13.1.2 Pasting Text from the Clipboard

An application can paste text from the clipboard into its client area. That is, it can retrieve a text handle from the clipboard and display it in the client area by using the TextOut function. To do this, the application must do the following:

1.Open the clipboard.

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

3.Close the clipboard.

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

case WM_INITMENU:

    if (wParam == (WPARAM) GetMenu(hwnd)) {
        if (OpenClipboard(hwnd)) {
            if (IsClipboardFormatAvailable(CF_TEXT)
                    || IsClipboardFormatAvailable(CF_OEMTEXT))
                EnableMenuItem((HMENU) wParam, IDM_PASTE, MF_ENABLED);

            else
                EnableMenuItem((HMENU) wParam, IDM_PASTE, MF_GRAYED);

            CloseClipboard();
            return TRUE;
        }

        else    /*  Clipboard is not available            */
            return FALSE;
    }

    return TRUE;

In this example, the first if statement checks the WM_INITMENU's wParam parameter 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.

The two calls to the IsClipboardFormatAvailable function check for the CF_TEXT or CF_OEMTEXT format. Based on whether the CF_TEXT or CF_OEMTEXT format is found, the EnableMenuItem function enables or disables the Paste command.

Your application must be able to paste from the clipboard when the user chooses the Paste command from the Edit menu. To make your application process the menu input and retrieve the text from the clipboard, add an IDM_PASTE case to the WM_COMMAND case in the window procedure. Add the following statements immediately after the IDM_COPY case:

    case IDM_PASTE:

        if (OpenClipboard(hwnd)) {
            if ((hClipData = GetClipboardData(CF_TEXT)) == NULL) {
                CloseClipboard();
                break;
            }

            if (hText != NULL)
                GlobalFree(hText);

            hText = GlobalAlloc(GMEM_MOVEABLE, GlobalSize(hClipData));

            if (hText == NULL ||
                    (lpClipData = GlobalLock(hClipData)) == NULL ||
                    (lpszText = GlobalLock(hText)) == NULL) {
                OutOfMemory();
                CloseClipboard();
                break;
            }

            lstrcpy(lpszText, lpClipData);
            GlobalUnlock(hClipData);
            CloseClipboard();
            GlobalUnlock(hText);
            EnableMenuItem(GetMenu(hwnd), IDM_CUT, MF_ENABLED);
            EnableMenuItem(GetMenu(hwnd), IDM_COPY, MF_ENABLED);

            /* Copy text to the application window. */

            InvalidateRect(hwnd, NULL, TRUE);
            UpdateWindow(hwnd);
            return TRUE;
        }

        else
            return FALSE;
}

break;

In this example, the OpenClipboard function opens the clipboard for the specified window if it is not already open. The GetClipboardData function then 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, because it is a global-memory handle. The clipboard format is CF_TEXT, so the global memory is assumed to contain a null-terminated string consisting of characters in the Windows character set. 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.

Your application must not modify or delete the data it retrieves from the clipboard. The application can examine it or make a copy of it, but it must not change the data. To examine the data, the application might need to lock the handle, as in this example, but must never leave a data handle locked. The application should unlock the handle 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. Do not rely on a handle remaining valid indefinitely. In general, the application should copy the data associated with the handle, and then release it without changes.

The CloseClipboard function closes the clipboard; your application 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.