//
要成为剪贴板查看器必须做到以下几点
// 1.调用SetClipboardViewer,把自己加入到剪贴板查看器链
// 在这一步中, 要保存在这条链中,紧跟自己后面的剪贴板查看器的窗口句柄
// 2.加入了剪贴板查看器链,在适当时候就必须退出这个链.
// 所以,在程序退出时,调用ChangeClipboardChain把自己从剪贴板查看器链移除
// 3.处理由于其他剪贴板查看器的上述操作引起的消息 WM_CHANGECBCHAIN
// 4.处理WM_DRAWCLIPBOARD, 真正地查看剪贴板,即把剪贴板的内容显示出来
// 这当然就要对不同的数据类型(例如文字类型和图片类型的数据)采取不同的方法显示
// 我这个例子就只简单地处理文字类型的数据, 所以比较简单
#include < windows.h >
// 过程函数的返回值都是LRESULT,类型都是CALLBACK
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd; // 主窗口句柄,在CreateWindow中赋值
MSG msg; // 消息变量,在GetMessage中使用
WNDCLASS wndclass; // 窗口类
TCHAR * szAppName = TEXT( " CBViewer " ); // 类名和窗口名
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 窗口背景
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); // 鼠标
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); // 图标
wndclass.lpszClassName = szAppName; // 类名
wndclass.cbClsExtra = 0 ; // 类的额外参数
wndclass.cbWndExtra = 0 ; // 窗口的额外参数.用于基于同一窗口类的窗口各自区分.
// 在自定义对话框类时必须指定为DLGWINDOWEXTRA的大小
wndclass.lpszMenuName = NULL; // 菜单名.可以用作子窗口的id
wndclass.style = CS_HREDRAW | CS_VREDRAW; // 窗口风格
wndclass.lpfnWndProc = WndProc; // 窗口过程
wndclass.hInstance = hInstance; // 包含窗口过程的实例句柄
if ( ! RegisterClass( & wndclass) ) // 注册窗口类
return 0 ;
hwnd = CreateWindow( // 创建窗口
szAppName, // 窗口类名
szAppName, // 窗口标题
WS_OVERLAPPEDWINDOW, // 窗口风格
CW_USEDEFAULT, // 初始的x坐标
CW_USEDEFAULT, // 初始的y坐标
CW_USEDEFAULT, // 初始的宽度
CW_USEDEFAULT, // 初始的高度
NULL, // 父窗口
NULL, // 菜单
hInstance, // 和窗口相关的实例句柄
NULL // 额外参数
);
ShowWindow( hwnd,nCmdShow ); // 显示窗口
UpdateWindow( hwnd ); // 更新窗口
while ( GetMessage( & msg,NULL, 0 , 0 ) ) // 消息循环
{
TranslateMessage( & msg); // 将WM_XXXKEYXXX消息翻译为WM_CHAR消息
DispatchMessage( & msg); // 传递消息到窗口过程
}
return msg.wParam; // 返回
}
LRESULT WINAPI WndProc( HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam )
{
static HWND hwndNextViewer; // 剪贴板查看器链的下一个窗口
switch ( message )
{
case WM_CREATE:
{
hwndNextViewer = SetClipboardViewer(hwnd);
return 0 ;
}
case WM_CHANGECBCHAIN:
if ( hwndNextViewer == (HWND)wParam )
{
hwndNextViewer = (HWND)lParam;
}
else if ( hwndNextViewer != NULL )
{
SendMessage(hwndNextViewer, message, wParam, lParam );
}
return 0 ;
case WM_DRAWCLIPBOARD:
{
if ( hwndNextViewer != NULL )
{
SendMessage(hwndNextViewer, message, wParam, lParam);
}
InvalidateRect(hwnd, NULL, TRUE);
return 0 ;
}
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
HGLOBAL hglobal;
char * pText;
RECT rc;
OpenClipboard(hwnd);
hdc = BeginPaint(hwnd, & ps);
hglobal = GetClipboardData(CF_TEXT);
if (hglobal != NULL)
{
pText = ( char * )GlobalLock(hglobal);
GetClientRect(hwnd, & rc);
DrawText(hdc, pText, - 1 , & rc, DT_CENTER);
GlobalUnlock(hglobal);
}
CloseClipboard();
EndPaint(hwnd, & ps);
return 0 ;
}
case WM_DESTROY:
ChangeClipboardChain(hwnd, hwndNextViewer);
PostQuitMessage( 0 );
return 0 ;
}
return DefWindowProc( hwnd,message,wParam,lParam );
}
// 1.调用SetClipboardViewer,把自己加入到剪贴板查看器链
// 在这一步中, 要保存在这条链中,紧跟自己后面的剪贴板查看器的窗口句柄
// 2.加入了剪贴板查看器链,在适当时候就必须退出这个链.
// 所以,在程序退出时,调用ChangeClipboardChain把自己从剪贴板查看器链移除
// 3.处理由于其他剪贴板查看器的上述操作引起的消息 WM_CHANGECBCHAIN
// 4.处理WM_DRAWCLIPBOARD, 真正地查看剪贴板,即把剪贴板的内容显示出来
// 这当然就要对不同的数据类型(例如文字类型和图片类型的数据)采取不同的方法显示
// 我这个例子就只简单地处理文字类型的数据, 所以比较简单
#include < windows.h >
// 过程函数的返回值都是LRESULT,类型都是CALLBACK
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd; // 主窗口句柄,在CreateWindow中赋值
MSG msg; // 消息变量,在GetMessage中使用
WNDCLASS wndclass; // 窗口类
TCHAR * szAppName = TEXT( " CBViewer " ); // 类名和窗口名
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 窗口背景
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); // 鼠标
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); // 图标
wndclass.lpszClassName = szAppName; // 类名
wndclass.cbClsExtra = 0 ; // 类的额外参数
wndclass.cbWndExtra = 0 ; // 窗口的额外参数.用于基于同一窗口类的窗口各自区分.
// 在自定义对话框类时必须指定为DLGWINDOWEXTRA的大小
wndclass.lpszMenuName = NULL; // 菜单名.可以用作子窗口的id
wndclass.style = CS_HREDRAW | CS_VREDRAW; // 窗口风格
wndclass.lpfnWndProc = WndProc; // 窗口过程
wndclass.hInstance = hInstance; // 包含窗口过程的实例句柄
if ( ! RegisterClass( & wndclass) ) // 注册窗口类
return 0 ;
hwnd = CreateWindow( // 创建窗口
szAppName, // 窗口类名
szAppName, // 窗口标题
WS_OVERLAPPEDWINDOW, // 窗口风格
CW_USEDEFAULT, // 初始的x坐标
CW_USEDEFAULT, // 初始的y坐标
CW_USEDEFAULT, // 初始的宽度
CW_USEDEFAULT, // 初始的高度
NULL, // 父窗口
NULL, // 菜单
hInstance, // 和窗口相关的实例句柄
NULL // 额外参数
);
ShowWindow( hwnd,nCmdShow ); // 显示窗口
UpdateWindow( hwnd ); // 更新窗口
while ( GetMessage( & msg,NULL, 0 , 0 ) ) // 消息循环
{
TranslateMessage( & msg); // 将WM_XXXKEYXXX消息翻译为WM_CHAR消息
DispatchMessage( & msg); // 传递消息到窗口过程
}
return msg.wParam; // 返回
}
LRESULT WINAPI WndProc( HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam )
{
static HWND hwndNextViewer; // 剪贴板查看器链的下一个窗口
switch ( message )
{
case WM_CREATE:
{
hwndNextViewer = SetClipboardViewer(hwnd);
return 0 ;
}
case WM_CHANGECBCHAIN:
if ( hwndNextViewer == (HWND)wParam )
{
hwndNextViewer = (HWND)lParam;
}
else if ( hwndNextViewer != NULL )
{
SendMessage(hwndNextViewer, message, wParam, lParam );
}
return 0 ;
case WM_DRAWCLIPBOARD:
{
if ( hwndNextViewer != NULL )
{
SendMessage(hwndNextViewer, message, wParam, lParam);
}
InvalidateRect(hwnd, NULL, TRUE);
return 0 ;
}
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
HGLOBAL hglobal;
char * pText;
RECT rc;
OpenClipboard(hwnd);
hdc = BeginPaint(hwnd, & ps);
hglobal = GetClipboardData(CF_TEXT);
if (hglobal != NULL)
{
pText = ( char * )GlobalLock(hglobal);
GetClientRect(hwnd, & rc);
DrawText(hdc, pText, - 1 , & rc, DT_CENTER);
GlobalUnlock(hglobal);
}
CloseClipboard();
EndPaint(hwnd, & ps);
return 0 ;
}
case WM_DESTROY:
ChangeClipboardChain(hwnd, hwndNextViewer);
PostQuitMessage( 0 );
return 0 ;
}
return DefWindowProc( hwnd,message,wParam,lParam );
}