CE 进程间通信
WINCE下进程间通信常用的方式有:剪贴板(Clipboard),网络套接字(Socket),WM_COPYDATA消息,共享内存,管道(消息队列),注册表等
剪贴板
///////////////////////////剪贴板发送数据//////////////////////////////////
)
{ //把数据放入剪贴板,并发送一个键盘粘贴消息给当前获得焦点的输入框。
HGLOBAL hMemClip; //指向分配的内存块
if (AfxGetMainWnd()->OpenClipboard()) //打开剪贴板
{ EmptyClipboard(); //清空剪贴板
hMemClip = GlobalAlloc(GHND,nlen*); //分配可移动内存块
WCHAR *buff_dest=(WCHAR *)GlobalLock(hMemClip); //锁定内存块
memcpy(buff_dest,szBuf,nlen*); //数据装入内存块
GlobalUnlock(hMemClip); //解锁内存块
SetClipboardData(CF_UNICODETEXT,hMemClip); //将存放有数据的内存块放入剪贴板的资源管理中
CloseClipboard(); //关闭剪贴板
//向有光标焦点的控件发送虚拟键盘消息“CTRL + V”再加一个回车
keybd_event(, , ); //V
keybd_event(, , ); //CTRL
keybd_event(, KEYEVENTF_KEYUP, );
keybd_event(, KEYEVENTF_KEYUP, );
keybd_event(, , ); //Enter
keybd_event(, KEYEVENTF_KEYUP, );
}
}
!!以下部分转自http://blog.csdn.net/firehood_/article/details/6269310 以下代码未作测试详细请看博客原地址
谢谢firehood
WM_COPYDATA消息
// 发送端////////////////////////////////////////////////////////////////////////
void SendMsg(HWND hwnd,LPVOID lpData,DWORD dwSize)
{
// 填充COPYDATASTRUCT结构
COPYDATASTRUCT cpd;
cpd.cbData = dwSize;
cpd.lpData = lpData;
// 向指定窗口发送WM_COPYDATA消息,不能用PostMessage方式发送
::SendMessage(hwnd, WM_COPYDATA, NULL,(LPARAM)&cpd);
}
TCHAR *data=_T("要发送的内容");
SendMsg(::FindWindow(NULL,_T();
// 接收端////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR data[]={};
switch (message)
{
case WM_COPYDATA:
{
COPYDATASTRUCT *pCopyDataStruct=(COPYDATASTRUCT *)lParam;
memcpy(data,pCopyDataStruct->lpData,pCopyDataStruct->cbData);
}
break;
// ...
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
共享内存
共享内存顾名思义是在内存中创建一个公共区域,供不同的进程间的数据共享。因为是直接对内存进行读写操作,效率非常高,所以共享内存特别适用于大批量的数据传输且实时性要求比较高的场合。
具体操作步骤如下:
1.进程A调用CreateFileMapping创建一个内存映射文件。
2.进程A调用MapViewOfFile获取到映射到文件的内存起始地址,调用memcpy往内存中拷贝数据。
3.进程B调用CreateFileMapping打开进程A创建的内存映射文件。
4.进程B调用MapViewOfFile获取到映射到文件的内存起始地址,调用memcpy从内存中读出数据。
5.通信完后进程A,B分别调用UnmapViewOfFile,CloseHandle取消内存映射和关闭内存映射对象句柄。
为了简化操作,这里封装了一个共享内存操作类,参考代码如下:
头文件CShareMemory.h:
/*******************************************************************
filename: CShareMemory.h
purpose: 封装了共享内存操作类
author: firehood
created: 2011.03.16
********************************************************************/
#ifndef _SHARE_MEMORY_H
#define _SHARE_MEMORY_H
class CShareMemory
{
public:
CShareMemory();
~CShareMemory();
public:
/**********************************************************
函数名:Open
功能: 创建或打开内存映射文件
参数:
[in]szMapName: 要创建的共享内存名称
[in]dwSize: 创建共享内存的大小
返回值:
0: 失败
1: 创建成功
2: 文件已存在
***********************************************************/
DWORD Open(LPCTSTR szMapName,DWORD dwSize);
/**********************************************************
函数名:Read
功能: 从共享内存指定位置读取数据
参数:
[out]pBuf: 存放读取的数据
[in]dwSize: 读取数据的大小
[in]dwOffset 距共享内存起始位置的偏移量
返回值:
TRUE: 成功 FALSE:失败
***********************************************************/
BOOL Read();
/**********************************************************
函数名:Write
功能: 从共享内存指定位置写入数据
参数:
[in]pBuf: 待写入的数据指针
[in]dwSize: 写入数据的大小
[in]dwOffset 距共享内存起始位置的偏移量
返回值:
TRUE: 失败 FALSE:失败
***********************************************************/
BOOL Write();
void Close(void);
private:
HANDLE m_hShareMemory;
LPVOID m_pMapBuffer;
HANDLE m_hAccessMutex;
};
#endif
源文件CShareMemory.cpp:
#include "stdafx.h"
#include "CShareMemory.h"
CShareMemory::CShareMemory()
{
m_hShareMemory = NULL;
m_pMapBuffer = NULL;
m_hAccessMutex =NULL;
}
CShareMemory::~CShareMemory()
{
Close();
}
DWORD CShareMemory::Open(LPCTSTR szMapName,DWORD dwSize)
{
DWORD dwRet = ;
if(szMapName == NULL)
;
if(m_hShareMemory)
{
Close();
}
// 创建内存映射文件对象
m_hShareMemory = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,,dwSize,szMapName);
if(!m_hShareMemory)
{
;
}
// 内存映射文件对象已存在
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
dwRet = ;
}
// 获取内存映射文件指针
m_pMapBuffer = MapViewOfFile(m_hShareMemory,FILE_MAP_ALL_ACCESS,,,);
if(!m_pMapBuffer)
{
CloseHandle(m_hShareMemory);
;
}
// 创建互斥体,用于读写同步
TCHAR szMutexName[MAX_PATH];
_tcscpy(szMutexName, szMapName);
_tcscat(szMutexName, _T("_Mutex"));
m_hAccessMutex=CreateMutex(NULL, FALSE, szMutexName);
if(!m_hAccessMutex)
{
Close();
;
}
return dwRet;
}
BOOL CShareMemory::Read(void* pBuf,DWORD dwSize,DWORD dwOffset)
{
BOOL bRet;
if(!m_pMapBuffer) return FALSE;
if(WaitForSingleObject(m_hAccessMutex,INFINITE)==WAIT_OBJECT_0)
{
memcpy(pBuf,(BYTE*)m_pMapBuffer+dwOffset,dwSize);
bRet = TRUE;
}
ReleaseMutex(m_hAccessMutex);
return bRet;
}
BOOL CShareMemory::Write(const void* pBuf,DWORD dwSize,DWORD dwOffset)
{
BOOL bRet;
if(!m_pMapBuffer) return FALSE;
if(WaitForSingleObject(m_hAccessMutex,INFINITE)==WAIT_OBJECT_0)
{
memcpy((BYTE*)m_pMapBuffer+dwOffset,pBuf,dwSize);
bRet = TRUE;
}
ReleaseMutex(m_hAccessMutex);
return TRUE;
}
void CShareMemory::Close(void)
{
if(m_hShareMemory)
{
UnmapViewOfFile(m_pMapBuffer);
CloseHandle(m_hShareMemory);
m_pMapBuffer = NULL;
m_hShareMemory = NULL;
}
if(m_hAccessMutex)
{
CloseHandle(m_hAccessMutex);
m_hAccessMutex = NULL;
}
}
管道(消息队列)
WINCE并不支持类似于PC机上匿名管道、命名管道的通信方式,但CE下提供了一种点对点消息队列的方法,其工作原理与管道非常类似:在通信的两端分别建立一个读队列和写队列,写进程往消息队列一端写入数据,读进程从消息队列另一端读取数据。
消息队列相关的系统API主要有:CreateMsgQueue()、ReadMsgQueue()、WriteMsgQuue()和CloseMsgQueue()。为了方便消息队列的操作,封装了一个消息队列操作类,参考代码如下:
头文件(CMsgQueue.h)
/*******************************************************************
filename: CMsgQueue.h
purpose: 封装了WINCE下消息队列操作类
author: firehood
created: 2011.03.23
********************************************************************/
#ifndef _MSG_QUEUE_H
#define _MSG_QUEUE_H
// 消息队列访问模式
enum ACCESSMODE
{
ReadMode = ,
WriteMode
};
// 定义消息回调函数
typedef BOOL (CALLBACK *MsgQueueCallBack)(PVOID pData, DWORD dwSize);
class CMsgQueue
{
public:
CMsgQueue();
CMsgQueue(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode);
~CMsgQueue();
public:
/**********************************************************************
函数名:Create
功能: 创建或打开消息队列
参数:
[in]lpQueueName: 消息队列名称
[in]dwSize: 每条消息的最大长度
[in]accessMode 消息队列访问模式 ReadMode:只读 WriteMode:只写
返回值:
成功:TRUE 失败:FALSE
**********************************************************************/
BOOL Create(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode);
/**********************************************************************
函数名:Read
功能: 从消息队列中读取一条消息
参数:
[out]lpBuffer: 存放读取的数据
[in] dwSize: 读取数据的大小
[out]lpNumberOfBytesRead 实际读取数据的大小
[in] dwTimeout 读取超时时间(ms) 0 立即返回 INFINITE 永远等待直至消息队列中有数据
返回值:
成功:TRUE 失败:FALSE
***********************************************************************/
BOOL Read(LPVOID lpBuffer,DWORD dwSize,LPDWORD lpNumberOfBytesRead,DWORD dwTimeout = );
/**********************************************************************
函数名:Write
功能: 向消息队列中写入一条消息
参数:
[in]lpBuffer: 待写入的数据
[in]dwSize: 写入数据的大小
返回值:
成功:TRUE 失败:FALSE
**********************************************************************/
BOOL Write(LPVOID lpBuffer,DWORD dwSize);
// 设置消息回调函数
BOOL SetMsgCallBack(MsgQueueCallBack pCallBackFun, PVOID pParam);
// 关闭消息队列
void Close(void);
private:
// 开启读取消息线程
BOOL StartRevMsgThread(void);
// 停止读取消息线程
BOOL StopRevMsgThread(void);
// 读取消息线程
static void WINAPI RevMsgThread(LPVOID pParam);
private:
HANDLE m_hMsgQueue;
DWORD m_dwQueueSize;
MsgQueueCallBack m_MsgCallBack;
HANDLE m_hRevMsgThread;
BOOL m_bThreadExit;
};
#endif
源文件(CMsgQueue.cpp)
#include "stdafx.h"
#include "CMsgQueue.h"
CMsgQueue::CMsgQueue()
{
m_hMsgQueue = NULL;
m_dwQueueSize = ;
m_hRevMsgThread = NULL;
m_bThreadExit = FALSE;
m_MsgCallBack = NULL;
}
CMsgQueue::CMsgQueue(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode)
{
Create(lpQueueName,dwSize,accessMode);
}
CMsgQueue::~CMsgQueue()
{
Close();
}
BOOL CMsgQueue::Create(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode)
{
if(!m_hMsgQueue)
{
m_hRevMsgThread = NULL;
m_bThreadExit = FALSE;
m_MsgCallBack = NULL;
m_dwQueueSize = dwSize;
// 创建消息队列
MSGQUEUEOPTIONS options;
options.dwSize = sizeof(options);
options.dwFlags = MSGQUEUE_NOPRECOMMIT|MSGQUEUE_ALLOW_BROKEN;
options.dwMaxMessages = ;
options.cbMaxMessage = dwSize;
options.bReadAccess = (accessMode==ReadMode) ? TRUE : FALSE;
m_hMsgQueue =::CreateMsgQueue(lpQueueName,&options);
}
return TRUE;
}
void CMsgQueue::Close(void)
{
if(m_hMsgQueue)
{
::CloseMsgQueue(m_hMsgQueue);
m_hMsgQueue = NULL;
}
// 注销回调函数
SetMsgCallBack(NULL,NULL);
}
BOOL CMsgQueue::Read(LPVOID lpBuffer,DWORD dwSize,LPDWORD lpNumberOfBytesRead,DWORD dwTimeout)
{
if(m_hMsgQueue == NULL || lpBuffer == NULL)
{
return FALSE;
}
DWORD dwFlag = ;
// 从消息队列头部读出数据
if(!::ReadMsgQueue(m_hMsgQueue,lpBuffer,dwSize,lpNumberOfBytesRead,dwTimeout,&dwFlag))
{
return FALSE;
}
return TRUE;
}
BOOL CMsgQueue::Write(LPVOID lpBuffer,DWORD dwSize)
{
if(m_hMsgQueue == NULL || lpBuffer == NULL)
{
return FALSE;
}
// 向消息队列尾部写入数据
,))
{
return FALSE;
}
return TRUE;
}
BOOL CMsgQueue::SetMsgCallBack(MsgQueueCallBack pCallBackFun, PVOID pParam)
{
m_MsgCallBack = pCallBackFun;
if (m_MsgCallBack)
{
if (m_hRevMsgThread == NULL)
{
// 开启读取线程
return StartRevMsgThread();
}
}
else
{
if (m_hRevMsgThread)
{
// 关闭读取线程
return StopRevMsgThread();
}
}
return TRUE;
}
BOOL CMsgQueue::StartRevMsgThread(void)
{
if(m_hRevMsgThread == NULL)
{
// 创建读取消息线程
m_hRevMsgThread = CreateThread(NULL, , (LPTHREAD_START_ROUTINE)CMsgQueue::RevMsgThread, , NULL);
}
return (m_hRevMsgThread ? TRUE : FALSE);
}
BOOL CMsgQueue::StopRevMsgThread(void)
{
if(m_hRevMsgThread)
{
m_bThreadExit = TRUE;
// 等待线程成功退出
WaitForSingleObject(m_hRevMsgThread,INFINITE);
CloseHandle(m_hRevMsgThread);
m_hRevMsgThread = NULL;
m_hRevMsgThread = FALSE;
}
return ((m_hRevMsgThread==NULL) ? TRUE : FALSE);
}
void WINAPI CMsgQueue::RevMsgThread(LPVOID pParam)
{
CMsgQueue *pMsgQueue=(CMsgQueue*)pParam;
LPVOID lpBuffer;
DWORD dwReadNums=;
lpBuffer=(LPVOID)malloc(pMsgQueue->m_dwQueueSize);
while(!pMsgQueue->m_bThreadExit)
{
if(!pMsgQueue->m_hMsgQueue )
break;
// 从消息队列中读取一条消息(阻塞模式)
BOOL ret=pMsgQueue->Read(lpBuffer,pMsgQueue->m_dwQueueSize,&dwReadNums,INFINITE);
printf("Read ret=%d,dwReadNums=%d/n",ret,dwReadNums);
)
{
// 调用回调函数
if(pMsgQueue->m_MsgCallBack)
pMsgQueue->m_MsgCallBack(lpBuffer,dwReadNums);
}
}
printf("RevMsgThread exit.../n");
free(lpBuffer);
}
使用CMsgQueue类实现进程间通信:
// 发送进程
//////////////////////////////////////////////////////////////////////////////////
// 创建只写消息队列
CMsgQueue cMsgQueue(L,WriteMode);
// 往消息队列写数据
cMsgQueue.Write(L);
cMsgQueue.Close();
//////////////////////////////////////////////////////////////////////////////////
// 接收进程
//////////////////////////////////////////////////////////////////////////////////
// 声明消息回调函数
BOOL CALLBACK RecvMsgProc(PVOID pData, DWORD dwSize);
// 创建只读消息队列
CMsgQueue cMsgQueue(L,ReadMode);
// 设置消息回调函数
cMsgQueue.SetMsgCallBack(RecvMsgProc,NULL);
// 处理消息
BOOL CALLBACK RecvMsgProc(PVOID pData, DWORD dwSize)
{
printf("RecvMsgProc:Rev data Size=%d/n",dwSize);
wchar_t data[];
memcpy(data, pData,dwSize);
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////////
CE 进程间通信的更多相关文章
- WINCE下进程间通信(二)
WINCE下进程间通信(二) 接着前面的文章<WINCE下进程间通信(一)>,现在介绍进程间通信的另一种方法. 三.管道(消息队列) WINCE并不支持类似于PC机上匿名管道.命名管道的通 ...
- CE修改器修改DNF 测试视频 阿修罗提升智力增加攻击力
使用CE修改器来修改网络游戏,如DNF 测试视频: CE修改器:指的是Cheat Engine,字面上的意思指的是作弊引擎的意思,是一款内存修改编辑工具.通过修改游戏的内存数据来得到一些原本无法实现的 ...
- PreEmptive Dotfuscator and Analytics CE
PreEmptive Dotfuscator and Analytics CE Dotfuscator 是领先的 .NET 模糊处理程序和压缩程序,有助于防止程序遭到反向工程,同时使程序更小更高效.D ...
- C++进程间通信
# C++进程间通信 # 进程间通讯的四种方式:剪贴板.匿名管道.命名管道和邮槽 ## 剪切板 ## //设置剪切板内容 CString str; this->GetDlgItemText(ID ...
- android:使用Messenger进行进程间通信(一)
Messenger简介 Messenger和AIDL是实现进程间通信(interprocess communication)的两种方式. 实际上,Messenger的实现其实是对AIDL的封装. Me ...
- PHP 进程间通信——消息队列(msg_queue)
PHP 进程间通信--消息队列 本文不涉及PHP基础库安装.详细安装说明,请参考官网,或期待后续博客分享. 1.消息队列函数准备 <?php//生成一个消息队列的key$msg_key = ft ...
- WM_COPYDATA实现的不同进程间通信
进程间通信,通过SendMessage向另一进程发送WM_COPYDATA消息,实现不同进程间的消息通信. 需求:已写好一个工具软件,想在不更改当前的软件开发的前提下,实现为后面新开发的软件提供数据推 ...
- Linux学习笔记(12)-进程间通信|匿名管道
Linux的进程间通信有几种方式,包括,管道,信号,信号灯,共享内存,消息队列和套接字等-- 现在一个个的开始学习! ----------------------------------------- ...
- Visual Studio 2005 搭建Windows CE 6.0环境之准备
Microsoft Visual Studio 2005 Visual Studio 2005 Professional 官方90天试用版英文版:http://download.microsoft.c ...
随机推荐
- Angular JS的依赖注入
依赖注入是一个在组件中给出的替代了硬的组件内的编码它们的依赖关系的软件设计模式.这减轻一个组成部分,从定位的依赖,依赖配置.这有助于使组件可重用,维护和测试. AngularJS提供了一个至高无上的依 ...
- jquery点击获取子元素ID值
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Theoretical comparison between the Gini Index and Information Gain criteria
Knowledge Discovery in Databases (KDD) is an active and important research area with the promise for ...
- 在浏览器地址栏前添加自定义的ico图标
首先,我们需要预先制作一个图标文件,大小为16*16像素.文件扩展名为ico,然后上传到相应目录中. 在HTML源文件“<head></head>”之间添加如下代码: < ...
- HighChart报表之饼图
个人认为HighChart做报表还是很不错的,从报表的样式还是性能都是很不错的选择. 1.新建一个html页面,命名为:ReportTest.html <script type="te ...
- 什么是java?
Java是一种软件技术 是一种由美国SUN计算机公司(Sun Microsystems, Inc.)所研究而成的语言 是一种为 Internet发展的计算机语言 是一种使网页(Web Page) ...
- SQLSERVER2008 不能用IP连接数据库问题
本机安装的数据库只能用电脑名+"\"+实例名来访问,用“.”.“(local)”.“localhost”呀都不能访问.然后在网上挖资料呀,挖呀挖呀,终于挖到了解决办法. 1.不能用 ...
- sudo apt-get install apache2 php7.0 php7.0-mysql mysql-server
sudo apt-get install apache2 php7.0 php7.0-mysql mysql-server sudo apt-get install libapache2-mod-ph ...
- Git 的深入理解与GitHub托管服务(转)
源代码管理系统(SCM)与版本控制 版本控制是一种记录若干文件内容变化,以便将来查阅特定版本修订情况的系统. 本地版本控制系统 许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会 ...
- Java随笔三
1.接口: 1)接口不是类,不能使用new运算符实例化一个接口,而是对类的一组需求描述,这些类要遵循接口描述的统一格式进行定义.个人感觉像C语言中的函数在头文件中的预先声明,但是包含了一些类的特点,比 ...