• 网络学院
  • IT资讯
  • 操作系统
  • 网络技术
  • 软件应用
  • 办公软件
  • 编程技术
  • 网站架设
  • 数据库类
  • 平面设计
  • 多媒体类
  • 游戏资讯
  • 教学论文
  • 认证考试
Windows编程的剪贴板机制
  站点:
  • 首 页
  • 最新软件
  • 文章教程
  • 国内软件
  • 国外软件
  • 绿色软件
  • 源码下载
  • 字体下载
Windows编程的剪贴板机制
软件发布 Windows编程的剪贴板机制
网络软件 系统工具 应用软件 联络聊天 图形图像 多媒体类 行业软件 游戏娱乐 编程开发 安全相关 教育教学 数码软件 绿软下载
热门软件: QQ 瑞星 pplive e话通 木马克星 千千静听 office2000 五笔字根 Photoshop 视频分割
返回文章教程首页 >> 软件应用 >> 系统工具 >> Windows编程的剪贴板机制

Windows编程的剪贴板机制

添加时间: 2007-3-11 3:33:07  作者: 第九软件网  阅读次数:36   来源: http://www.d9soft.com

       

  摘要: 本文对Windows剪贴板机制作了深入、全面的阐述,具体内容包括:文本、位图、DSP、自定义格式剪贴板的使用和多数据项和延迟提交技术。

  关键词: VC++6.0; 剪贴板机制;数据格式;延迟提交

  Windows剪贴板

  Windows剪贴板是一种比较简单同时也是开销比较小的IPC(InterProcess Communication,进程间通讯)机制。Windows系统支持剪贴板IPC的基本机制是由系统预留的一块全局共享内存,用来暂存在各进程间进行交换的数据:提供数据的进程创建一个全局内存块,并将要传送的数据移到或复制到该内存块;接受数据的进程(也可以是提供数据的进程本身)获取此内存块的句柄,并完成对该内存块数据的读取。

  为使剪贴板的这种IPC机制更加完善和便于使用,需要解决好如下三个问题:提供数据的进程在结束时Windows系统将删除其创建的全局内存块,而接受数据的进程则希望在其退出后剪贴板中的数据仍然存在,可以继续为其他进程所获取;能方便地管理和传送剪贴板数据句柄;能方便设置和确定剪贴板数据格式。为完善上述功能,Windows提供了存在于USER32.dll中的一组API函数、消息和预定义数据格式等,并通过对这些函数、消息的使用来管理在进程间进行的剪贴板数据交换。

  Windows系统为剪贴板提供了一组API函数和多种消息,基本可以满足编程的需要。而且Windows还为剪贴板预定义了多种数据格式。通过这些预定义的格式,可以使接收方正确再现数据提供方放置于剪贴板中的数据内容。

  文本剪贴板和位图剪贴板的使用

  这两种剪贴板是比较常用的。其中,文本剪贴板是包含具有格式CF_TEXT的字符串的剪贴板,是最经常使用的剪贴板之一。在文本剪贴板中传递的数据是不带任何格式信息的ASCII字符。若要将文本传送到剪贴板,可以先分配一个可移动全局内存块,然后将要复制的文本内容写入到此内存区域。最后调用剪贴板函数将数据放置到剪贴板:

DWord dwLength = 100; // 要复制的字串长度
HANDLE hGlobalMemory = GlobalAlloc(GHND, dwLength + 1); // 分配内存
LPBYTE lpGlobalMemory = (LPBYTE)GlobalLock(hGlobalMemory); // 锁定内存
for (int i = 0; i 〈 dwLength; i++) // 将"*"复制到全局内存块
 *lpGlobalMemory++ = '*';
 GlobalUnlock(hGlobalMemory); // 锁定内存块解锁
 HWND hWnd = GetSafeHwnd(); // 获取安全窗口句柄
 ::OpenClipboard(hWnd); // 打开剪贴板
 ::EmptyClipboard(); // 清空剪贴板
 ::SetClipboardData(CF_TEXT, hGlobalMemory); // 将内存中的数据放置到剪贴板
 ::CloseClipboard(); // 关闭剪贴板


  这里以OpenClipboard()打开剪贴板,并在调用了EmptyClipboard()后使hWnd指向的窗口成为剪贴板的拥有者,一直持续到CloseClipboard()函数的调用。在此期间,剪贴板为拥有者所独占,其他进程将无法对剪贴板内容进行修改。

  从剪贴板获取文本的过程与之类似,首先打开剪贴板并获取剪贴板的数据句柄,如果数据存在就拷贝其数据到程序变量。由于GetClipboardData()获取的数据句柄是属于剪贴板的,因此用户程序必须在调用CloseClipboard()函数之前使用它:

HWND hWnd = GetSafeHwnd(); // 获取安全窗口句柄
::OpenClipboard(hWnd); // 打开剪贴板
HANDLE hClipMemory = ::GetClipboardData(CF_TEXT);// 获取剪贴板数据句柄
DWORD dwLength = GlobalSize(hClipMemory); // 返回指定内存区域的当前大小
LPBYTE lpClipMemory = (LPBYTE)GlobalLock(hClipMemory); // 锁定内存
m_sMessage = CString(lpClipMemory); // 保存得到的文本数据
GlobalUnlock(hClipMemory); // 内存解锁
::CloseClipboard(); // 关闭剪贴板


  大多数应用程序对图形数据采取的是位图的剪贴板数据格式。位图剪贴板的使用与文本剪贴板的使用是类似的,只是数据格式要指明为CF_BITMAP,而且在使用SetClipboardData()或GetClipboardData()函数时交给剪贴板或从剪贴板返回的是设备相关位图句柄。下面这段示例代码将把存在于剪贴板中的位图数据显示到程序的客户区:

HWND hWnd = GetSafeHwnd(); // 获取安全窗口句柄
::OpenClipboard(hWnd); // 打开剪贴板
HANDLE hBitmap = ::GetClipboardData(CF_BITMAP); // 获取剪贴板数据句柄
HDC hDC = ::GetDC(hWnd); // 获取设备环境句柄
HDC hdcMem = CreateCompatibleDC(hDC); // 创建与设备相关的内存环境
SelectObject(hdcMem, hBitmap); // 选择对象
SetMapMode(hdcMem, GetMapMode(hDC)); // 设置映射模式
BITMAP bm; // 得到位图对象
GetObject(hBitmap, sizeof(BITMAP), &bm);
BitBlt(hDC, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); //位图复制
::ReleaseDC(hWnd, hDC); // 释放设备环境句柄
DeleteDC(hdcMem); // 删除内存环境
::CloseClipboard(); // 关闭剪贴板

  多数据项和延迟提交技术

  要把数据放入剪贴板,在打开剪贴板后一定要调用EmptyClipboard()函数清除当前剪贴板中的内容,而不可以在原有数据项基础上追加新的数据项。但是,可以在EmptyClipboard()和CloseClipboard()调用之间多次调用SetClipboardData()函数来放置多个不同格式的数据项。例如:

OpenClipboard(hWnd);
EmptyClipboardData();
SetClipboardData(CF_TEXT, hGMemText);
SetClipboardData(CF_BITMAP, hBitmap);
CloseClipboard();


  这时如果用CF_TEXT或CF_BITMAP等格式标记去调用IsClipboardFormatAvailable()都将返回TRUE,表明这几种格式的数据同时存在于剪贴板中。以不同的格式标记去调用GetClipboardData()函数可以得到相应的数据句柄。

  对于多数据项的剪贴板数据,还可以用CountClipboardFormats()和EnumClipboardFormats()函数得到当前剪贴板中存在的数据格式数目和具体的数据格式。EnumClipboardFormats()的函数原型为:

UINT EnumClipboardFormats(UINT format);


  参数format指定了剪贴板的数据格式。如果成功执行将返回format指定的格式的下一个数据格式值,如果format为最后的数据格式值,那么将返回0。由此不难写出处理剪贴板中所有格式数据项的程序段代码:

UINT format = 0; // 从第一种格式值开始枚举
OpenClipboard(hWnd);
while(format = EnumClipboardFormats(format))
{
…… // 对相关格式数据的处理
}
CloseClipboard();


  在数据提供进程创建了剪贴板数据后,一直到有其他进程获取剪贴板数据前,这些数据都要占据内存空间。如在剪贴板放置的数据量过大,就会浪费内存空间,降低对资源的利用率。为避免这种浪费,可以采取延迟提交(Delayed rendering)技术,即由数据提供进程先创建一个指定数据格式的空(NULL)剪贴板数据块,直到有其他进程需要数据或自身进程要终止运行时才真正提交数据。

  延迟提交的实现并不复杂,只需剪贴板拥有者进程在调用SetClipboardData()将数据句柄参数设置为NULL即可。延迟提交的拥有者进程需要做的主要工作是对WM_RENDERFORMAT、WM_DESTORYCLIPBOARD和WM_RENDERALLFORMATS等剪贴板延迟提交消息的处理。

  当另一个进程调用GetClipboardData()函数时,系统将会向延迟提交数据的剪贴板拥有者进程发送WM_RENDERFORMAT消息。剪贴板拥有者进程在此消息的响应函数中应使用相应的格式和实际的数据句柄来调用SetClipboardData()函数,但不必再调用OpenClipboard()和EmptyClipboard()去打开和清空剪贴板了。在设置完数据有也无须调用CloseClipboard()关闭剪贴板。如果其他进程打开了剪贴板并且调用EmptyClipboard()函数去清空剪贴板的内容,接管剪贴板的拥有权时,系统将向延迟提交的剪贴板拥有者进程发送WM_DESTROYCLIPBOARD消息,以通知该进程对剪贴板拥有权的丧失。而失去剪贴板拥有权的进程在收到该消息后则不会再向剪贴板提交数据。另外,在延迟提交进程在提交完所有要提交的数据后也会收到此消息。如果延迟提交剪贴板拥有者进程将要终止,系统将会为其发送一条WM_RENDERALLFORMATS消息,通知其打开并清除剪贴板内容。在调用SetClipboardData()设置各数据句柄后关闭剪贴板。

  下面这段代码将完成对数据的延迟提交,WM_RENDERFORMAT消息响应函数OnRenderFormat()并不会立即执行,当有进程调用GetClipboardData()函数从剪贴板读取数据时才会发出该消息。在消息处理函数中完成对数据的提交:

  进行延迟提交:

HWND hWnd = GetSafeHwnd(); // 获取安全窗口句柄
::OpenClipboard(hWnd); // 打开剪贴板
::EmptyClipboard(); // 清空剪贴板
::SetClipboardData(CF_TEXT, NULL); // 进行剪贴板数据的延迟提交
::CloseClipboard(); // 关闭剪贴板


  在WM_RENDERFORMAT消息的响应函数中:

DWord dwLength = 100; // 要复制的字串长度
HANDLE hGlobalMemory = GlobalAlloc(GHND, dwLength + 1); // 分配内存块
LPBYTE lpGlobalMemory = (LPBYTE)GlobalLock(hGlobalMemory); // 锁定内存块
for (int i = 0; i 〈 dwLength; i++) // 将"*"复制到全局内存块
*lpGlobalMemory++ = '*';
GlobalUnlock(hGlobalMemory); // 锁定内存块解锁
::SetClipboardData(CF_TEXT, hGlobalMemory); // 将内存中的数据放置到剪贴板

 

  DSP和自定义数据格式的使用

  Windows系统预定义了三个带“DSP”前缀的数据格式:CF_DSPTEXT、CF_DSPBITMAP和CF_DSPMETAFILEPICT。这是一些伪标准格式,用于表示在程序中定义的私有剪贴板数据格式。对于不同的程序,这些格式的规定是不同的,因此这些格式只针对某一具体程序的不同实例才有意义。

  为使用DSP数据格式,必须确保进程本身与剪贴板拥有者进程同属一个程序。可以调用GetClipboardOwner()函数来获取剪贴板拥有者窗口句柄,并调用GetClassName()来获取窗口类名:

HWND hClipOwner = GetClipboardOwner();
GetClassName(hClipOwner, &ClassName, 255);

  如果剪贴板拥有者窗口类名同本进程的窗口类名一致,就可以使用带有DSP前缀的剪贴板数据格式了。
