Example of a Clipboard Viewer

The following example shows a simple clipboard viewer application.

HINSTANCE hinst;

UINT uFormat = (UINT)(-1);

BOOL fAuto = TRUE;

LRESULT APIENTRY MainWndProc(hwnd, uMsg, wParam, lParam)

HWND hwnd;

UINT uMsg;

WPARAM wParam;

LPARAM lParam;

{

static HWND hwndNextViewer;

HDC hdc;

HDC hdcMem;

PAINTSTRUCT ps;

LPPAINTSTRUCT lpps;

RECT rc;

LPRECT lprc;

HGLOBAL hglb;

LPSTR lpstr;

HBITMAP hbm;

HENHMETAFILE hemf;

HWND hwndOwner;

switch (uMsg)

{

case WM_PAINT:

hdc = BeginPaint(hwnd, &ps);

// Branch depending on the clipboard format.

switch (uFormat)

{

case CF_OWNERDISPLAY:

hwndOwner = GetClipboardOwner();

hglb = GlobalAlloc(GMEM_DDESHARE,

sizeof(PAINTSTRUCT));

lpps = GlobalLock(hglb);

memcpy(lpps, &ps, sizeof(PAINTSTRUCT));

GlobalUnlock(hglb);

SendMessage(hwndOwner, WM_PAINTCLIPBOARD,

(WPARAM) hwnd, (LPARAM) hglb);

GlobalFree(hglb);

break;

case CF_BITMAP:

hdcMem = CreateCompatibleDC(hdc);

if (hdcMem != NULL)

{

if (OpenClipboard(hwnd))

{

hbm = (HBITMAP)

GetClipboardData(uFormat);

SelectObject(hdcMem, hbm);

GetClientRect(hwnd, &rc);

BitBlt(hdc, 0, 0, rc.right, rc.bottom,

hdcMem, 0, 0, SRCCOPY);

CloseClipboard();

}

DeleteDC(hdcMem);

}

break;

case CF_TEXT:

if (OpenClipboard(hwnd))

{

hglb = GetClipboardData(uFormat);

lpstr = GlobalLock(hglb);

GetClientRect(hwnd, &rc);

DrawText(hdc, lpstr, -1, &rc, DT_LEFT);

GlobalUnlock(hglb);

CloseClipboard();

}

break;

case CF_ENHMETAFILE:

if (OpenClipboard(hwnd))

{

hemf = GetClipboardData(uFormat);

GetClientRect(hwnd, &rc);

PlayEnhMetaFile(hdc, hemf, &rc);

CloseClipboard();

}

break;

case 0:

GetClientRect(hwnd, &rc);

DrawText(hdc, "The clipboard is empty.", -1,

&rc, DT_CENTER | DT_SINGLELINE |

DT_VCENTER);

break;

default:

GetClientRect(hwnd, &rc);

DrawText(hdc, "Unable to display format.", -1,

&rc, DT_CENTER | DT_SINGLELINE |

DT_VCENTER);

}

EndPaint(hwnd, &ps);

break;

case WM_SIZE:

if (uFormat == CF_OWNERDISPLAY)

{

hwndOwner = GetClipboardOwner();

hglb = GlobalAlloc(GMEM_DDESHARE, sizeof(RECT));

lprc = GlobalLock(hglb);

GetClientRect(hwnd, lprc);

GlobalUnlock(hglb);

SendMessage(hwndOwner, WM_SIZECLIPBOARD,

(WPARAM) hwnd, (LPARAM) hglb);

GlobalFree(hglb);

}

break;

case WM_CREATE:

// Add the window to the clipboard viewer chain.

hwndNextViewer = SetClipboardViewer(hwnd);

break;

case WM_CHANGECBCHAIN:

// If the next window is closing, repair the chain.

if ((HWND) wParam == hwndNextViewer)

hwndNextViewer = (HWND) lParam;

// Otherwise, pass the message to the next link.

else if (hwndNextViewer != NULL)

SendMessage(hwndNextViewer, uMsg, wParam, lParam);

break;

case WM_DESTROY:

ChangeClipboardChain(hwnd, hwndNextViewer);

PostQuitMessage(0);

break;

case WM_DRAWCLIPBOARD: // clipboard contents changed.

// Update the window by using Auto clipboard format.

SetAutoView(hwnd);

// Pass the message to the next window in clipboard

// viewer chain.

SendMessage(hwndNextViewer, uMsg, wParam, lParam);

break;

case WM_INITMENUPOPUP:

if (!HIWORD(lParam))

InitMenu(hwnd, (HMENU) wParam);

break;

case WM_COMMAND:

switch (LOWORD(wParam))

{

case IDM_EXIT:

DestroyWindow(hwnd);

break;

case IDM_AUTO:

SetAutoView(hwnd);

break;

default:

fAuto = FALSE;

uFormat = LOWORD(wParam);

InvalidateRect(hwnd, NULL, TRUE);

}

break;

default:

return DefWindowProc(hwnd, uMsg, wParam, lParam);

}

return (LRESULT) NULL;

}

void WINAPI SetAutoView(HWND hwnd)

{

static UINT auPriorityList[] = {

CF_OWNERDISPLAY,

CF_TEXT,

CF_ENHMETAFILE,

CF_BITMAP

};

uFormat = GetPriorityClipboardFormat(auPriorityList, 4);

fAuto = TRUE;

InvalidateRect(hwnd, NULL, TRUE);

UpdateWindow(hwnd);

}

void WINAPI InitMenu(HWND hwnd, HMENU hmenu)

{

UINT uFormat;

char szFormatName[80];

LPCSTR lpFormatName;

UINT fuFlags;

UINT idMenuItem;

// If a menu is not the display menu, no initialization is necessary.

if (GetMenuItemID(hmenu, 0) != IDM_AUTO)

return;

// Delete all menu items except the first.

while (GetMenuItemCount(hmenu) > 1)

DeleteMenu(hmenu, 1, MF_BYPOSITION);

// Check or uncheck the Auto menu item.

fuFlags = fAuto ? MF_BYCOMMAND | MF_CHECKED :

MF_BYCOMMAND | MF_UNCHECKED;

CheckMenuItem(hmenu, IDM_AUTO, fuFlags);

// If there are no clipboard formats, return.

if (CountClipboardFormats() == 0)

return;

// Open the clipboard.

if (!OpenClipboard(hwnd))

return;

// Add a separator and then a menu item for each format.

AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);

uFormat = EnumClipboardFormats(0);

while (uFormat)

{

// Call an application-defined function to get the name

// of the clipboard format.

lpFormatName = GetPredefinedClipboardFormatName(uFormat);

// For registered formats, get the registered name.

if (lpFormatName == NULL)

{

if (GetClipboardFormatName(uFormat, szFormatName,

sizeof(szFormatName)))

lpFormatName = szFormatName;

else

lpFormatName = "(unknown)";

}

// Add a menu item for the format. For displayable

// formats, use the format ID for the menu ID.

if (IsDisplayableFormat(uFormat))

{

fuFlags = MF_STRING;

idMenuItem = uFormat;

}

else

{

fuFlags = MF_STRING | MF_GRAYED;

idMenuItem = 0;

}

AppendMenu(hmenu, fuFlags, idMenuItem, lpFormatName);

uFormat = EnumClipboardFormats(uFormat);

}

CloseClipboard();

}

BOOL WINAPI IsDisplayableFormat(UINT uFormat)

{

switch (uFormat)

{

case CF_OWNERDISPLAY:

case CF_TEXT:

case CF_ENHMETAFILE:

case CF_BITMAP:

return TRUE;

}

return FALSE;

}