PMGuide - Clipboards: Difference between revisions
Created page with "{{IBM-Reprint}} {{PMGuide}} The clipboard is a small amount of system-managed random-access memory (RAM) used for user-driven data exchange. This is in contrast with dynamic d..." |
No edit summary |
||
Line 207: | Line 207: | ||
│ │of the clipboard viewer). │ | │ │of the clipboard viewer). │ | ||
└────────────────────┴────────────────────────────────────────┘ | └────────────────────┴────────────────────────────────────────┘ | ||
</PRE> | |||
An application automatically loses ownership of the clipboard when the clipboard data is cleared by the WinEmptyClipbrd function. Ownership is necessary only when data is present on the clipboard. Typically, an application loses ownership when another application places data on the clipboard. | |||
==Using the Clipboard== | ==Using the Clipboard== | ||
You can use the clipboard functions to perform the following tasks: | You can use the clipboard functions to perform the following tasks: | ||
Line 323: | Line 324: | ||
</PRE> | </PRE> | ||
Responding to WM_DRAWCLIPBOARD Message | Responding to WM_DRAWCLIPBOARD Message | ||
[[Category:PMGuide]] |
Revision as of 17:01, 19 May 2024
Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation
The clipboard is a small amount of system-managed random-access memory (RAM) used for user-driven data exchange. This is in contrast with dynamic data exchange (DDE), which is application driven. While the clipboard stores only pointers or handles to data, its associated set of functions can be used in applications to move and exchange data. This chapter describes how to use the clipboard in PM applications.
About the Clipboard
The clipboard enables the user to move data in a single application or exchange data between applications. Typically, a user selects data in the application using the mouse or keyboard, and then initiates a cut, copy, or paste operation on that selection.
Descriptions of these operations are in the following table:
┌───────────────┬─────────────────────────────────────────────┐ │Operation │Description │ ├───────────────┼─────────────────────────────────────────────┤ │Cut │Deletes the selected data from the │ │ │application and copies it to the clipboard. │ │ │Any previous contents of the clipboard are │ │ │destroyed. │ ├───────────────┼─────────────────────────────────────────────┤ │Copy │Copies the selected data to the clipboard. │ │ │The selection remains unchanged. Previous │ │ │contents of the clipboard are destroyed. │ ├───────────────┼─────────────────────────────────────────────┤ │Paste │Deletes the selected data from the │ │ │application and replaces it with the contents│ │ │of the clipboard. The contents of the │ │ │clipboard are not changed. │ └───────────────┴─────────────────────────────────────────────┘
An application should not perform any clipboard operations unless the user initiates them explicitly. Other OS/2 features, such as pipes, queues, shared memory, and especially DDE should be used when data exchange is needed without user involvement. For example, an application that continuously passes remotely collected data to a data-analysis application must not use the clipboard. Such an application, instead, should use the other interprocess data-communication capabilities of the operating system.
The data on the clipboard is maintained in memory only. Clipboard data is lost when the computer is turned off.
An application must store, in shared memory, text data that is destined for the clipboard. To do so, the application calls the DosAllocSharedMem function with the OBJ_GIVEABLE attribute to allocate a shared memory object, and then copies the text data to the object. The application passes the clipboard a pointer, which the clipboard uses to access the shared memory object. Clipboard functions use the CFI_POINTER flag to indicate text data stored in a shared memory object.
To pass a bit map or metafile to the clipboard, an application passes the clipboard a bit map or metafile handle. The clipboard functions make the bit map or metafile shareable. The CFI_HANDLE flag is used in clipboard functions to indicate bit map or metafile data.
After closing the clipboard, an application no longer can access the data it passed to the clipboard. Likewise, when an application requests data from the clipboard, it receives a pointer or handle that is good only until the application closes the clipboard. Typically, the application either uses the data immediately before closing the clipboard, or it copies the data to local memory for future use, then closes the clipboard.
Clipboard Operations
An application uses the clipboard when cutting, copying, or pasting data. Typically, an application places data on the clipboard for cut and copy operations and removes data from the clipboard for paste operations. The following paragraphs describe all these clipboard operations.
Cut and Copy Operations
To put data on the clipboard, an application first calls the WinOpenClipbrd function to verify that other applications are not trying to retrieve or set clipboard data. The WinOpenClipbrd function does not return if another thread has the clipboard open; it waits until either the clipboard is free or there is a message in the message queue of the calling thread. In practice, the WinOpenClipbrd function waits until the clipboard is available or until the calling application responds to a message. If the clipboard cannot be opened before a message arrives, the application receives the message, and the WinOpenClipbrd function continues to try to open the clipboard. The WinOpenClipbrd function does not return until the clipboard is open. However, the application continues to receive messages.
Once an application successfully opens the clipboard, it must remove any previously stored data on the clipboard by calling the WinEmptyClipbrd function. If the clipboard is not cleared, writing an existing format on the clipboard replaces the old data in that format with the new data. Old data in other formats remains on the clipboard.
After emptying the clipboard, an application should write its data to the clipboard in as many standard formats as possible. For each format, the application passes the data to the clipboard by calling the WinSetClipbrdData function, specifying each data format. The clipboard is not cleared when a new format is written to it; all new data formats coexist on the clipboard until it is cleared by the next clipboard user.
If an application passes NULL as the ulData parameter of the WinSetClipbrdData function, applications must render the data on request.
Finally, when an application finishes writing the clipboard data, it must release the clipboard by calling the WinCloseClipbrd function so that other applications can use the clipboard.
Paste Operation
To retrieve data from the clipboard, an application first must call the WinOpenClipbrd function to verify that no other applications are trying to retrieve or set the clipboard data.
Once an application successfully opens the clipboard, it calls the WinQueryClipbrdData function, specifying a preferred format. If that format is not available (indicated by a NULL return from the WinQueryClipbrdData function) the application should continue to call WinQueryClipbrdData for other possible formats until it either receives the data or runs out of format choices.
If the clipboard contains one of the requested formats, the WinQueryClipbrdData function returns a 32-bit integer, the meaning of which depends on the particular format. For text data, the return value is a pointer to a shareable memory object containing the text. For bit map data, the return value is a bit map handle. For metafile data, the return value is a metafile handle.
It is important that an application use the WinCloseClipbrd function to close the clipboard as soon as possible so that other applications can access it.
Standard Clipboard-Data Formats
The clipboard can accept data in three standard formats: text, bit map, and metafile. Applications can either use these formats or create their own private formats.
All PM applications can access the clipboard, so applications can copy to the clipboard the same selection of data in many different formats. For example, a word processor that supports multiple fonts might write the same selection of text to the clipboard in three different formats: straight text, rich text, and metafile. Then, another application (pasting from the clipboard) could choose the appropriate format.
Applications can use the following constants to specify the standard clipboard-data formats:
┌───────────────┬─────────────────────────────────────────────┐ │Format │Description │ ├───────────────┼─────────────────────────────────────────────┤ │CF_BITMAP │Specifies that the data in the clipboard is a│ │ │bit map. │ ├───────────────┼─────────────────────────────────────────────┤ │CF_DSPBITMAP │Specifies that the data in the clipboard is a│ │ │bit map representation of a private-data │ │ │format. The clipboard viewer uses this │ │ │format to display a private format. │ ├───────────────┼─────────────────────────────────────────────┤ │CF_DSPMETAFILE │Specifies that the data in the clipboard is a│ │ │metafile representation of a private-data │ │ │format. The clipboard viewer uses this │ │ │format to display a private format. │ ├───────────────┼─────────────────────────────────────────────┤ │CF_DSPTEXT │Specifies that the data in the clipboard is a│ │ │text representation of a private-data format.│ │ │The clipboard viewer uses this format to │ │ │display a private format. │ ├───────────────┼─────────────────────────────────────────────┤ │CF_METAFILE │Specifies that the data in the clipboard is a│ │ │metafile. │ ├───────────────┼─────────────────────────────────────────────┤ │CF_TEXT │Specifies that the data in the clipboard is │ │ │an array of text characters. These │ │ │characters can include newline characters to │ │ │indicate line breaks. The NULL character │ │ │indicates the end of the text data. │ └───────────────┴─────────────────────────────────────────────┘
Private Clipboard-Data Formats
Applications that use the clipboard to move data within the documents of the application can use private clipboard-data formats when standard formats are insufficient for representing clipboard data. For example, a word processor might have a rich-text format that contains font and style information in addition to the usual text characters. Clearly, if the word processor uses the clipboard to support cut, copy, and paste operations for moving data in its documents, a standard text format will be inadequate.
In such case, the word processor should write at least two formats to the clipboard for each cut or copy operation: a standard text format representing the text of the current selection and a private rich-text format representing the true state of the selection. If the word processor performs a paste operation by using clipboard data, it can use the rich-text format to retain all formatting. If another application requests the same data, it can use the standard-text format if it does not recognize the private format. Also, the word processor should be able to render data in CF_BITMAP and CF_METAFILE formats for painting and drawing applications.
Format Identification Number
Each private format must have a unique identification number. To obtain an identification number, the application registers the name of the private format in the system atom table. The system assigns a unique identification number for the format name. Other applications having access to the format name can query the system atom table for the format identification number.
An application can interpret its own private formats and request them from the clipboard for cutting and pasting its own data. Other applications that know the private-format identification number also can interpret the formatted data.
Display Formats
The OS/2 operating system provides three standard display formats for applications that use private formats: CF_DSPTEXT, CF_DSPBITMAP, and CF_DSPMETAFILE. These formats correspond to the standard text, bit map, and metafile formats, with the exception that they are intended for use only by the clipboard viewer. An application that uses a private format should write one of the DSP formats that approximates the appearance of the private data so that the clipboard viewer can display the data regardless of the format. For example, a word processor using the rich-text format also would write a CF_DSPBITMAP formatted picture of the selected text that contains all the type fonts and styles.
Notice that you can choose delayed rendering for DSP formats because there might not always be a clipboard viewer active on the screen. With delayed rendering, an application actually does not render the format unless it is requested to do so.
Delayed Rendering
An application can pass NULL as the ulData parameter of the WinSetClipbrdData function instead of a pointer or a handle. This indicates that the data is rendered only when another application requests it from the clipboard. This is useful if an application supports several clipboard formats that are time-consuming to render. With delayed rendering, an application can send NULL handles for each clipboard format that it supports and render individual formats only when the format actually is requested from the clipboard. An application can either write data for standard formats or choose delayed rendering for more complex formats.
When an application uses delayed rendering for one or more of its clipboard formats, it must become the clipboard owner. As long as the application is the clipboard owner, it receives a WM_RENDERFMT message whenever a request is received by the clipboard for a format using delayed rendering. When the application receives such a message, it renders the data and passes the pointer or handle to the clipboard by calling the WinSetClipbrdData function. The rules for shared-memory access for rendered data are the same as those for standard clipboard data. This simply is a delayed execution of the operation that occurs if the data does not have delayed rendering.
The clipboard owner, with one or more delayed-rendering formats on the clipboard, receives a WM_RENDERALLFMTS message just before the clipboard-owner application terminates. This ensures that the application renders all of its data before terminating.
Clipboard Viewer
A window can become a clipboard viewer and display the current contents of the clipboard. The clipboard viewer is informed whenever the clipboard contents change. Typically, the clipboard viewer is a window that can draw the standard clipboard formats. The clipboard viewer is a convenience for the user; it does not have any effect on the data-transaction functions of the clipboard.
To create a clipboard viewer, an application calls WinSetClipbrdViewer, specifying the window in which the clipboard data will be displayed. Usually this is the client window of an application. There can be only one clipboard viewer at any time in the system, so setting a clipboard viewer replaces any previous clipboard viewer. The WinQueryClipbrdViewer function receives the handle to the current clipboard viewer so that the application can reset it when finished with the clipboard viewer.
Once a window becomes the clipboard viewer, it receives WM_DRAWCLIPBOARD messages whenever the contents of the clipboard change. The window should respond to these messages by drawing the contents of the clipboard.
The clipboard viewer displays all the standard formats and should process CFI_OWNERDISPLAY items by sending the appropriate message to the clipboard owner.
The clipboard viewer cannot display private-format data. For this reason, an application that writes private-format data to the clipboard also must write the data in one of the three standard-display formats: CF_DSPTEXT, CF_DSPBITMAP, or CF_DSPMETAFILE.
If a standard format is not provided in addition to the private formats, the clipboard owner must draw the clipboard data in the clipboard-viewer window. An application uses the CFI_OWNERDRAW flag to identify clipboard data that the clipboard owner draws. When the clipboard viewer encounters data with the CFI_OWNERDRAW flag set, it sends WM_PAINTCLIPBOARD messages to the clipboard owner whenever the data must be drawn, scrolled, or sized.
The clipboard viewer determines the attributes of a particular clipboard format by calling the WinQueryClipbrdFmtInfo function. The identity of the current owner is found by calling the WinQueryClipbrdOwner function.
Clipboard Owner
The clipboard owner is any application window connected to the clipboard data. Following are situations in which an application would call WinSetClipbrdOwner to become the clipboard owner:
- The application calling WinSetClipbrdData passes a NULL pointer or handle to the clipboard, indicating that the application renders the data in a particular format on request. As a result, the system sends rendering requests to the current clipboard owner.
- The application calling WinSetClipbrdData passes data with the CFI_OWNERFREE attribute, indicating that the application frees memory for data when the clipboard is emptied. As a result, the system sends owner-free requests to the current clipboard owner.
- The application calling WinSetClipbrdData passes data with the CFI_OWNERDISPLAY attribute, indicating that the owner application draws the data in the clipboard viewer. As a result, the clipboard viewer sends drawing-related requests to the current clipboard owner.
The window specified in the call to the WinSetClipbrdOwner function responds to the following messages:
┌────────────────────┬────────────────────────────────────────┐ │Message │Description │ ├────────────────────┼────────────────────────────────────────┤ │WM_RENDERFMT │Sent by the system to the clipboard │ │ │owner when a particular format with │ │ │delayed rendering must be rendered. The│ │ │receiver must render the data in the │ │ │specified format and pass it to the │ │ │clipboard by calling the │ │ │WinSetClipbrdData function. │ ├────────────────────┼────────────────────────────────────────┤ │WM_RENDERALLFMTS │Sent by the system to the clipboard │ │ │owner just before the owner application │ │ │terminates. The receiver must render │ │ │the clipboard data in all formats on the│ │ │clipboard with delayed rendering. It │ │ │must pass the data for each format to │ │ │the clipboard by calling the │ │ │WinSetClipbrdData function. │ ├────────────────────┼────────────────────────────────────────┤ │WM_DESTROYCLIPBOARD │Sent by the system to the clipboard │ │ │owner when the clipboard is cleared by │ │ │another application calling the │ │ │WinEmptyClipbrd function. The receiver │ │ │must free the memory occupied by any │ │ │clipboard formats using the │ │ │CFI_OWNERFREE attribute. │ ├────────────────────┼────────────────────────────────────────┤ │WM_SIZECLIPBOARD │Sent by the clipboard viewer to the │ │ │clipboard owner when the clipboard │ │ │contains the data handle with the │ │ │CFI_OWNERDISPLAY attribute and when the │ │ │clipboard-viewer changes size. When the│ │ │clipboard viewer is being destroyed or │ │ │reduced to an icon, this message is sent│ │ │with the coordinates of the opposite │ │ │corners set to (0,0), which permits the │ │ │owner to free its display resources. │ ├────────────────────┼────────────────────────────────────────┤ │WM_VSCROLLCLIPBOARD │Sent by the clipboard viewer to the │ │ │clipboard owner when the clipboard │ │ │contains data with the CFI_OWNERDISPLAY │ │ │attribute and when an event occurs in │ │ │the clipboard-viewer scroll bars. The │ │ │receiver must respond to this message by│ │ │scrolling the image, invalidating the │ │ │appropriate area of the clipboard │ │ │viewer, and updating the slider │ │ │position. │ ├────────────────────┼────────────────────────────────────────┤ │WM_HSCROLLCLIPBOARD │Sent by the clipboard viewer to the │ │ │clipboard owner when the clipboard │ │ │contains data with the CFI_OWNERDISPLAY │ │ │attribute and when an event occurs in │ │ │the scroll bars of the clipboard viewer.│ │ │The receiver must respond to this │ │ │message by scrolling the image, │ │ │invalidating the appropriate area of the│ │ │clipboard viewer, and updating the │ │ │slider position. │ ├────────────────────┼────────────────────────────────────────┤ │WM_PAINTCLIPBOARD │Sent by the clipboard viewer to the │ │ │clipboard owner when the clipboard │ │ │contains data with the CFI_OWNERDISPLAY │ │ │attribute and when the clipboard-viewer │ │ │client area needs repainting. The │ │ │receiver must respond to this message by│ │ │painting the requested format (by │ │ │calling WinGetPS for the window handle │ │ │of the clipboard viewer). │ └────────────────────┴────────────────────────────────────────┘
An application automatically loses ownership of the clipboard when the clipboard data is cleared by the WinEmptyClipbrd function. Ownership is necessary only when data is present on the clipboard. Typically, an application loses ownership when another application places data on the clipboard.
Using the Clipboard
You can use the clipboard functions to perform the following tasks:
- Put data on the clipboard
- Retrieve data from the clipboard
- View data on the clipboard
Putting Data on the Clipboard
The following code fragment shows how an application places text data on the clipboard, how it opens the clipboard, copies the text to a shared memory object, empties the clipboard, and passes the pointer to the clipboard:
#define MAXSTR 1024 PSZ pszSrc, pszDest; BOOL fSuccess; CHAR szClipString[MAXSTR]; HAB hab; . . /* Get character string (szClipString). */ . if (WinOpenClipbrd(hab)) { /* Allocate a shared memory object for the text data. */ if (!(fSuccess = DosAllocSharedMem( (PVOID)&pszDest, /* Pointer to shared memory object */ NULL, /* Use unnamed shared memory */ strlen(szClipString)+1,/* Amount of memory to allocate */ PAG_WRITE | /* Allow write access */ PAG_COMMIT | /* Commit the shared memory */ OBJ_GIVEABLE))) { /* Make pointer giveable */ /* Set up the source pointer to point to text. */ pszSrc = szClipString; /* Copy the string to the allocated memory. */ while (*pszDest++ = *pszSrc++); /* Clear old data from the clipboard. */ WinEmptyClipbrd(hab); /* * Pass the pointer to the clipboard in CF_TEXT format. Notice * that the pointer must be a ULONG value. */ fSuccess = WinSetClipbrdData(hab, /* Anchor-block handle */ (ULONG) pszDest, /* Pointer to text data */ CF_TEXT, /* Data is in text format */ CFI_POINTER); /* Passing a pointer */ /* Close the clipboard. */ WinCloseClipbrd(hab); } }
Retrieving Data from the Clipboard
The following code fragment shows how to open the clipboard, retrieve data in the requested format, copy the data to local memory, and close the clipboard:
PSZ pszClipText, pszLocalText; if (WinOpenClipbrd(hab)) { if (pszClipText = (PSZ) WinQueryClipbrdData(hab, CF_TEXT)) { /* Copy text from the shared memory object to local memory. */ while (*pszLocalText++ = *pszClipText++); } WinCloseClipbrd(hab); }
Viewing Data on the Clipboard
The following code fragment shows how a sample clipboard viewer responds to the WM_DRAWCLIPBOARD message, drawing text and bit map data in its window. Notice that the code uses the data retrieved from the clipboard before closing the clipboard. An alternative strategy is to copy the data and then close the clipboard. In any case, the original data from the clipboard cannot be used after the clipboard is closed.
PSZ pszText; HPS hps; RECTL rcl; HBITMAP hBitmap; POINTL ptlDest; case WM_DRAWCLIPBOARD: if (!WinOpenClipbrd(hab)) return 0; hps = WinGetPS(hwnd); /* Get a presentation space for drawing */ WinQueryWindowRect(hwnd, &rcl);/* Get dimensions of the window */ if (pszText =(PSZ)WinQueryClipbrdData(hab, CF_TEXT)) { WinDrawText(hps, -1, /* Null-terminated string */ pszText, /* The string */ &rcl, /* Where to put the string */ CLR_BLACK, /* Foreground color */ CLR_WHITE, /* Background color */ DT_CENTER | DT_VCENTER | DT_ERASERECT); } else if (hBitmap = (HBITMAP)WinQueryClipbrdData(hab, CF_BITMAP)) { ptlDest.x = ptlDest.y = 0; WinFillRect(hps, &rcl, CLR_WHITE); WinDrawBitmap(hps, hBitmap, NULL, /* Draws entire bit map */ &ptlDest, /* Destination */ CLR_BLACK, /* Foreground color */ CLR_WHITE, /* Background color */ DBM_NORMAL); /* Bit map flags */ } /* Remove rectangle from the update region */ WinValidateRect(hwnd, &rcl, FALSE); WinReleasePS(hps); /* Release the presentation space.*/ WinCloseClipbrd(hab); /* Close the clipboard. */ return 0;
Responding to WM_DRAWCLIPBOARD Message