Пример ниже показывает простое приложение создающее окно просмотра буфера обмена.
Демонстрационный пример
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); // Переходим в формат зависимый от буфера обмена. switch (uFormat) { case CF_OWNERDISPLAY: hwndOwner = GetClipboardOwner(); hglb = GlobalAlloc(GMEM_MOVEABLE, 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_MOVEABLE, sizeof(RECT)); lprc = GlobalLock(hglb); GetClientRect(hwnd, lprc); GlobalUnlock(hglb); SendMessage(hwndOwner, WM_SIZECLIPBOARD, (WPARAM) hwnd, (LPARAM) hglb); GlobalFree(hglb); } break; case WM_CREATE: // Добавим окно в цепочку окон просмотра буфера. hwndNextViewer = SetClipboardViewer(hwnd); break; case WM_CHANGECBCHAIN: // Если следующее окно закрывается, восстановим цепочку. if ((HWND) wParam == hwndNextViewer) hwndNextViewer = (HWND) lParam; // Иначе, передадим сообщение в следующее звено. else if (hwndNextViewer != NULL) SendMessage(hwndNextViewer, uMsg, wParam, lParam); break; case WM_DESTROY: ChangeClipboardChain(hwnd, hwndNextViewer); PostQuitMessage(0); break; case WM_DRAWCLIPBOARD: // изменилось содержание буфера обмена. // Обновим окно используя формат буфера обмена Auto. SetAutoView(hwnd); // Передадим сообщение в следующее окно в цепочке // окон просмотра буфера. 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 (GetMenuItemID(hmenu, 0) != IDM_AUTO) return; // Удаляем все пункты меню кроме первого. while (GetMenuItemCount(hmenu) > 1) DeleteMenu(hmenu, 1, MF_BYPOSITION); // Отмечаем или не отмечаем пункт меню Auto. fuFlags = fAuto ? MF_BYCOMMAND | MF_CHECKED : MF_BYCOMMAND | MF_UNCHECKED; CheckMenuItem(hmenu, IDM_AUTO, fuFlags); // Если нет форматов буфера обмена, возвращаемся. if (CountClipboardFormats() == 0) return; // Открываем буфер обмена. if (!OpenClipboard(hwnd)) return; // Добавляем сепаратор и затем пункты меню для каждого формата. AppendMenu(hmenu, MF_SEPARATOR, 0, NULL); uFormat = EnumClipboardFormats(0); while (uFormat) { // Вызываем определяемую программой функцию, которая // получит название формата буфера обмена. lpFormatName = GetPredefinedClipboardFormatName(uFormat); // Для зарегистрированного формата получим зарегистрированное имя. if (lpFormatName == NULL) { // Заметьте, что если имя формата больше, // чем буфер, оно обрезается. if (GetClipboardFormatName(uFormat, szFormatName, sizeof(szFormatName))) lpFormatName = szFormatName; else lpFormatName = "(unknown)"; } // Добавим пункт меню для формата. Для воспроизводящего формата // используйте ID формата для 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; } |