//引用MSDN上的注释
The SetClipboardViewer function adds the specified window to the chain of clipboard viewers. Clipboard viewer windows receive a WM_DRAWCLIPBOARD message whenever the content of the clipboard changes.
The windows that are part of the clipboard viewer chain, called clipboard viewer windows, must process the clipboard messages WM_CHANGECBCHAIN and WM_DRAWCLIPBOARD. Each clipboard viewer window calls theSendMessage function to pass these messages to the next window in the clipboard viewer chain.
A clipboard viewer window must eventually remove itself from the clipboard viewer chain by calling the ChangeClipboardChain function — for example, in response to theWM_DESTROY message.
// SimpClipboardViewer.cpp : 定义应用程序的入口点。
//
#ifndef WINVER
#define WINVER 0x0500 // 将此值更改为相应的值,以适用于 Windows 的其他版本。
#endif //WINVER
#ifndef _WIN32_WINNT // 指定要求的最低平台是 Windows 2000。
#define _WIN32_WINNT 0x0500 // 将此值更改为相应的值,以适用于 Windows 的其他版本。
#endif
#ifndef _WIN32_WINDOWS // 指定要求的最低平台是 Windows 98。
#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
#endif
// Windows 头文件:
#include <windows.h>
// C 运行时头文件
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include "resource.h"
#define MAX_LOADSTRING 100
// 全局变量:
HINSTANCE hInst = NULL; // 当前实例
// 此代码模块中包含的函数的前向声明:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
int iRet = 0;
hInst = hInstance;
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
do
{
//注册类
ATOM wClassEx = 0;
{
WNDCLASSEX wcex = {0};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_SIMPCLIPBOARDVIEWER);
wcex.lpszClassName = _T("SIMPCLIPBOARDVIEWER");
if((wClassEx = RegisterClassEx(&wcex)) == 0)
{
iRet = -1;
break;
}
}
// 执行应用程序初始化:
{
HWND hWnd = CreateWindow((LPCTSTR)wClassEx, _T("剪切板查看器"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if(hWnd == NULL)
{
iRet = -2;
break;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
}
// 主消息循环:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
iRet = (int) msg.wParam;
}while(0);
return iRet;
}
UINT uFormat = (UINT)(-1);
BOOL fAuto = TRUE;
HWND hwndNextViewer = NULL;
void WINAPI SetAutoView(HWND hwnd)
{
static UINT auPriorityList[] =
{
CF_OWNERDISPLAY,
CF_TEXT,
CF_UNICODETEXT,
CF_ENHMETAFILE,
CF_BITMAP
};
uFormat = GetPriorityClipboardFormat(auPriorityList, _countof(auPriorityList));
fAuto = TRUE;
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
BOOL WINAPI IsDisplayableFormat(UINT uFormat)
{
switch (uFormat)
{
case CF_OWNERDISPLAY:
case CF_TEXT:
case CF_UNICODETEXT:
case CF_ENHMETAFILE:
case CF_BITMAP:
return TRUE;
}
return FALSE;
}
LPCTSTR GetPredefinedClipboardFormatName(UINT uFormat)
{
LPCTSTR lpFormatName = NULL;
#define caseFormat(x) case(x): { lpFormatName = _T(#x); break; }
switch(uFormat)
{
caseFormat(CF_TEXT)
caseFormat(CF_BITMAP)
caseFormat(CF_METAFILEPICT)
caseFormat(CF_SYLK)
caseFormat(CF_DIF)
caseFormat(CF_TIFF)
caseFormat(CF_OEMTEXT)
caseFormat(CF_DIB)
caseFormat(CF_PALETTE)
caseFormat(CF_PENDATA)
caseFormat(CF_RIFF)
caseFormat(CF_WAVE)
caseFormat(CF_UNICODETEXT)
caseFormat(CF_ENHMETAFILE)
#if(WINVER >= 0x0400)
caseFormat(CF_HDROP)
caseFormat(CF_LOCALE)
#endif /* WINVER >= 0x0400 */
#if(WINVER >= 0x0500)
caseFormat(CF_DIBV5)
#endif /* WINVER >= 0x0500 */
caseFormat(CF_OWNERDISPLAY)
caseFormat(CF_DSPTEXT)
caseFormat(CF_DSPBITMAP)
caseFormat(CF_DSPMETAFILEPICT)
caseFormat(CF_DSPENHMETAFILE)
default: break;
}
return lpFormatName;
}
void WINAPI InitMenu(HWND hwnd, HMENU hmenu)
{
UINT uFormat;
TCHAR szFormatName[80];
LPCTSTR 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 = _T("(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();
}
LRESULT APIENTRY WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
HDC hdcMem;
PAINTSTRUCT ps;
RECT rc;
HGLOBAL hglb;
HBITMAP hbm;
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));
LPPAINTSTRUCT lpps = (LPPAINTSTRUCT)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);
LPCSTR lpstr = (LPCSTR)GlobalLock(hglb);
GetClientRect(hwnd, &rc);
DrawTextA(hdc, lpstr, -1, &rc, DT_LEFT);
GlobalUnlock(hglb);
CloseClipboard();
}
break;
}
case CF_UNICODETEXT:
{
if (OpenClipboard(hwnd))
{
hglb = GetClipboardData(uFormat);
LPCWSTR lpstr = (LPCWSTR)GlobalLock(hglb);
GetClientRect(hwnd, &rc);
DrawTextW(hdc, lpstr, -1, &rc, DT_LEFT);
GlobalUnlock(hglb);
CloseClipboard();
}
break;
}
case CF_ENHMETAFILE:
{
if (OpenClipboard(hwnd))
{
HENHMETAFILE hemf = (HENHMETAFILE)GetClipboardData(uFormat);
GetClientRect(hwnd, &rc);
PlayEnhMetaFile(hdc, hemf, &rc);
CloseClipboard();
}
break;
}
case 0:
{
GetClientRect(hwnd, &rc);
DrawText(hdc, _T("The clipboard is empty."), -1,
&rc, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
break;
}
default:
{
GetClientRect(hwnd, &rc);
DrawText(hdc, _T("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));
LPRECT lprc = (LPRECT)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;
}
//resource.h
#define IDM_EXIT 105
#define IDC_SIMPCLIPBOARDVIEWER 109
#define IDM_AUTO 32772
//SimpclipboardViwer.rc
//
// Menu
//
IDC_SIMPCLIPBOARDVIEWER MENU
BEGIN
POPUP "文件(&F)"
BEGIN
MENUITEM "退出(&X)", IDM_EXIT
END
POPUP "剪贴板格式"
BEGIN
MENUITEM "自动刷新", IDM_AUTO
MENUITEM SEPARATOR
END
END