进程的通信 - 剪切板

news2024/11/18 10:33:00

剪切板是系统维护管理的一块内存区域,本机的所有进程都可以访问。当一个进程复制数据时,先将数据放在该内存区,当另一个进程粘贴时,则是从该内存区块取出数据

剪切板操作:

其实在剪切板中也就那几个API在使用,下面会介绍几个常用的API,然后会给出一个demo示例

剪切板打开—OpenClipboard

BOOL OpenClipboard(
  [in, optional] HWND hWndNewOwner
);

OpenClipboard函数用来打开剪切板(放数据前的笔要操作)。参数hWndNewOwner指向一个窗口句柄,即代表是这个窗口打开的剪切板,如果这个参数设置为NULL,则以当前任务来打开剪切板 。如果有另一个窗口打开了剪切板,则函数失败,返回零。

 清空剪切板—EmptyClipboard

BOOL EmptyClipboard();

这个函数将清空剪贴板,并释放剪贴板中数据的句柄,然后将剪贴板的所有权分配给当前打开剪贴板的窗口。

因为剪贴板是所有进程都可以访问的,所以应用程序在使用这个剪贴板时,有可能已经有其他的应用程序把数据放置到了剪贴板上,因此该进程打开剪贴板之后,就需要调用 EmptyClipboard 函数来清空剪贴板,释放剪贴板中存放的数据的句柄,并将剪贴板的所有权分配给当前的进程,这样做之后当前打开这个剪贴板的程序就拥有了剪贴板的所有权,因此这个程序就可以往剪贴板上放置数据了。

数据发送到剪切板—SetClipboardData

HANDLE SetClipboardData(
  [in]           UINT   uFormat,
  [in, optional] HANDLE hMem
);
  • 参数uFormat用来指定发送剪切板上的数据的格式

常见的有CF_BTMAP(bitmap类型),CF_TEXT(text类型),CT_DIB等

  • 参数hMen表示一个指定格式的数据句柄。 

如果hMen参数标识的是内存对象,则必须带有GME_MOVEABLE属性的函数分配对象。下面的GlobalAlloc函数可以创建这种标识的内存对象句柄。

应用程序在调用了 SetClipboardData 函数之后,系统就拥有了 hMem 参数所标识的数据对象,该应用程序可以读取这个数据对象,但是在应用程序调用 CloseClipboard 函数之前,它都是不能释放该对象的句柄的,或者锁定这个句柄,如果 hMem 标识一个内存对象,那么这个对象必须是利用 GMEM_MOVEABLE 标识调用 GlobalAlloc 函数为其分配内存的。

数据句柄—GlobalAlloc 

DECLSPEC_ALLOCATOR HGLOBAL GlobalAlloc(
  [in] UINT   uFlags,
  [in] SIZE_T dwBytes
);

GlobalAlloc函数上分配指定数目的字节

这里有读者可能会问:为什么我们在自己的应用程序中不使用 GlobalAlloc 函数来分配内存,而是要使用 malloc 或者 new  来实现?

其实,这个也只用稍微想想就知道了,使用 malloc 或者 new 分配的内存是在进程的私有地址空间上分配的,这块私有地址空间归这个进程所拥有,在之后对这块内存的读写会快很多,而全局内存不属于这个进程,你下次要去访问全局内存的时候,还得通过映射转换,这样肯定是运行效率低。

  • 第一个参数表示内存分配的属性,例如上面要求的GME_MOVEABLE表示分配可移动内存 。
  • 第二个参数表示分配的字节数。

函数执行成功,返回新分配内存对象的句柄,否则返回NULL。

锁定全局内存对象—GlobalLock

LPVOID GlobalLock(
  [in] HGLOBAL hMem
);

锁定全局内存对象并返回指向该对象内存块的第一个字节的指针。我们可以通过这个指针对这块内存数据存取,这也保证了其他进程不会对这块内存的数据修改。

  • 参数hMem表示全局内存对象的句柄。此句柄由 GlobalAlloc 或GlobalReAlloc函数返回。

每个内存对象的内部数据结构包括最初为零的锁计数。对于可移动内存对象(GME_MOVEABLE),全局锁定将计数递增 1,全局解锁函数将计数递减 1。锁定内存对象的内存块将保持锁定状态,直到其锁定计数减少到零,此时可以移动或丢弃它。

全局内存对象解锁—GlobalUnLock

BOOL GlobalUnlock(
  [in] HGLOBAL hMem
);

GlobalUnlock函数递减与分配了GMEM_MOVEABLE的内存对象关联的锁定计数

  • 参数hMem表示全局内存对象的句柄。此句柄由 GlobalAlloc 或GlobalReAlloc函数返回。 

