Visual C++ Workshop
Session 7
R. Eckert

THE CLIPBOARD

Windows Clipboard--
     Provides common mechanism for getting data from app to app
     Can also be used for single-program cut and paste
     Commonly programs have "Edit" | "Cut", "Copy", "Paste" menu items
          "Cut" or "Copy"  transfer data to clipboard
          "Paste" gets data from clipboard
     A movable global memory block maintained by Windows
          Contents available to any running application
          Can be viewed with Windows CLIPBRD.EXE application
          Can only be accessed through a HANDLE
               Must use Win16 memory management functions:
                    GlobalAlloc()
                    GlobalLock()
                    GlobalUnlock()
                    GlobalFree()

A "Clipboard format" keeps track of type of data stored in Clipboard
     CF_TEXT for text data
     CF_BITMAP for bitmaps
     Lots of others
     Custom formats can be registered

Sending data to clipboard:
     Copy it into a global memory block
     Then transfer it to clipboard
          Block is "in clipboard"
          Windows controls it

Allocating and Using Global Memory Blocks (important functions)--

1. Get handle to block (HANDLE hMem):

     hMem = GlobalAlloc(allocation_flags, numbytes_to_allocate);

          allocation_flags: Bitwise OR of:
               GMEM_MOVEABLE, GMEM_ZEROINIT, & others
               Most common: GMEM_MOVEABLE|GMEM_ZEROINT
                    Also defined to be GHND 
          Returns handle to block 
               Used in subsequent calls to other clipboard 
          If unsuccessful, returns 0

2. Fix block in memory and get a pointer to it:

     pBlock = GlobalLock(hMem);

          Returned pointer used to read/write data from/to the memory block

3. After done accessing memory block, make it movable again

     GlobalUnlock(hMem);

          Block still exists, contents intact
          Pointer no longer valid
          Handle (hMem) can still be used to gain future access to block

4. Get rid of the block:

     GlobalFree(hMem);

          Releases it from memory
          No longer usable

CLIPBOARD FUNCTIONS--

OpenClipboard(hWnd);
     Opens Clipboard for access by program 
     Only one application can open clipboard at any given time
     Returns FALSE if unsuccessful
          Clipboard was not available
               (Probably being accessed by other application)

EmptyClipboard();
     Empties clipboard memory block
     Frees handle to data currently in clipboard
     Returns FALSE if unsuccessful

GetClipboardData(uFormat);
     Gets a handle to data in Clipboard
     uFormat parameter specifies data format
     Returns NULL if unsuccessful
          Clipboard didn't contain data in specified format
     Returned handle doesn't belong to app
          App must not free block, change its data, or leave it locked
          Copy to new block if app needs to manipulate data
 
SetClipboardData(uFormat, hData);
     Passes memory block whose handle is specified to clipboard
     Windows takes control of block
     App can read data, but must not free handle or leave it locked
     Returns handle to data if successful
     Usually EmptyClipboard() is called before using this function 

CloseClipboard();
     Closes clipboard so other programs can access it
     Returns FALSE if unsuccessful

Sending Data to the Clipboard (e.g., in Cut and Copy Operations)--

     1. Allocate and lock a global memory block
     2. Copy data into the global memory block
     3. Unlock the block
     4. Open the clipboard with OpenClipboard()
     5. Empty current contents of the clipboard with EmptyClipboard()
     6. Transfer the block to the Clipboard with SetClipboardData()
          (Windows now controls the block)
     7. Close the clipboard with CloseClipboard().
          (So other programs can access it)

Getting Data from the Clipboard (e.g., in Paste Operations)--
     
     1. Open the clipboard with OpenClipboard()
     2. Get a handle to the clipboard data with GetClipboardData()
     3. Allocate and lock a memory block to hold the clipboard data
     4. Lock the clipboard data block
     5. Copy data from the clipboard data block to the program's data block
          (The data can now be manipulated by the application)
     6. Unlock both memory blocks
     7. Close the clipboard with CloseClipboard()

Clipboard Data Formats--

Several predefined data types (See online help on Clipboard formats)

Custom formats can be created using RegisterClipboardFormat()

Only one memory block at a time in clipboard can have a given format
But there can be many blocks as long as each has a different format

