WINDOWS COPYSTRUCT消息收发

本文介绍了一个作为应用程序与通信模块间消息传递的中间类库。该类通过创建隐藏窗口并使用WM_COPYDATA消息来发送和接收数据,实现了双向通信。文章详细展示了类的接口定义、消息发送流程及窗口创建和注册过程。

 公司不知道从哪里搞来的源代码,有个库是没有代码的,导师让我把它重写。这个库的的类是一个中间类,被应用程序用作收发消息,被通信模块也用作收发消息。

消息模式是COPYSTRUCT

大概的过程如下:

   应用模块收集设备的信息,比如设备状态,设备耗材等,通过这个中间类,发送给通信模块,通信模块接收到后,再发送主机。然后主机进行处理,主机应答后,再发回给

通信模块。通信模块收集到主机的指令后,通过这个中间类,再发送给应用模块,让应用模块继续处理或者完成。

该类接口是

class __declspec(dllexport) CIPC 
{
public:
 CIPC();
 virtual ~CIPC();

 bool Create(CString csTitle); 
 void Release();
 
 int Send(CString csRevWndTile, DWORD dwCode, LPVOID pData, DWORD dwSize);
 virtual int OnReceive(CString csSendWndTile, DWORD dwCode, LPVOID pData, DWORD dwSize) = 0;

private:
 class CManager *m_pManager;
};

 

class CManager
{
public:
 CManager(CIPC* pIPC);
 virtual ~CManager();
 
 //创建一个隐藏窗口,用于收发WINDOWS消息
 bool Create(CString csTitle);
 
 //释放窗口资源
 void Release();
   
 //发送消息函数
 //csRevWndTile 接受窗口名
 //dwCode   消息码,触发窗口的函数动作
 //pData   传递的数据
 //dwSize  数据大小S
 int Send(CString csRevWndTile, DWORD dwCode, LPVOID pData, DWORD dwSize);
   
private:
 bool RegisterWindow();  //注册窗口函数
 //void CreateWindow();
private:
 HWND m_hHandle;

};

 

 

Create函数用来创建一个隐藏的窗口,处理WINDOWS消息。实现方法为:

bool CManager::Create(CString csTitle)

 /*
    bool bRes = false;
 m_csSendWndTile = csTitle;
 CString strMyClass;
 try
 {
  strMyClass = AfxRegisterWndClass(0);
  TRACE("WindowName: %s\n", strMyClass);
 }
 
 catch (CResourceException* pEx)
 {
  AfxMessageBox( _T("Couldn't register class! (Already registered?)"));
  pEx->Delete();
 }
       
 if (!(bRes = m_hCreateWnd.CreateEx(0, AfxRegisterWndClass(0), \
  _T(csTitle), \
  WS_POPUP | WS_VISIBLE, 0, 0, 800, 600, NULL, NULL, 0)?true:false))
 {
  TRACE0("Warning: unable to create window!\n");
  AfxThrowResourceException();
 }
   
 m_hCreateWnd.ShowWindow(SW_HIDE);
 m_hCreateWnd.UpdateWindow();
    */
   if (!RegisterWindow())
   {  
    TRACE("register ipc window failed");
       return false;
   }

   m_hHandle = CreateWindow(AfxGetAppName(),
                     TEXT(csTitle),
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      NULL,
      NULL,
                     AfxGetInstanceHandle(),
                        NULL);
   if (m_hHandle == NULL)
   { 
   TRACE("create ipc window failed");
      return false;
   }
   m_csSendWndTile = csTitle;
   ShowWindow(m_hHandle,SW_HIDE);
   UpdateWindow(m_hHandle);
  
   return true;
}

 

 

创建窗口的时候需要注册窗口类,窗口类中有个注册函数,也就是回调函数,用来处理接收的消息,也就是该回调函数需要调用OnReceive接口。

该回调函数实现方法是

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   switch (message)
   { 
      case WM_COPYDATA:
  COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam;
  if ((cds!=NULL)&&(m_ipc!=NULL))
  { 

   //m_ipc为CIPC的类对象,
    m_ipc->OnReceive(m_csSendWndTile,cds->dwData,cds->lpData,cds->cbData);
  }
     return 0;
   }

   return DefWindowProc(hwnd, message, wParam, lParam);
}

 

send函数用来向接收窗口发送消息,实现方法为

HWND hRecvWnd = NULL;
 HWND hSendWnd = NULL;
 
 // Get target Window handle
 for(int ix = 0; ix < 3; ix++)
 {
  ::Sleep(10);
  
  //hRecvWnd = ::FindWindow(NULL,gcsATMCWndTitle);
  hRecvWnd = ::FindWindow(NULL,csRevWndTile);
  if(NULL == hRecvWnd)
  {
   continue;
  }
  
  hSendWnd = ::FindWindow(NULL,m_csSendWndTile);
  if(hSendWnd != NULL)
  {
   break;
  }
 }
 if(NULL == hRecvWnd || NULL == hSendWnd)
 {
  TRACE("IPCSendMsg: NULL window handle\n");
  TRACE("GetLastError returned %u\n",GetLastError());
  //theLog.Write(LOG_ERROR,"IPC: can not find %s.",( NULL == hRecvWnd ? gcsATMCWndTitle : gcsPacketWndTitle ) );
  return -1; // Window not found
 }
 
 int    i = 0;
 DWORD   dwResult;
 LRESULT   ret;
 COPYDATASTRUCT cds;
 
 do{
  TRACE("Sent: Message Code = %d\n", dwCode);
  
  cds.dwData = dwCode;
  cds.cbData = dwSize;
  cds.lpData = pData;
  ret = ::SendMessageTimeout(hRecvWnd,// handle to window
   WM_COPYDATA,      // message type
   (WPARAM)hSendWnd,    // first message parameter
   (LPARAM)&cds,     // second message parameter
   SMTO_BLOCK,      // send options
   3000,       // time-out duration
   &dwResult);      // return value for synchronous call
  
  if(0 == ret)
  {
   TRACE("%d Send Message Fail,GetLastError returned %u\n",(i+1),GetLastError());
   // Re Get target Window handle
   hRecvWnd = ::FindWindow(NULL,csRevWndTile);
  }
 }while ((ret == 0) && (++i < 3));
 if (3 == i)
 {
  TRACE("Send Message Time-Out\n");
  return -2; // Time Out
 }
 
 //AfxMessageBox("Send Message ok\n");
 return 0; 

 

RegisterWindow窗口实现方法为:

WNDCLASS wndclass; 
   wndclass.style = CS_HREDRAW | CS_VREDRAW;
   wndclass.lpfnWndProc = WndProc;
   wndclass.cbClsExtra = 0;
   wndclass.cbWndExtra = 0;
   wndclass.hInstance =  AfxGetInstanceHandle();
   wndclass.hIcon = 0;
   wndclass.hCursor = 0;
   wndclass.hbrBackground = 0;
   wndclass.lpszMenuName = NULL;
   wndclass.lpszClassName = AfxGetAppName();

   if (!RegisterClass(&wndclass))
   {
      return false;
   }
  
   return true;

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值