若函数执行完后内存对象仍处于锁定状态,则函数返回非零值,如果减少计数后解锁内存对象,则函数返回零(GetLasrError返回NO_ERROR),如果函数失败,则返回零(GetLastError返回NO_ERROR以外的值)

剪切板中的数据格式判断—IsClipboardFormatAvaliable

BOOL IsClipboardFormatAvailable(
  [in] UINT format
);

该函数将确定剪贴板是否包含指定格式的数据。如果剪贴板格式可用,则返回值为非零值。否则返回零。

  • 参数format指明需要判断的格式

剪贴板中数据接收—GetClipboardData

HANDLE GetClipboardData(
  [in] UINT uFormat
);

GetClipboardData以指定格式从剪贴板检索数据。剪贴板之前必须已打开。函数成功,返回指定格式剪切板对象的句柄,失败返回NULL。

Demo示例

创建一个MFC项目

当接收按钮按下后,会打开剪切板,将上方编辑框里的内容放到剪切板内

当接收按钮按下后,则会将剪切板中的内容粘贴到上方编辑框中。

接收按钮程序:

void CClipDlg::OnBnClickedSendBtn()
{
	
	//打开剪切板
	if (OpenClipboard()) {
		//清空剪切板
		EmptyClipboard();

		char* szSendBuf;//要发送的数据

		//获取编辑框的内容
		CStringW strSendW;
		GetDlgItemText(IDC_SEND_EDIT, strSendW);

		CStringA  strSend = (CStringA)strSendW;
		//分配一个内存对象,内存对象的句柄就是hClip
		HANDLE hClip = GlobalAlloc(GMEM_MOVEABLE, strSend.GetLength() + 1);
			//句柄加锁
		szSendBuf = (char*)GlobalLock(hClip);

	
		//将指定字符串复制到目标字符串,若目标字符串大小小于指定字符串,则会溢出
		//第一个参数为目标字符串,第二个参数为指定字符串
		strcpy(szSendBuf, strSend);

		//TRACE("seSendBuf =%s", szSendBuf);
			//解锁
		GlobalUnlock(hClip);
		//将数据放在剪切板
		SetClipboardData(CF_TEXT, hClip);
		//关闭剪切板
		CloseClipboard();
	}
}

发送按钮程序:

void CClipDlg::OnBnClickedButton1()
{
	if (OpenClipboard()) {
		//先确认剪切板是否可用
		if (IsClipboardFormatAvailable(CF_TEXT)) {
			HANDLE hClip;
			char* pBuf;
			//向剪切板要数据
			hClip = GetClipboardData(CF_TEXT);
			pBuf = (char*)GlobalLock(hClip);

			

			USES_CONVERSION;
			LPCWSTR strBuf = A2W(pBuf);
			GlobalUnlock(hClip);
			//显示
			SetDlgItemText(IDC_RECV_EDIT, strBuf);
			
		}
		CloseClipboard();
	}
}

运行:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/11504.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CEF 桌面软件开发实战

作者介绍 刘晓伦liulun,资深桌面端开发工程师。目前在一家大型国有控股上市公司任职,主要负责桌面端产品的核心技术研发、重难点技术攻关,以及新技术的预研和技术储备工作,拥有十几年的软件开发经验,在 Electron 、 Qt…

湖南郴州知心世界岛主王瑞平将出新书《知心世界》谷传民为其顾问

最近几天,被谷传民起诉的大衣哥,终于又满血复活,他也通过网络给知心世界岛主王瑞平送去了祝福。 就在农民歌唱家大衣哥,给知心世界岛主王瑞平,送去真挚的祝福不久,著名导演谷传民那边也有了动作。 原来&…

AntDesignVue动态创建下拉菜单

最近项目需要,有需要动态创建下拉菜单的需求,特此记录一下。 vue版本:3.1.4 ant-design-vue版本:2.1.6 需求是下拉菜单项可以根据配置来控制是否显示,那么就需要用到 v-for 和 v-if 的结合。 v-for 和 v-if 是不能…

MOSFET N-CH 30V SM3323NHQAC-TRG、SI7114DN-T1-GE3场效应管

