概述
说明
剪贴板是内存中的一块共享区域,两个进程间通过共享剪贴板中的数据实现进程间通信的目的。
在本节课中,主要讲了当剪贴板中的数据是内存块对象时的操作方法。
在剪贴板编程时,对于数据是内存块对象的情况,在申请内存块时必须使用函数GlobalAlloc(),并且必须指定标识GMEM_MOVEALBLE,
在从剪贴板中取数据时也要对这一情况进行处理:获得内存块对象句柄,转换为指针再使用。
★ 写剪贴板步骤
①打开剪贴板(OpenClipboard)
②清空剪贴板(获得该剪贴板使用权)(EmptyClipboard)
③申请内存块(GlobalAlloc)
④锁定该内存块,使内存块对象句柄转换为指针以获得地址从而往该地址写数据(GlobalLock)
⑤往该地址写数据
⑥往剪贴板写数据(SetClipboardData)
⑦解除锁定(GlobalUnlock)
⑧关闭剪贴板(CloseClipboard)
★ 从剪贴板取数据步骤
①打开剪贴板(OpenClipboard)
②判断是否是可以取的数据类型或根据不同数据类型做不同处理(IsClipboardFormatAvailable)
③获得某种类型的剪贴板对象句柄(GetClipboardData)
④锁定该句柄,获得指针(GlobalLock)
⑤使用该指针
⑥解除锁定(GlobalUnlock)
⑦关闭剪贴板
NOTE:从剪贴板取数据不能清空(EmptyClipboard), 原因你懂的!
关于解除锁定的调用位置,我认为可以放在关闭剪贴板之前的最后位置,当然孙鑫老师在视频里讲的时候把接触锁定操作放在紧接着获得指针之后的位置程序也没有问题。
相关函数
①打开剪贴板
BOOL OpenClipboard(
HWND hWndNewOwner //[in] 拥有打开的剪贴板的窗口句柄,如果为NULL则打开的剪贴板和当前任务关联
);
成功返回非0,失败返回0
eg.
if(::OpenClipboard(m_hWnd)) //打开,从CWnd类继承来的类都有m_hWnd句柄成员
{
MessageBox(_T("打开剪贴板成功"));
}
②清空剪贴板
BOOL EmptyClipboard(
void
);
成功返回非0,失败返回0
eg.
EmptyClipboard();
③申请内存块
HGLOBAL GlobalAlloc(
UINT uFlags, //属性,常用的有GMEM_FIXED, GMEM_MOVEABLE
SIZE_T dwBytes //申请大小,字节单位
);
eg.
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, 100); //申请100字节内存块
④锁定,获得指针
LPVOID GlobalLock(
HGOBAL hMem
);
返回值为空指针,要根据需要把空指针转换为任何想要的指针。
eg.
char* pBuf = (char*)GlobalAlloc(GMEM_MOVEABLE, 100); //锁定,获得指针
strcpy(pBuf, "hello world!"); //使用该指针
GlobalUnlock(hMem); //解除锁定
⑤往剪贴板写数据
HANDLE SetClipboardData(
UINT uFormat, //剪贴板格式,分为标准格式和注册格式
HANDLE hMem //要写的数据句柄,如果是内存对象则是该对象的句柄
);
eg.
SetClipboardData(CF_TEXT, hMem); //写文本格式数据,该数据在内存块对象句柄hMem对应的块中
⑥从剪贴板读取数据
HANDLE GetClipboardData(
UINT uFormat //剪贴板格式
);
以内存块对象为例
eg.
HANDLE hData = GetClipboardData(CF_TEXT); //获得该内存块对象句柄
char* pBuf = (char*)GlobalLock(hData); //根据句柄获得指针值
SetDlgItemText(IDC_EDIT_INFO, pBuf); //使用该指针对应数据
GlobalUnlock(hMem); //解除锁定
⑦判断是否是可以处理的剪贴板类型
BOOL IsClipboardFormatAvailable(
UINT format //[in] 剪贴板格式
);
如果是可用的返回非0,不可用返回0
eg.
if(IsClipboardFormatAvailable(CF_TEXT))
{
//codes
}
else if(IsClipboardFormatAvailable(CF_BITMAP))
{
//codes
}
//codes
⑧关闭剪贴板
BOOL CloseClipboard(
void
);
eg.
CloseClipboard();
例子
/往剪贴板写数据,数据为一个内存块对象
if(::OpenClipboard(m_hWnd))
{
EmptyClipboard(); //清空
HGLOBAL hMem = NULL;
CString str = "";
GetDlgItemText(IDC_EDIT_INFO, str); //取得编辑框控件中的值
hMem = GlobalAlloc(GMEM_MOVEABLE, str.GetLength() + 1); //分配空间
char* pBuf = GlobalLock(hMem); //锁定,获得地址
strcpy(pBuf, str); //往该内存区域写值
SetClipboardData(CF_TEXT, hMem); //设置剪贴板值
GlobalUnlock(hMem); //解除锁定
CloseClipboard(); //关闭剪贴板
}
/从剪贴板取数据,数据为一个内存块对象
if(::OpenClipboard(m_hWnd))
{
if(IsClipboardFormatAvailable(CF_TEXT) //如果是这种类型的数据做这种处理
{
HANDLE hData = GetClipboardData(CF_TEXT); //获得该类型数据
char* pBuf = (char*)GlobalLock(hData); //锁定,句柄转换为指针
SetDlgItemText(IDC_EDIT_INFO2, pBuf); //设置编辑框值
GlobalUnlock(hMem); //解除锁定
}
else //其他类型数据
{
//codes
}
CloseClipboard(); //关闭剪贴板
}
补充
如果是位图格式的数据则不涉及到锁定解锁等步骤,因此锁定的目的是获得指针并往内存区域写值,而如果是位图则可以写剪贴板数据的时候写该位图的句柄就可以。
eg.
//写剪贴板
if(::OpenClipboard(m_hWnd))
{
EmptyClipboard();
HBITMAP hBitmap = NULL;
hBitmap = ::LoadBitmap(NULL, MAKEINTRESOURCE(IDB_BITMAP1)); //加载位图,获得该位图句柄
SetClipboardData(CF_BITMAP, hBitmap); //写剪贴板数据,类型为CF_BITMAP
CloseClipboard();
}
//读剪贴板
if(::OpenClipboard(m_hWnd))
{
HANDLE hData = GetClipboardData(CF_BITMAP); //获得该位图句柄
//codes
}
最后
以上就是勤劳龙猫为你收集整理的孙鑫 第十七课进程间通信之一 剪贴板的全部内容,希望文章能够帮你解决孙鑫 第十七课进程间通信之一 剪贴板所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复