您的位置:首页 > 其它

第12章 剪贴板_12.3 实现一个剪贴板查看器

2015-08-02 09:38 246 查看
12.3.1 剪贴板查看器链
(1)Windows下可运行任意个剪贴板查看器,但只有一个是“当前剪贴板查看器”,Windows只维护这个剪贴板查看器的窗口句柄,并在剪贴板内容改变时,通知它。

(2)当A程序注册为剪贴板查看器时,就成为当前查看器。Windows会把上个当前查看器B的窗口句柄交给A程序来保存。当A收到剪贴板消息时,要发送给查看器链中的下一个程序,即B的窗口过程。

12.3.2 剪贴板查看器函数和消息

(1)将程序加入剪贴板查看器链

static HWND hwndNextViewer;

case WM_CREATE:

hwndNextViewer =SetClipboardViewer(hwnd);//hwndNextViewer得保存下来,这是

//剪贴板消息的下一个接收者。

(2)WM_DRAWCLIPBOARD消息

①剪贴板内板改变时,会发送这消息给当前查看器(最新注册的那个)。

②剪贴板查看器链中的每个程序都应通用SendMessage把消息传给下一个查看器

(hwndNextViewer),直到hwndNextViewer为NULL。

③不要把WM_DRAWCLIPBOARD与WM_PAINTCLIPBOARD混为一谈

消息

消息发起者

WM_DRAWCLIPBOARD

Windows自动发送的,通知查看器剪贴板内容发生了变化。

WM_PAINTCLIPBOARD

查看器(即手动发送的),发给使用CF_OWNERDISP格式的程序

④WM_DRAWCLIPBOARD消息的处理

case WM_DRAWCLIPBOARD:

if(hwndNextViewer)SendMessage(hwndNextViewer,message,wParam,lParam);

InvalidateRect(hwnd,NULL,TRUE);

return 0;

(3)退出剪贴板查看器链:ChangeClipboardChain(hwnd,hwndNextViewer);

①当某个程序退出查看器链时,Windows会向当前查看器发送WM_CHANGECBCHAIN消息。

case WM_CHANGECBCHAIN:  //wParam:要退出链的窗口句柄。lParam:它的下个剪贴板查看器
if((HWND)wParam == hwndNextViewer) //要退出的窗口w是不是我的下个查看器消息接收者?
hwndNextViewer =(HWND)lParam; //如果是,将A的消息接收者(lParam)转到我的接收者。
else if(hwndNextViewer)   //如果要退出的不是我的下个接收者,将退出消息转发下去。
SendMessage(hwndNextViewer,message,wParam,lParam);

return 0;


②程序终止时,必须从查看器链退出中。

case WM_DESTROY:

ChangeClipboardChain(hwnd,hwndNextViewer);

PostQuitMessage(0);

(4)获得第一个剪贴板查看器(即当前查看器)的窗口句柄:hwndViewer= GetClipboardViewer();

12.3.3 一个简单的剪贴板查看器

①可实时感知剪贴板内容发生变化(eg.迅雷的下载地址监测)

②本程序只监测CF_TEXT的变化。

【ClipView程序】
效果图



/*------------------------------------------------------------
CLIPVIEW.C -- Simple Clipboard Viewer
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("ClipView");
HWND         hwnd;
MSG          msg;
WNDCLASS     wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}

hwnd = CreateWindow(szAppName,                  // window class name
TEXT("Simple Clipboard Viewer(Text Only)"), // window caption
WS_OVERLAPPEDWINDOW,        // window style
CW_USEDEFAULT,              // initial x position
CW_USEDEFAULT,              // initial y position
CW_USEDEFAULT,              // initial x size
CW_USEDEFAULT,              // initial y size
NULL,                       // parent window handle
NULL,                       // window menu handle
hInstance,                  // program instance handle
NULL);                     // creation parameters

ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);

while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC         hdc;
PAINTSTRUCT ps;
RECT        rect;
static HWND hwndNextViewer;
HGLOBAL     hGlobal;
PTSTR       pGlobal;
switch (message)
{
case WM_CREATE:
//加入剪贴板查看器链
hwndNextViewer = SetClipboardViewer(hwnd);
return 0;
case WM_CHANGECBCHAIN: //当有程序退出剪贴板查看器链时
//wParam:要退出查看器链的窗口句柄,lParam:它的下一个消息接收者。
if ((HWND)wParam == hwndNextViewer) //退出窗口是我的下个消息接收者?
{
hwndNextViewer = (HWND)lParam; //如果是,将该窗的下个消息接收者(lParam)转到我的名下。
} else if (hwndNextViewer)  //要退出的不是我的下个接收者,则直接将退出消息向下通知出去。
SendMessage(hwndNextViewer, message, wParam, lParam);
return 0;
case WM_DRAWCLIPBOARD:  //当剪贴板内容改变时,将消息通知下去。
if (hwndNextViewer)
SendMessage(hwndNextViewer, message, wParam, lParam);
InvalidateRect(hwnd, NULL, TRUE);
return 0;

case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
OpenClipboard(hwnd);
#ifdef UNICODE
hGlobal = GetClipboardData(CF_UNICODETEXT);
#else
hGlobal = GetClipboardData(CF_TEXT);
#endif
if (hGlobal != NULL)
{
pGlobal = GlobalLock(hGlobal);
DrawText(hdc, pGlobal, -1, &rect,
DT_EXPANDTABS);
GlobalUnlock(hGlobal);
}

CloseClipboard();

EndPaint(hwnd, &ps);
return 0;

case WM_DESTROY:
//退出剪贴板查看器链
ChangeClipboardChain(hwnd, hwndNextViewer);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: