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 Win32 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 (HGLOBAL 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--

BOOL  CWnd::OpenClipboard( );
     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)

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

HGLOBAL  ::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
 
HGLOBAL  ::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 

BOOL  ::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 CWnd::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 CWnd::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_MFC Example Program--

"Copy to Clipboard" menu item ==>
     Send uppercase alphabet to clipboard as text

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

"Clear Screen" menu item ==>
     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_MFC: An Example that Uses Multiple Clipboard Data Formats--

"Clipboard | Copy to Clipboard" menu item ==>
     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" menu item ==>
      Retrieve and display text from clipboard

"Clipboard | Get clipboard BMP" menu item ==>
     Retrieve and display bitmap image from clipboard

"Clipboard / Get Special Data" menu item ==>
     Retrieve and display custom-format data from clipboard

After using CLIP2_MFC "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 Word application and "Paste" ==>
     Gets text since
          Word considers CF_TEXT "preferable" to CF_BITMAP
     But use Word 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:

CWnd::OpenClipboard ( );
::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 ();
     }