13.3.4 Modifying the WM_COMMAND Case

To process the Edit menu commands, you must modify the IDM_CUT, IDM_COPY, and IDM_PASTE cases in the WM_COMMAND case. The IDM_CUT and IDM_COPY cases must create a global memory object, fill it with text, and copy the handle of the object to the clipboard; the IDM_CUT case must also discard the current client-area text. The IDM_PASTE case must retrieve a handle from the clipboard, use its contents to replace the current client-area text, and request that the client area be repainted.

Replace the existing IDM_CUT and IDM_COPY cases with the following statements:

case IDM_CUT:
case IDM_COPY:

    if (hText != NULL) {

        /* Allocate memory and copy the string to it. */

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

        if (hData == NULL  ||
                (lpData = GlobalLock(hData)) == NULL ||
                (lpszText = GlobalLock(hText)) == NULL) {
            OutOfMemory();
            return TRUE;
        }

        lstrcpy(lpData, lpszText);
        GlobalUnlock(hData);
        GlobalUnlock(hText);

        /*
         * Clear the current contents of the clipboard,
         * and set the data handle to the new string.
         */

        if (OpenClipboard(hwnd)) {
            EmptyClipboard();
            SetClipboardData(CF_TEXT, hData);
            CloseClipboard();
        }

        hData = NULL;






        if (wParam == IDM_CUT) {
            GlobalFree(hText);
            hText = NULL;
            EnableMenuItem(GetMenu (hwnd), IDM_CUT, MF_GRAYED);
            EnableMenuItem(GetMenu(hwnd), IDM_COPY, MF_GRAYED);
            InvalidateRect(hwnd, NULL, TRUE);
            UpdateWindow(hwnd);
        }
    }

    return TRUE;

The GlobalAlloc function allocates the global memory object used to pass text data to the clipboard. The lstrcpy function copies the client-area text into the object after the handle has been locked by the GlobalLock function. The handle must be unlocked before it can be copied to the clipboard. The EmptyClipboard function is used to remove any existing data from the clipboard.

Replace the IDM_PASTE case with the following statements:

    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;

The GetClipboardData function returns a handle of a global memory object. The GlobalLock function locks this handle, returning the object address that is used to make a copy of the new client-area text.