Windows剪贴板是一种比较简单同时也是开销比较小的IPC(InterProcess Communication,进程间通讯)机制。Windows系统支持剪贴板IPC的基本机制是由系统预留的一块全局共享内存,用来暂存在各进程间进行交换的数据:提供数据的进程创建一个全局内存块,并将要传送的数据移到或复制到该内存块;接受数据的进程(也可以是提供数据的进程本身)获取此内存块的句柄,并完成对该内存块数据的读取。
为使剪贴板的这种IPC机制更加完善和便于使用,需要解决好如下三个问题:提供数据的进程在结束时Windows系统将删除其创建的全局内存块,而接受数据的进程则希望在其退出后剪贴板中的数据仍然存在,可以继续为其他进程所获取;能方便地管理和传送剪贴板数据句柄;能方便设置和确定剪贴板数据格式。为完善上述功能,Windows提供了存在于USER32.dll中的一组API函数、消息和预定义数据格式等,并通过对这些函数、消息的使用来管理在进程间进行的剪贴板数据交换。
Windows系统为剪贴板提供了一组API函数和多种消息,基本可以满足编程的需要。而且Windows还为剪贴板预定义了多种数据格式。通过这些预定义的格式,可以使接收方正确再现数据提供方放置于剪贴板中的数据内容。
(1)文本剪贴板
文本剪贴板是包含具有格式CF_TEXT的字符串的剪贴板,是最经常使用的剪贴板之一。在文本剪贴板中传递的数据是不带任何格式信息的ASCII字符。若要将文本传送到剪贴板,可以先分配一个可移动全局内存块,然后将要复制的文本内容写入到此内存区域。最后调用剪贴板函数将数据放置到剪贴板:
1
//
---------------------------------------------------------
2
//
名称: CopyStringToCliPBoard
3
//
功能: 复制字符串到剪贴板
4
//
参数: hWnd - 窗口HANDLE,可以为NULL
5
//
lpszText - 要复制的字符串
6
//
返回: TRUE-复制成功; FALSE-失败
7
//
---------------------------------------------------------
8
BOOL CopyStringToCliPBoard( HWND hWnd, LPCTSTR lpszText )
9
{
10
//
计算字符串长度
11
int
nlen
=
strlen(lpszText);
12
if
( nlen
==
0
)
13
return
FALSE;
14
15
//
将szText中的内容复制到剪贴板
16
HGLOBAL hglbCopy;
17
LPTSTR lptstrCopy;
18
19
//
打开剪贴板
20
if
(
!
::OpenCliPBoard(hWnd) )
21
return
FALSE;
22
23
//
申请内存空间
24
hglbCopy
=
GlobalAlloc( GMEM_DDESHARE, (nlen
+
1
)
*
sizeof
(
char
) );
25
26
//
申请失败, 关闭剪贴板然后返回
27
if
(hglbCopy
==
NULL)
28
{
29
CloseCliPBoard();
30
return
FALSE;
31
}
32
33
//
清空剪贴板
34
EmptyCliPBoard();
35
36
//
复制数据到申请的内存里
37
lptstrCopy
=
(LPTSTR)GlobalLock( hglbCopy );
38
memcpy( lptstrCopy, lpszText, nlen );
39
//
null character
40
lptstrCopy[nlen]
=
(TCHAR)
0
;
41
GlobalUnlock(lptstrCopy);
42
43
//
将数据拷贝到剪贴板
44
SetCliPBoardData( CF_TEXT, hglbCopy );
45
//
关闭剪贴板
46
CloseCliPBoard();
47
return
TRUE;
48
}
这里以OpenClipboard()打开剪贴板,并在调用了EmptyClipboard()后使hWnd指向的窗口成为剪贴板的拥有者,一直持续到CloseClipboard()函数的调用。在此期间,剪贴板为拥有者所独占,其他进程将无法对剪贴板内容进行修改。
从剪贴板获取文本的过程与之类似,首先打开剪贴板并获取剪贴板的数据句柄,如果数据存在就拷贝其数据到程序变量。由于GetClipboardData()获取的数据句柄是属于剪贴板的,因此用户程序必须在调用CloseClipboard()函数之前使用它:
1 //---------------------------------------------------------
2 // 名称: GetStringFromClipBoard
3 // 功能: 从剪贴板获得文本
4 // 参数: hWnd - 窗口HANDLE,可以为NULL
5 // 返回: 剪贴板的文本
6 //---------------------------------------------------------
7 LPCTSTR GetStringFromClipBoard( HWND hWnd )
8 {
9 // 数据指针
10 LPCTSTR buffer = NULL;
11 // 打开剪贴板
12 if( ::OpenClipboard( hWnd ) )
13 {
14 // 获得剪贴板的数据
15 HANDLE hData =GetClipboardData( CF_TEXT );
16 buffer = (LPCTSTR)GlobalLock( hData );
17 GlobalUnlock( hData );
18 // 关闭剪贴板
19 CloseClipboard();
20 }
21 return buffer;
22 }
(2)位图剪贴板
大多数应用程序对图形数据采取的是位图的剪贴板数据格式。位图剪贴板的使用与文本剪贴板的使用是类似的,只是数据格式要指明为CF_BITMAP,而且在使用SetClipboardData()或GetClipboardData()函数时交给剪贴板或从剪贴板返回的是设备相关位图句柄。下面这段示例代码将把存在于剪贴板中的位图数据显示到程序的客户区:
1 // 获取安全窗口句柄
2 HWND hWnd = GetSafeHwnd();
3 // 打开剪贴板
4 ::OpenClipboard(hWnd);
5 // 获取剪贴板数据句柄
6 HANDLE hBitmap = ::GetClipboardData(CF_BITMAP);
7 // 获取设备环境句柄
8 HDC hDC = ::GetDC(hWnd);
9 // 创建与设备相关的内存环境
10 HDC hdcMem = CreateCompatibleDC(hDC);
11 // 选择对象
12 SelectObject(hdcMem, hBitmap);
13 // 设置映射模式
14 SetMapMode(hdcMem, GetMapMode(hDC));
15 // 得到位图对象
16 BITMAP bm;
17 GetObject(hBitmap, sizeof(BITMAP), &bm);
18 // 位图复制
19 BitBlt(hDC, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
20 // 释放设备环境句柄
21 ::ReleaseDC(hWnd, hDC);
22 // 删除内存环境
23 DeleteDC(hdcMem);
24 // 关闭剪贴板
25 ::CloseClipboard();
这个例子显示了如何在剪贴板保存位图:
1 if( OpenClipboard() )
2 {
3 EmptyClipboard();
4 CBitmap * junk = new CBitmap();
5 CClientDC cdc(this);
6 CDC dc;
7 dc.CreateCompatibleDC(&cdc);
8 CRect client(0,0,200,200);
9 junk->CreateCompatibleBitmap(&cdc,client.Width(),client.Height());
10 dc.SelectObject(junk);
11
12 DrawImage(&dc,CString("Bitmap"));
13
14 //复制数据到剪贴板
15 SetClipboardData(CF_BITMAP,junk->m_hObject);
16 CloseClipboard();
17
18 delete junk;
19 }
(3)WMF数据的操作
在剪贴板上读写图象数据是非常有用的功能,并且实现起来也很简单。下面的代码显示了如何将扩展图元文件复制到剪贴板:
1 if(OpenClipboard());
2 {
3 EmptyClipboard();
4
5 //创建图元文件DC
6 CMetaFileDC * cDC = new CMetaFileDC();
7 cDC->CreateEnhanced(GetDC(),NULL,NULL,"the_name");
8
9 //调用绘图例程
10
11 //关闭CMetafileDC并获得它的句柄
12 HENHMETAFILE handle = cDC->CloseEnhanced();
13
14 //复制到剪贴板
15 SetClipBoardData(CF_ENHMETAFILE,handle);
16 CloseClipboard();
17
18 //删除dc
19 delete cDC;
20 }
21
下面的代码演示了从剪贴板获得图元文件并将其绘制到client DC上:
1 if(OpenClipboard())
2 {
3 //获得剪贴板数据
4 HENMETAFILE handle = (HENMETAFILE)GetClipboardData(CF_ENHMETAFILE);
5
6 //显示
7 CClientDC dc(this);
8 CRect client(0,0,200,200);
9 dc.PlayMetaFile(handle,client);
10
11 //关闭剪贴板
12 CloseClipboard();
13 }
14
posted on 2009-06-11 14:47
翾 阅读(618)
评论(0) 编辑 收藏 引用 所属分类:
C/C++