Pasting Text from the Clipboard

You can paste text from the clipboard into your client area. That is, you can retrieve a text handle from the clipboard and display it in the client area by using the TextOut function. To do this you will need to do the following:

1.Open the clipboard.

2.Retrieve the data handle associated with CF_TEXT or CF_OEMTEXT.

3.Close the clipboard.

Summary: Disable the Paste command when the clipboard is empty.

You should let the user paste only if there is text in the clipboard. To prevent attempts to paste when no text is present, check the clipboard before Windows displays the Edit menu by processing the WM_INITMENU message. If the clipboard is empty, disable the Paste command; if text is present, enable it. Add the following statements to the window function:

case WM_INITMENU:

1 if (wParam == hEditMenu) {

if (OpenClipboard(hWnd)) {

2 if (IsClipboardFormatAvailable(CF_TEXT)

|| IsClipboardFormatAvailable(CF_OEMTEXT))

3 EnableMenuItem(wParam, IDM_PASTE, MF_ENABLED);

else

EnableMenuItem(wParam, IDM_PASTE, MF_GRAYED);

CloseClipboard();

return (TRUE);

}

else /* Clipboard is not available */

return (FALSE);

}

In this example:

1 The first if statement checks the wParam parameter of WM_INITMENU against the menu handle returned by the GetMenu function. Since many applications have at least two menus, including a System menu, it is important to ensure that the message applies to the Edit menu.
2 The two calls to the IsClipboardFormatAvailable function check for the CF_TEXT or CF_OEMTEXT format.
3 The EnableMenuItem function enables or disables the Paste command based on whether the CF_TEXT or CF_OEMTEXT format is found.

You can paste from the clipboard when the user chooses the Paste command from the Edit menu. To process the menu input and retrieve the text from the clipboard, add an IDM_PASTE case to the WM_COMMAND case in the window function. Add the following statements immediately after the IDM_COPY case:

case IDM_PASTE:

1 if (OpenClipboard(hWnd)) {

/* get text from the clipboard */

2 if (!(hClipData = GetClipboardData(CF_TEXT))) {

CloseClipboard();

break;

}

3 if (!(lpClipData = GlobalLock(hClipData))) {

OutOfMemory();

CloseClipboard();

break;

}

4 hDC = GetDC(hWnd);

TextOut(hDC, 10, 10, lpClipData);

ReleaseDC(hWnd, hDC);

GlobalUnlock(hClipData);

CloseClipboard();

}

break;

In this example:

1 The OpenClipboard function opens the clipboard for the specified window if it is not already open.
2 The GetClipboardData function retrieves the data handle for the text; if there is no such data, the function retrieves zero. You should check this handle before using it.
3 The GetClipboardData function returns a handle to global memory. Because the clipboard format is CF_TEXT, the global memory is assumed to contain a null-terminated ANSI string. This means the global memory can be locked by using the GlobalLock function, and the contents can be displayed in the client area by using the TextOut function.
4 So that you will be able to see that your application has copied the contents of the clipboard, the TextOut function writes to the coordinates (10, 10) in your client area. You will need a display context to use TextOut, so the GetDC function is required; and since you must release a display context immediately after using it, the ReleaseDC function is also required.

This method of displaying the text in the client area is for illustration only. Since the application does not save the content of the string, there is no way to repaint the text if the client-area background is erased, such as during processing of a WM_PAINT message. (The ClipText sample application, described later in this chapter, demonstrates one method of saving text so that the client-area display can be redrawn.)

You must not modify or delete the data you have retrieved from the clipboard. You can examine it or make a copy of it, but you must not change it. To examine the data, you might need to lock the handle, as in this example, but you must never leave a data handle locked. Unlock it immediately after using it.

Data handles returned by the GetClipboardData function are for temporary use only. Handles belong to the clipboard, not to the application requesting data. Accordingly, handles should not be freed and should be unlocked immediately after they are used. The application should not rely on the handle remaining valid indefinitely. In general, the application should copy the data associated with the handle, then release it without changes.

The CloseClipboard function closes the clipboard; you should always close the clipboard immediately after it has been used so that other applications can use it. Before closing the clipboard, be sure you unlock the data retrieved by GetClipboardData.