型号:SM3323NHQAC-TRG SM3323NHQAC 描述:N沟道 30V 54A 封装:DFN3x3D-8 型号:SI7114DN-T1-GE3 SI7114DN 描述:MOSFET N-CH 30V 11.7A PPAK1212-8 FET 类型:N 通道 技术:MOSFET(金属…

【C++进阶】map和set——中篇(AVL树的学习)

🎇C笔试强训 博客主页:一起去看日落吗分享博主的C刷题日常,大家一起学习博主的能力有限,出现错误希望大家不吝赐教分享给大家一句我很喜欢的话:夜色难免微凉,前方必有曙光 🌞。 🍁 &…

第8章 数据库连接池

*数据库连接池的基本思想:为数据库建立一个缓冲池,预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需要从缓冲池中取出一个,使用完毕后再放回 *数据库连接池负责分配、管理和释放数据库连接,…

Java 变量和数据类型

Java 变量和数据类型Java 变量Java变量概念变量使用的基本步骤案例:输出人的信息(年龄,成绩,性别,姓名)变量使用注意事项案例:变量使用注意事项程序中 号的使用案例数据类型整数类型基本介绍案…

Spring Bean的生命周期源码解析

文章目录前言零、Bean生命周期流程图一、加载类二、实例化前2.1、使用案例2.2、源码---InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()三、实例化3.1、Supplier创建对象3.2、工厂方法创建对象3.3、推断构造方法3.4、源码四、BeanDefinition的后置处理4…

在Ubuntu下安装地球物理学专业软件madagascar

1.下载安装文件 git clone https://github.com/ahay/src RSFSRC这一步搞好后会在当前路径下生成RSFSRC 文件夹 2.预安装 安装依赖软件 sudo apt-get install libxaw7-dev freeglut3-dev libnetpbm10-dev libgd-dev \ libplplot-dev libavcodec-dev libcairo2-dev libjpeg-d…

(设计模式)工厂模式

工厂模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用…

【C++】C++基础知识(五)---数组

C基础知识(五)1. 一维数组1.1 定义方式1.2 数组名用途1.3 案例分析2. 二维数组2.1 定义方式2.2 数组名用途2.3 案例分析3. 多维数组1. 一维数组 数组就是一个集合,里面存放了相同类型的数据元素。 特点: 1、数组中每个元素的数据…

探究并发和并行、同步和异步、进程和线程、阻塞和非阻塞、响应和吞吐等

一. 并发和并行 操作系统扫盲: 1. 对于单核cpu而言(不管单核单线程也好,单核多线程也罢),同一时间只能干一件事!!为了看起像可以“同时干多件事”,windows操作系统把cpu的时间划分为长短基本相同的时间区间…

Golang入门笔记(3)—— 运算符

本来这块代码,作为有了一点语言基础的人是真不想写的,因为和其他语言没有什么不同的地方,但是就怕 真的还有人看我的帖子,还真怕真的有初学者在看我帖子,所以还是贴心的抄了一遍。 和Java不同的地方 1. &变量取地址…

【Spring】一文带你吃透基于XML的DI技术

个人主页: 几分醉意的CSDN博客_传送门 文章目录💖基于XML的DI✨set注入💫基本语法💫和属性名无关💫给非自定义类属性赋值💫引用类型注入✨构造注入💫name属性💫index属性✨引用类型的…

哈希表(hash_table)的原理

一、hash_table的介绍 hash_table可提供对任何键值对的存取和删除操作。由于操作对象是键值对,所以hash table也可被视为一种字典结构(dictionary)。这种结构的用意在于提供常数时间的基本操作,就像stack或queue那样。乍听之下这几乎是不可能的任务&…

SpringBoot中使用Redis实现分布式锁

文章目录一。Redis实现分布式锁原理二。代码实现Redis分布式锁一。Redis实现分布式锁原理 以下内容为转载部分,主要介绍Redis实现分布式锁的背景: 转载博客:https://blog.csdn.net/fuzhongmin05/article/details/119251590 为什么需要分布式…

[附源码]计算机毕业设计JAVA高校创新创业项目管理系统

[附源码]计算机毕业设计JAVA高校创新创业项目管理系统 项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM…

数字化转型重塑企业竞争优势,SaaS电商系统助力锂电池行业实现降本增效

作为我国核心基础工业的关键材料之一,锂电池在汽车、医疗器械、航天航空、消费类电子产品等领域均可发挥重要作用。近年来,随着新能源汽车的快速发展有力带动了锂电池行业的市场需求,锂电池已成为化学电源应用领域中最具竞争力的电池&#xf…

Vue | Vue.js 实现过渡动画

🖥️ Vue .js专栏:Vue .js 实现过渡动画 🧑‍💼 个人简介:一个不甘平庸的平凡人🍬 ✨ 个人主页:CoderHing的个人主页 🍀 格言: ☀️ 路漫漫其修远兮,吾将上下而求索☀️ &#x1f44…

基于51单片机的智能路灯控制系统proteus仿真原理图PCB

功能: 0.本系统采用STC89C52作为单片机 1.LCD1602液晶实时显示当前时间/环境光强/工作模式 2.支持路灯故障检测 3.工作时间内(17~24时),两个路灯同时点亮,24时以后,B路灯关闭,若检测到由物体通过,路灯B点亮…