问题描述
需求:
1.客户端基于 MFC 实现,需要浏览器通过 URL Protocol 吊起本地客户端,并且传递参数
2.客户端只能单实例运行
3.如果本地客户端已经启动,再通过浏览器启动新的本地实例需要通过进程间通信,把参数传递给已经启动的进程,保证单实例运行
解决方案
单实例运行参考链接地址:
http://blog.csdn.net/zoomcloudmeetings/article/details/70141427
进程间通信通过 WM_COPYDATA 实现方式,参考地址:
http://www.cnblogs.com/zhuyf87/archive/2013/03/03/2941620.html
完成进程间通信最简单的方式就是发送 WM_COPYDATA 消息,在程序检测到已经有进程启动的时候,发送消息
(1)发送WM_COPYDATA消息
SendMessage(接收窗口句柄, WM_COPYDATA, (WPARAM)发送窗口句柄, (LPARAM)©Data);
BOOL CVeoApp::InitInstance()
{
//单例进程模式
HANDLE hMutex=::CreateMutex(NULL,TRUE,_T("AtlasSegment"));
if(hMutex!=NULL)
{
if(GetLastError()==ERROR_ALREADY_EXISTS)
{
// 向已经启动的进程传递参数、指令
LRESULT copyDataResult; //copyDataResult has value returned by other app
CWnd *pOtherWnd = CWnd::FindWindowW(NULL, _T("埃塔远程诊疗"));
if (pOtherWnd)
{
// TODO 实例已经存在时处理逻辑
CString strDataToSend = AfxGetApp()->m_lpCmdLine;
COPYDATASTRUCT cpd;
cpd.dwData = 0;
cpd.cbData = (strDataToSend.GetLength() + 1)*sizeof(TCHAR); //data length
cpd.lpData = (void*)strDataToSend.GetBuffer(cpd.cbData); //data buffer
copyDataResult = pOtherWnd->SendMessage(WM_COPYDATA,(WPARAM)AfxGetApp()->m_pMainWnd->GetSafeHwnd(),(LPARAM)&cpd);
strDataToSend.ReleaseBuffer();
}
CloseHandle(hMutex);
return FALSE;
}
}
…… ……
}
(2)接收WM_COPYDATA消息:
WM_COPYDATA
wParam = (WPARAM)(HWND) hwnd;
lParam = (LPARAM)(PCOPYDATASTRUCT) pcds;
hwnd: Handle to the window passing the data. (数据发送方的句柄,接收方可以通过此句柄向发送方反馈数据)
pcds: Pointer to a COPYDATASTRUCT structure that contains the data to be passed.
Return Values
If the receiving application processes this message, it should return TRUE; otherwise, it should return FALSE.
lParam包含了接收到的数据,在处理之前需要将类型转换为COPYDATASTRUCT结构体。接收方应认为这些数据是只读的,并且只在处理该消息的过程中有效。如果想修改这些数据,应该把它们复制到本地buffer。(The receiving application should consider the data read-only. The pcds parameter is valid only during the processing of the message. The receiving application should not free the memory referenced by pcds. If the receiving application must access the data after SendMessage returns, it must copy the data into a local buffer. )
由于发送方在接收方处理WM_COPYDATA消息完毕前都是处于等待(SendMessage阻塞)中,所以接收方应当尽快处理WM_COPYDATA消息。
示例代码片段(MFC):
BOOL CVeoDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CString strRecievedText = (LPCTSTR) (pCopyDataStruct->lpData);
// 业务逻辑
initVeoHandle(strRecievedText);
return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}