记录一些学习小事

Work hard

统计

留言簿

阅读排行榜

评论排行榜

进程通信——剪贴板

由于在启动一个进程后,操作系统会给这个进程分配 4GB 的私有地址空间,至于为何有 4GB 这么大,

那得考虑进程的私有地址空间和实际物理内存地址空间之间的映射以及页交换等等细节问题了,这里不予讨论,

既然操作系统给每一个进程分配的是私有地址空间,自然,这段地址空间也只有这个进程自己才能访问了,
既然这段私有地址空间只能由进程本身访问,那也就说明别的进程是不能够随意的访问这个进程的地址空间的,

而上面又说任意两个进程之间是并能够互相访问对方的私有地址空间的,都不能访问了,那还通信个屁啊 ?

自然上面的访问对方进程的私有地址空间是行不通了,那应该还有其他办法的 !!!

如果我在物理内存中划分出一块内存,这一块内存不为任何的进程所私有,但是任何的进程又都可以访问这块内存,

那么 进程 A 就可以往这块内存中存放数据 Data ,然后 进程 B 也是可以访问这块内存的,从而 进程 B 就可以访问到数据 Data 了,

这样不就实现了 进程 A 进程 B 之间的通信了 !!!

而上面的这种思路就是剪贴板了。

当然解决进程间通信还有好几种思路,本文暂只介绍利用剪贴板来实现进程间的通信。
前面
这段话是我抄过来的,呵呵,自己写不了这种书面语。
我写一下我对剪贴板的使用,我也是新学的,有不对的地方还请大家指点。

向剪贴板中写入数据
打开剪贴板 OpenClipboard
清空剪贴板 EmptyClipboard
设置剪贴板数据SetClipboardData
关闭剪贴板CloseClipboard

从剪贴板读取数据
打开剪贴板 OpenClipboard
判断数据类型IsClipboardFormatAvailable
得到剪贴板数据GetClipboardData
关闭剪贴板CloseClipboard

我在说下具体的函数怎么用
Openclipboard大家在msdn上可以看到 仅有一个参数hWndNewOwner
这个参数表明那个窗口拥有剪贴板的使用权 已在此窗口中打开,别的窗口中调用openclipboard就会失败
这个参数可以设置成null。If this parameter is NULL, the open clipboard is associated with the current task
呵呵,这个设成null之后 在后边的 setclipboarddata 就不能采用延迟发送了。因为……等会说延迟发送就会知道了。(这是我试验得出的结论,应该没问题)
这个参数我们暂且设为窗口句柄 m_hWnd(我用的MFC编的)
EmptyClipboard这个函数就没什么说的了。就是清空剪贴板的数据 还有就是The function then assigns ownership of the clipboard to the window that currently has the clipboard open.
SetClipboardData( UINT uFormat, HANDLE hMem);
有两个参数第一个参数是数据类型 我们设置成CF_UNICODETEXT。
第二个参数是the hMem parameter identifies a memory object, the object must have been allocated using the function with the GMEM_MOVEABLE flag.
这句话得意思就是 hmem是块内存对象的句柄 这块内存要是GMEM_MOVEABLE 型的。这又要引进一个申请内存的函数。平常我们用的malloc new 等都是
在自己的进程中申请空间,如果用他们 我们的通信也就通不成了。所以我们要申请个全局的内存空间
GlobalAlloc(GMEM_MOVEABLE,dwBytes);第一个参数就是可移动的意思(当别人申请一块大空间的时候 比如我们申请的空间比较散乱占用了一部分空间 别人就申请不了一整块大的空间了。这样我们的空间如果是可移动的,就会被移动的凝聚一些,别人就有地方申请大的空间了,红色是我们申请的凌乱的空间,绿色是又想申请的一大块)。

这个我不在这里多讲,内存管理我懂的也不太多。不懂的可以找找内存管理方面的书。 第二个参数就是空间大小。

这样我们完成了设置剪贴板数据 ,然后我们关闭剪贴板就行了。
读取简单一些。
::OpenClipboard(m_hWnd)
IsClipboardFormatAvailable(CF_UNICODETEXT)//判断剪贴板内数据类型
HANDLE hClip=::GetClipboardData(CF_UNICODETEXT)//得到剪贴板的句柄
然后就是使用里面的数据了。这里要注意,一定要给数据上锁 ,就是说我们在使用数据的这个时间内,别人不准移动我们的内存。这个大家能理解吧。
TCHAR * p=(TCHAR *)GlobalLock(hClip);//强制装换成我们的宽字符  上锁
MessageBox(p);输出即可
  GlobalUnlock(hClip);  解锁
  ::CloseClipboard();
这就完成了,我贴一段代码上来哦

//这个是写入剪贴板
    if(!::OpenClipboard(m_hWnd))
    
{
        MessageBox(_T(
"打开剪切板失败"));
    }

    ::EmptyClipboard();
      CString str
=_T("hahaaha");
      HGLOBAL  hG
=GlobalAlloc(GMEM_MOVEABLE,sizeof(_T("hahaaha"))+2);
      _tcscpy_s((wchar_t 
*)GlobalLock(hG),sizeof(_T("hahaaha"))/2+1,str);
      GlobalUnlock(hG);
    ::SetClipboardData(CF_UNICODETEXT,hG);
    ::C
//这个是从剪贴板中读出数据
if(!::OpenClipboard(m_hWnd))
         
{
             MessageBox(_T(
"打开剪切板失败"));
            
return ;
         }

        
if (::IsClipboardFormatAvailable(CF_UNICODETEXT))
    
{

        HANDLE hClip
=::GetClipboardData(CF_UNICODETEXT);
        TCHAR 
* p=(TCHAR *)GlobalLock(hClip);
        MessageBox(p);
        GlobalUnlock(hClip);
        ::CloseClipboard();
    }

    
else
    
{
        MessageBox(_T(
"剪贴板的内容不是unicode"));
    }


然后最后我在说说延迟发送setclipboarddata 的第二个参数传为null 就为延迟发送
延迟发送就是一开始点写入剪贴板的时候不写入,然后另一个进程想要得到剪贴板里的信息的时候也就是在getclipboarddata时
系统会发个消息给我们以前的那个窗口 还记得openclipboard传的那个m_hWnd了吧,就是给这个窗口发个消息WM_RENDERFORMAT
然后你在这个消息响应函数中进行把数据写入剪贴板。
还有一种情况就是你在想粘贴的时候  你的原先写入的那个程序已经关闭了,这样的话你就帖不了了。 这样 还有一个消息
如果你选择了延迟发送 然后关闭应用程序的话,就会响应一个WM_RENDERALLFORMATS消息 那么你在这个响应函数中把你要写入剪贴板得数据
写入 就可以避免这种情况了。
啊 累死我了,可下写完了。。。。




posted on 2011-07-31 17:11 陈晓 阅读(2028) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理