IsClipboardFormatAvailable(uFormat)-- 
     Determines if specified data format is currently in clipboard
     Returns TRUE if so
     Can be used without opening clipboard
     Alternative to checking for NULL on call to GetClipboardData()

CLIP1 Example Program--



"Copy to Clipboard"
     Send uppercase alphabet to clipboard as text

"Get clipboard Text"
     Retrieve text data from clipboard, if available
     Output it to window's client area

"Clear Screen"
     Clear the client area.

Multiple Clipboard Data Formats--

Clipboard can hold one block of data for each clipboard format
Could represent different ways of saving same basic data
     e.g., Microsoft Word: 
          text, rich text format, Word format, Wordperfect format, html, etc. 
App using clipboard can check each format stored
     See if data is as expected 
     Or choose format it can work with "best"

CLIP2: An Example that Uses Multiple Clipboard Data Formats--



"Clipboard | Copy to Clipboard"
     Three types of data sent to clipboard: 
          Some text using CF_TEXT format
          A bitmap image using CF_BITMAP format
          Some custom-format data

"Clipboard | Get clipboard Text"
     Retrieve and display text from clipboard

"Clipboard | Get clipboard BMP"
     Retrieve and display bitmap image from clipboard

"Clipboard / Get Special Data"
     Retrieve and display custom-format data from clipboard


After using CLIP2 "Copy to Clipboard", try the following:

1. Use Windows Notepad and "Paste"
     Gets text since Notepad supports only CF_TEXT format

2. Use Windows Paint application and "Paste"
     Gets bitmap since Paint reads and writes CF_BITMAP

3. Use Windows WordPad application and "Paste"
     Get text since
          WordPad considers CF_TEXT "preferable" to CF_BITMAP
     But use WordPad and select "Paste Special"
          Can choose either text or bitmap


Delayed Rendering of Clipboard Data--

Many clipboard data formats
     Memory space could be wasted if all formats are sent to clipboard
App can "send" data without including the data
     Send just the format
     Pass NULL as data block handle in SetClipboardData()
          Windows "remembers" active window handle when clipboard opened   
          Subsequent clipboard read attempts
               App's WndProc() must provide data of specified type

For example, data supplier program does the following:

OpenClipboard (hWnd);
EmptyClipboard ();
SetClipboardData (CF_TEXT, 0)  // delayed rendering of CF_TEXT data
CloseClipboard();

When any app subsequently tries to read clipboard, the following occurs:

     The app requests CF_TEXT data with GetClipboardData()
     Windows recognizes that CF_TEXT data must be loaded
     Windows sends WM_RENDERFORMAT msg to data supplier
          wParam = clipboard format code
     Suppler program's WndProc() calls SetClipboardData() again
          This time, sending the data (handle)
     Windows passes handle to app requesting the data

But what if data supplier program terminates before data is requested?

Windows sends supplier program  a WM_RENDERALLFORMATS msg      
     Sent before it terminates
     Program responds by sending blocks with data of all formats it supports


Using the Clipboard with an Edit Control--

Edit controls have built-in cut-and-paste capability for selected text 
User selects text in edit control by dragging mouse cursor over text 
     (or by using  <Shift>-arrow keys)
Selected text is highlighted
It can be cut or copied to clipboard:
     Just send edit control WM_CUT or WM_COPY message

Example: Copy currently-selected text in edit control with handle hEdWin--

     SendMessage (hEdWin, WM_COPY, 0, 0);

     wParam and lParam are not used
     Edit control receives this message
          Selected text is copied to clipboard using CF_TEXT format

Pasting text from the clipboard to an edit control--
    Send edit control a WM_PASTE message

    SendMessage (hEdWin, WM_PASTE, 0, 0);

     If there's clipboard contains text, it's inserted into edit control
     at position of blinking caret

Cutting text (removing it) from edit control to clipboard--
    Send edit control a WM_CUT message:

    SendMessage (hEdWin, WM_CUT, 0, 0);

Deleting text from edit control by cutting it and emptying clipboard:

     SendMessage (hEditWin, WM_CUT, 0, 0);
     if (OpenClipboard (hWnd)
     {
          EmptyClipboard ();
          CloseClipboard ();
     }