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