除了使用Windows预定义的剪贴板数据格式外,也可以在程序中使用自定义的数据格式。对于自定义的数据格式lpszFormat,可以调用RegisterClipboardFormat()函数来登记,并获取其返回的格式标识值:

UINT format = RegisterClipboardFormat(lpszFormat);

  对此返回的格式标识值的使用与系统预定义的格式标识是一样的。可以通过GetClipboardFormatName()函数来获取自定义格式的ASCII名。

  小结

  本文主要对Windows编程中的剪贴板机制作了较为深入的讨论,对其中常用的文本、位图、DSP和自定义数据格式的使用方法以及多数据项和延迟提交等重要技术一并做了阐述。并给出了具体的程序示例代码,使读者能够更好的掌握剪贴板机制的使用。

 

上下文章:

 

上一篇文章: 巧用计划任务实现人性化定时关机 下一篇文章: 打造“好色”电脑全攻略

相关文章:

  • Windows 7用户界面与互动模式
  • Windows操作系统的发展简史
  • Windows 7内置定位服务引发安全疑虑
  • Windows7 演变中的故障诊断特性
  • Windows Vista的安全性高过XP七倍

相关软件:

  • Windows优化大师 v8.0 Build 8.1105 标准版
  • Windows优化大师 v7.78 Build 7.1119 繁体中文版
  • Windows优化大师 v8.0 Build 8.1105 免费版
  • eDonkey2000 Client for Windows V1.4.6
  • Windows木马清道夫 2008 11.3 Build 1017 上网必备版
  • VMware Workstation for Windows V5.5.2 Build 29772

 

快速导航

  • 网络学院
  • 精品汇聚
  • 字体下载
  • 教程下载
  • ASP源码
  • PHP源码
  • Net源码
  • JSP 源码

软件应用分类导航

  • 即时通讯
  • 网络工具
  • 系统工具
  • 磁盘工具
  • 媒体工具
  • 光盘工具
  • 实用工具
  • 杂类工具
  • 安全相关
  • 教育类别
  • 行业工具
  • 手机数码

本类经典文章推荐

  • 占用0%资源 HOST文件打造迷你
  • 磁盘空间整理原来也可以这么简单
  • 5个最出色必须拥有的 XP管理插件
  • 提防PQMAGIC和GHOST的一些误操作
  • 安全第一:重要文件选删除还是粉碎
  • 一键GHOST 硬盘版的安装运行教程
  • 适合Win Vista与新手的鼠标手势
  • 巧借Everest为系统服务“拍个照”
  • 驱动精灵完全革新版2008 Beta5
  • 大翻新 新版优化大师8.0Beta探秘

系统工具阅读排行

  • 快速恢复 矮人DOS工具箱使用方法
  • 夏季CPU降温专家:CPUCool
  • 硬盘分区管理工具谁执牛耳
  • 桌面背景攻略
  • 见招拆招 密码破解轻而易举自成高...
  • 快点再快点!Netpas网络加速器试用...
  • 程序监控专家让程序按需运行
  • 让ADSL开机后自动拨号连接网络
  • WINDOWS系列工具 画图 阶段教学
  • 浅谈MSconfig工具的使用方法

软件应用阅读总排行

  • 教你怎么把别人漂亮的QQ空间克隆一...
  • WinXp下的硬盘分区大师
  • 教你免费领养到QQ宠物的六种途径
  • 内网用好UPNP BT、电驴下载大提速
  • 网友送链接 让你免费穿上QQ秀
  • 快速升级为太阳用户
  • 快速恢复 矮人DOS工具箱使用方法
  • 打破无聊与难学 另类五笔学习方法
  • 截取视频我不需要工具
  • 夏季CPU降温专家:CPUCool

广告位置

字母检索 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 回到顶部

关于我们 | 版权声明 | 免责条款 | 广告联系 | 软件发布 | 下载帮助 | 下载排行 | 网站地图 | 特别鸣谢 | 友情连接

copyright; 2005-2008 D9soft.com 第九软件网 版权所有