关于剪贴板和Unicode —— CLIPTEXT程序分析

/*----------------------------------------------
CLIPTEXT.C -- The Clipboard and Text
----------------------------------------------*/
#include
#include"resource.h"

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

#ifdef UNICODE

#define CF_TCHAR CF_UNICODETEXT
TCHAR szDefault Text[] = TEXT("Default Text - Unicode Version");
THCAR szCaption[] = TEXT("Clipboard Text Transfers - Unicode Version");
#else
#define CF_TCHAR CF_TEXT
TCHAR szDefaultText[] = TEXT("Default Text - ANSI Version");
TCHAR szCaption[] = TEXT("Clipboard Text Transfers - ANSI Version");

#endif

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
static TCHAR szAppName[] = TEXT("ClipText");
HACCEL hAccel;
HWND hwnd;
MSG msg;
WNDCLASS wndcls;

wndcls.style = CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = WndProc;
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
wndcls.hInstance = hInstance;
wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndcls.hCursor = LoadCursor(NULL,IDC_ARROW);
wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndcls.lpszMenuName = szAppName;
wndcls.lpszClassName = szAppName;

RegisterClass(&wndcls);

hwnd = CreateWindow(szAppName,szCaption,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL);

ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);

hAccel = LoadAccelerators(hInstance,szAppName);

while(GetMessage(&msg,NULL,0,0))
{
if(!TranslateAccelerator(hwnd,hAccel,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
static PTSTR pText; //程序文本字符串指针,用于给程序提供要显示的文本
//pText作为程序文本内存块指针,需要在各个消息间实现交互,因此malloc和free不需要在一个消息执行过程中成对出现

BOOL bEnable;
HGLOBAL hGlobal; //全局内存块句柄,用以引用剪贴板内存块
HDC hdc;
LPSTR pGlobal; //指向剪贴板内存块的指针
PAINTSTRUCT ps;
RECT rect;

switch(msg)
{
case WM_CREATE:
SendMessage(hwnd,WM_COMMAND,IDM_EDIT_RESET,0); //程序启动时,初始化程序文本字符串为默认字符串
return 0;

case WM_INITMENUPOPUP:
EnableMenuItem((HMENU)wParam,IDM_EDIT_PASTE,
IsClipboardFormatAvailable(CF_TCHAR) ? MF_ENABLED : MF_GRAYED); //检查剪贴板内存块中有无可用的数据类型

bEnable = pText ? MF_ENABLED : MF_GRAYED; //如果剪贴板内存块中有CF_TCHAR数据类型,就使菜单状态标志可用

EnableMenuItem((HMENU)wParam,IDM_EDIT_CUT,bEnable);
EnableMenuItem((HMENU)wParam,IDM_EDIT_COPY,bEnable);
EnableMenuItem((HMENU)wParam,IDM_EDIT_CLEAR,bEnable);
break;

case WM_COMMAND:
switch(LOWORD(wParam)) //LOWORD(wParam)为菜单项的ID
{
case IDM_EDIT_PASTE: //如果选中的是“粘贴”菜单项
OpenClipboard(hwnd); //程序打开剪贴板

if(hGlobal = GetClipboardData(CF_TCHAR)) //如果从剪贴板中获取CF_CHAR类型数据成功
{
pGlobal = GlobalLock(hGlobal); //锁定剪贴板内存块并返回指向剪贴板内存块的指针
if(pText) //如果程序文本字符串中原来不为空
{
free(pText); //回收先前指向的程序文本内存块,否则会发生内存泄漏
pText = NULL;
}
pText = malloc(GlobalSize(hGlobal)); //重新分配一个和剪贴板内存块一样大小的程序内存块给pText指针
lstrcpy(pText,pGlobal); //从剪贴板中复制数据到程序文本内存块
InvalidateRect(hwnd,NULL,TRUE); //使窗口无效而发生重绘,更新窗口的显示内容
}
CloseClipboard(); //粘贴完成,关闭剪贴板
return 0;


//执行“剪切”和“复制”菜单命令
case IDM_EDIT_CUT:
case IDM_EDIT_COPY:
if(!pText)
return 0;

hGlobal = GlobalAlloc(GHND | GMEM_SHARE,
(lstrlen(pText) + 1) * sizeof(TCHAR)); //分配全局内存块
pGlobal = GlobalLock(hGlobal); //锁定内存块并得到指向它的指针
lstrcpy(pGlobal,pText); //从程序内存块中复制数据到全局内存块
GlobalUnlock(hGlobal); //解锁全局内存块

OpenClipboard(hwnd); //打开剪贴板
EmptyClipboard(); //清空剪贴板原来的内容以备复制新的数据到剪贴板
SetClipboardData(CF_TCHAR,hGlobal); //将全局内存句柄传给剪贴板
CloseClipboard(); //复制完成,关闭剪贴板


//如果选中是“复制”命令就直接返回
//如果是“剪切”命令就继续下传执行后面的IDM_EDIT_CLEAR消息来清空程序文本内存块来实现“剪切”的目的
if(LOWORD(wParam) ==IDM_EDIT_COPY)
return 0;

case IDM_EDIT_CLEAR:
if(pText)
{
free(pText); //回收程序文本内存
pText = NULL; //释放pText指针
}
InvalidateRect(hwnd,NULL,TRUE); //程序文本内存改变后立即更新窗口
return 0;

case IDM_EDIT_RESET: //重置程序文本内存
if(pText)
{
free(pText);
pText = NULL;
}

//将默认字符串赋给程序文本内存指针
pText = malloc((lstrlen(szDefaultText) + 1) * sizeof(TCHAR));
lstrcpy(pText,szDefaultText);
InvalidateRect(hwnd,NULL,TRUE); //使窗口无效,更新窗口显示内容
return 0;
}
break;

case WM_PAINT:
hdc = BeginPaint(hwnd,&ps);

GetClientRect(hwnd,&rect);

//将程序文本内存块通过DrawText函数输出到窗口客户区
if(pText != NULL)
DrawText(hdc,pText,-1,&rect,DT_EXPANDTABS | DT_WORDBREAK);

EndPaint(hwnd,&ps);
return 0;

case WM_DESTROY:
//程序结束时回收内存
if(pText)
free(pText);

PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}

你可能感兴趣的:(Windows程序设计)