第7章剪贴板操作7.1剪贴板的简单使用7.2剪贴板的复杂用法7.1剪贴板的简单使用•MicrosoftWindows剪贴板–一个Windows内存区域,用于把数据从一个程序传送到另一个程序中。•剪贴板浏览程序–一个Windows程序,用于显示剪贴板的当前内容。•剪贴板操作–Cut、Copy和Paste•剪贴板传输函数–将文字传入和移出剪贴板7.1.1标准剪贴板数据格式CF_TEXT:ANSI字符集字符串。CF_OEMTEXT:OEM字符集数据。CF_UNICODETEXT:Unicode文字的内存块。CF_SYLK:包含Microsoft符号连结的数据格式CF_DIF:数据交换格式CF_BITMAP:设备相关位图CF_DIB:设备无关位图CF_PALETTE:调色板。CF_TIFF:标号图像文件格式(TIFF)数据CF_METAFILEPICT:旧的metafile格式CF_ENHMETAFILE:增强型metafileCF_PENDATA:笔式输入CF_WAVE:声音波形文件。CF_RIFF:资源交换文件格式的多媒体数据。CF_HDROP:与拖放服务相关的文件列表。7.1.2全局内存配置•配置一个内存块–hGlobal=GlobalAlloc(uiFlags,dwSize);•参数:–uiFlags–内存块大小。•返回值–整体内存块句柄,NULL表示不能配置足够的内存。•重新配置函数:–hGlobal=GlobalReAlloc(hGlobal,dwSize,uiFlags);•释放内存块的函数:–GlobalFree(hGlobal)•参数:uiFlagsValueMeaningGHND0x0042CombinesGMEM_MOVEABLEandGMEM_ZEROINIT.GMEM_FIXED0x0000Allocatesfixedmemory.Thereturnvalueisapointer.GMEM_MOVEABLE0x0002Allocatesmovablememory.Thereturnvalueisahandletothememoryobject.Totranslatethehandleintoapointer,usetheGlobalLockfunction.ThisvaluecannotbecombinedwithGMEM_FIXED.GMEM_ZEROINIT0x0040Initializesmemorycontentstozero.GPTR0x0040CombinesGMEM_FIXEDandGMEM_ZEROINIT.7.1.2全局内存配置•定义一个指针和句柄变量–int*p;–GLOBALHANDLEhGlobal;•配置全局内存–hGlobal=GlobalAlloc(GHND,1024);•存取全局内存–p=(int*)GlobalLock(hGlobal);•存取结束–GlobalUnlock(hGlobal);•释放内存–hGlobal=GlobalHandle(p);•GlobalFree(hGlobal)7.1.3将文字传送到剪贴板•首先,配置一个全局内存块–hGlobal=GlobalAlloc(GHND|GMEM_SHARE,iLength+1);•锁定这块内存,得到指向它的一个指针:–pGlobal=GlobalLock(hGlobal);•将字符串复制到内存块中:–for(i=0;iwLength;i++)•*pGlobal++=*pString++;•解锁内存块:–GlobalUnlock(hGlobal);•打开并清空剪贴板:–OpenClipboard(hwnd);–EmptyClipboard();•把指定格式的数据交给剪贴板,关闭剪贴板:–SetClipboardData(CF_TEXT,hGlobal);–CloseClipboard();规则•在同一个消息处理过程中调用OpenClipboard和CloseClipboard。•不要把锁定的内存句柄交给剪贴板。•调用SetClipboardData之后,请不要再继续使用该内存块。•在呼叫CloseClipboard之前,应先为此句柄解锁。7.1.4从剪贴板上取得文字•确定剪贴板的数据格式–bAvailable=IsClipboardFormatAvailable(CF_TEXT);–剪贴板上含有CF_TEXT格式数据时函数返回TRUE•打开剪贴板:–OpenClipboard(hwnd);•获得指定格式的内存块句柄:–hGlobal=GetClipboardData(CF_TEXT);–如果GetClipboardData返回NULL,则关闭剪贴板。–从GetClipboardData得到的句柄不属于使用者程序-它属于剪贴板。不能释放这个句柄或更改它所引用的数据。–存取这些数据,必须制作这个内存块的副本。7.1.4从剪贴板上取得文字•将数据复制到使用者程序中–首先,配置一块与剪贴板数据块大小相同的内存:•pText=(char*)malloc(GlobalSize(hGlobal));–锁定句柄,获得一个指向剪贴板块的指标:•pGlobal=GlobalLock(hGlobal);–复制数据:•strcpy(pText,pGlobal);•或者:•while(*pText++=*pGlobal++);–解锁内存块:•GlobalUnlock(hGlobal);–关闭剪贴板•CloseClipboard();7.1.5打开和关闭剪贴板问题•在任何时候,只有一个程序可以打开剪贴板。•OpenClipboard的作用–当一个程序使用剪贴板时,防止剪贴板的内容发生变化。•OpenClipboard返回值,说明是否已经成功地打开了剪贴板。如果另一个应用程序没有关闭剪贴板,那么它就不能被打开。•如果每个程序都能够尽快、规范地打开和关闭剪贴板,那么您将永远不会遇到不能打开剪贴板的问题。7.1.6剪贴板的文字格式转换只讨论了用剪贴板处理CF_TEXT格式(ANSI文字)。可能对CF_OEMTEXT和CF_UNICODETEXT还不熟悉。处理文字格式时,只需调用SetClipboardData和GetClipboardData,Windows将处理剪贴板中所有的文字转换例如,如果一个程序用SetClipboardData来处理CF_TEXT格式数据时,程序也能用CF_OEMTEXT呼叫GetClipboardData。同样,剪贴板也能将CF_OEMTEXT数据转换为CF_TEXT。在WindowsNT中,转换发生在CF_UNICODETEXT、CF_TEXT和CF_OEMTEXT之间。程序可以使用程序本身最方便的一种文字格式来呼叫SetClipboardData。同样地,程序也可以用需要的文字格式来呼叫GetClipboardData。7.2复杂的剪贴板用法•向剪贴板传输数据:–OpenClipboard(hwnd);–EmptyClipboard();–SetClipboardData(iFormat,hGlobal);–CloseClipboard();•存取剪贴板数据–OpenClipboard(hwnd);–hGlobal=GetClipboardData(iFormat);–其它行程序–CloseClipboard();7.2.1向剪贴板传送多种格式数据•向剪贴板传输数据:–可以把同一数据以多种格式的形式同时写到剪贴板上,此时需要对每种格式数据的全局内存块句柄调用SetClipboardData函数。例如–OpenClipboard(hwnd);–EmptyClipboard();–SetClipboardData(CF_TEXT,hGlobalText);–SetClipboardData(CF_BITMAP,hBitmap);–SetClipboardData(CF_METAFILEPICT,hGlobalMFP);–CloseClipboard();7.2.1向剪贴板传送多种格式数据•当CF_TEXT、CF_BITMAP或CF_METAFILEPICT三种格式的数据同时位于剪贴板上时,用参数呼叫IsClipboardFormatAvailable将传回TRUE。•通过下列函数调用程序可以存取这些代码:–hGlobalText=GetClipboardData(CF_TEXT);–或–hBitmap=GetClipboardData(CF_BITMAP);–或–hGlobalMFP=GetClipboardData(CF_METAFILEPICT);7.2.1向剪贴板传送多种格式数据•枚举剪贴板上的数据格式–iFormat=0;–OpenClipboard(hwnd);–while(iFormat=EnumClipboardFormats(iFormat))–{•各个iFormat值的处理方式–}–CloseClipboard();•取剪贴板中之不同格式的个数:–iCount=CountClipboardFormats();7.2.2延迟提出•延迟提出技术–当向剪贴板传送数据中,并不直接将数据的这份副本传给剪贴板,而是直到有另一个程序需要数据时,程序才提供这份数据。–在调用SetClipboardData函数时,仅传递一个空内存句柄。–程序呼叫GetClipboardData时,Windows将检查那种格式的句柄是否为NULL。–如果是,Windows将给剪贴板所有者发送一个消息,要求取得数据的实际句柄,这时您的程序负责提供这个句柄。7.2.2延迟提出技术的三个消息•WM_RENDERFORMAT–另一个程序呼叫GetClipboardData时,Windows给窗口消息处理程序发送一个的消息,wParam的值是所要求的格式。–在处理WM_RENDERFORMAT消息时,不要打开或清空剪贴板。为wParam所指定的格–式建立一个整体内存块,把数据传给它,并用正确的格式和相应句柄呼叫SetClipboardData。•WM_DESTROYCLIPBOARD–当有个程序调用EmptyClipboard时,Windows将给您的程序发送一个WM_DESTROYCLIPBOARD消息,告诉您不再需要构造剪贴板数据的信息。–此时你的程序将不再是剪贴板的所有者。7.2.2延迟提出技术的三个消息•WM_RENDERALLFORMATS–如果剪贴板拥有者程序要终止执行,并且此时剪贴板上仍然包含着该程序用SetClipboardData设定的NULL数据句柄,将收到WM_RENDERALLFORMATS消息。–这时,应该打开剪贴板,清空它,把数据加载内存块中,并为每种格式呼叫SetClipboardData,然后关闭剪贴板。–WM_RENDERALLFORMATS消息程序最后收到的消息之一。它后面跟有WM_DESTROYCLIPBOARD消息,然后是正常的WM_DESTROY消息。7.2.3延迟技术的实现•延迟技术的实现–在调用SetClipboardData函数时,不传递内存句柄•OpenClipboard(hwnd);•EmptyClipboard();•SetClipboardData(iFormat,NULL);•CloseClipboard();–如果只向剪贴板传输一种格式数据,那么可以把WM_RENDERALLFORMATS和WM_RENDERFORMAT处理结合在一起。•caseWM_RENDERALLFORMATS:–OpenClipboard(hwnd);–EmptyClipboard();•caseWM_RENDERFORMAT:–SetClipboardData(CF_TEXT,hGlobal);–if(message==WM_RENDERALLFORMATS)–CloseClipboard();–return0;7.2.4自定义数据格式•自定义数据格式的意义–在同一个程序的内部传送数据。•自订数据