乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      VC++ 中WM_COPYDATA 怎么樣應(yīng)用來實(shí)現(xiàn)兩個(gè)進(jìn)程間的數(shù)據(jù)傳輸[轉(zhuǎn)]

       Jugg_Bug 2013-04-19

      本文著重講述了如果用WM_COPYDATA消息來實(shí)現(xiàn)兩個(gè)進(jìn)程之間傳遞數(shù)據(jù).

      進(jìn)程之間通訊的幾種方法:

      在Windows程序中,各個(gè)進(jìn)程之間常常需要交換數(shù)據(jù),進(jìn)行數(shù)據(jù)通訊。常用的方法有

        使用內(nèi)存映射文件
        通過共享內(nèi)存DLL共享內(nèi)存
        使用SendMessage向另一進(jìn)程發(fā)送WM_COPYDATA消息

      比起前兩種的復(fù)雜實(shí)現(xiàn)來,WM_COPYDATA消息無疑是一種經(jīng)濟(jì)實(shí)惠的一中方法.

      WM_COPYDATA消息的主要目的是允許在進(jìn)程間傳遞只讀數(shù)據(jù)。Windows在通過WM_COPYDATA消息傳遞期間,不提供繼承同步方式。SDK文檔推薦用戶使用SendMessage函數(shù),接受方在數(shù)據(jù)拷貝完成前不返回,這樣發(fā)送方就不可能刪除和修改數(shù)據(jù):

      這個(gè)函數(shù)的原型及其要用到的結(jié)構(gòu)如下:

      SendMessage(hwnd,WM_COPYDATA,wParam,lParam);
      其中,WM_COPYDATA對(duì)應(yīng)的十六進(jìn)制數(shù)為0x004A

      wParam設(shè)置為包含數(shù)據(jù)的窗口的句柄。lParam指向一個(gè)COPYDATASTRUCT的結(jié)構(gòu):
      typedef struct tagCOPYDATASTRUCT{
          DWORD dwData;//用戶定義數(shù)據(jù)
          DWORD cbData;//數(shù)據(jù)大小
          PVOID lpData;//指向數(shù)據(jù)的指針
      }COPYDATASTRUCT;
      該結(jié)構(gòu)用來定義用戶數(shù)據(jù)。

      具體過程如下:


      首先,在發(fā)送方,用FindWindow找到接受方的句柄,然后向接受方發(fā)送WM_COPYDATA消息.

      接受方在DefWndProc事件中,來處理這條消息.由于中文編碼是兩個(gè)字節(jié),所以傳遞中文時(shí)候字節(jié)長度要搞清楚.

      代碼中有適量的解釋,大家請(qǐng)自己看吧.

      用WM_COPYDATA的前提:

      1,知道接收消息進(jìn)程的句柄。

      2,接收消息進(jìn)程重載了WM_COPYDATA消息映射,能對(duì)其做出反應(yīng)(否則不是發(fā)送端自作多情了?)

      看過前提,的出結(jié)論:在自己寫的兩個(gè)進(jìn)程間用WM_COPYDATA再好不過。

      下面CODE幾行就說明了一切。

      獲得句柄的方法,最簡單的方法就是使用FindWindow,找窗口類,或者名,如果你覺得這樣不把握,那就利用SetProp個(gè)窗口做個(gè)記號(hào)....(不說這些,跑踢兒了都)

      OK,開始寫發(fā)送端代碼:

      HWND hWnd = FindWindow(NULL,"MyApp");

      if(hWnd!=NULL)

      {

            COPYDATASTRUCT cpd; /*給COPYDATASTRUCT結(jié)構(gòu)賦值*/

            cpd.dwData = 0;

            cpd.cbData = strlen("字符串");

            cpd.lpData = (void*)"字符串";

            ::SendMessage(hWnd,WM_COPYDATANULL,(LPARAM)&cpd);//發(fā)送!

            /*完事兒了??!*/

      }

      接收端重載ON_WM_COPYDATA消息映射函數(shù)(下面是手工所要加的,你最好還是用ClassWizard)

      afx_msg BOOL OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct);

      ON_WM_COPYDATA()/*消息映射*/

      BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
      {
              AfxMessageBox((LPCSTR)(pCopyDataStruct->lpData));/*利用對(duì)話框表示收到消息*/

              return CWnd::OnCopyData(pWnd, pCopyDataStruct);
      }

      進(jìn)程通信還有其他一些手段,相對(duì)來說比較麻煩,但局限性要比WM_COPYDATA小。當(dāng)然你也可以兩端都注冊(cè)一個(gè)消息來通信。

      使用WM_COPYDATA進(jìn)行進(jìn)程間通信的一個(gè)問題

       

      開發(fā)中有時(shí)需要進(jìn)程間傳遞數(shù)據(jù),比如對(duì)于只允許單實(shí)例運(yùn)行的程序,當(dāng)已有實(shí)例運(yùn)行時(shí),再次打開程序,可能需要向當(dāng)前運(yùn)行的實(shí)例傳遞信息進(jìn)行特殊處理。對(duì)于傳遞少量數(shù)據(jù)的情況,最簡單的就是用SendMessage發(fā)送WM_COPYDATA消息,所帶參數(shù)wParam和lParam可以攜帶相關(guān)數(shù)據(jù)。由于SendMessage是阻塞的,在接收數(shù)據(jù)進(jìn)程處理完數(shù)據(jù)之前不會(huì)返回,發(fā)送方不會(huì)刪除或修改數(shù)據(jù),因此這種方法是簡單且安全的,不過數(shù)據(jù)量不能太大,否則會(huì)由于處理時(shí)間過長造成阻塞假死。

          用SendMessage發(fā)送WM_COPYDATA的方法如下:

         

       

          lResult SendMessage(     // returns LRESULT in lResult
             (HWND) hWndControl,     // handle to destination control
             (UINT) WM_COPYDATA,     // message ID
             (WPARAM) wParam,     // (WPARAM) () wParam;
             (LPARAM) lParam     // (LPARAM) () lParam;

          );

         

       

          其中,wParam為發(fā)送數(shù)據(jù)方的窗口句柄,lParam為指向一個(gè)COPYDATASTRUCT類型結(jié)構(gòu)體的指針,該結(jié)構(gòu)體中包含了傳遞的數(shù)據(jù)信息。COPYDATASTRUCT定義如下:

          typedef struct tagCOPYDATASTRUCT {
              ULONG_PTR dwData;
              DWORD cbData;
              PVOID lpData;
          } COPYDATASTRUCT, *PCOPYDATASTRUCT;

          其中,dwData為自定義的數(shù)據(jù),cbData指定lpData指向數(shù)據(jù)的大小,lpData為指向數(shù)據(jù)的指針。按照前面所說,在使用WM_COPYDATA時(shí)要保證數(shù)據(jù)的只讀屬性,即不能有發(fā)送方的其他線程對(duì)傳遞數(shù)據(jù)進(jìn)行改寫。(這也解釋了為什么不允許用PostMessage發(fā)送WM_COPYDATA,因?yàn)镻ostMessage函數(shù)是異步的。還有一點(diǎn)需要注意的是由于SendMessage是阻塞的,所以容易引起死鎖,可以考慮用SendMessageTimeout代替。)另外,如果傳遞數(shù)據(jù)中涉及到對(duì)象或系統(tǒng)資源,必須確保接收方可以對(duì)其進(jìn)行處理,比如HDC、HBITMAP之類的資源是無效的,他們屬于不同的進(jìn)程。

          在使用的時(shí)候,要用FindWindow等API找到接收方的窗口句柄;接收方的程序中要添加對(duì)WM_COPYDATA消息的響應(yīng)。

         

          前幾天寫程序用到WM_COPYDATA進(jìn)行進(jìn)程間通信,但是接收方怎么也收不到消息。調(diào)試發(fā)現(xiàn)找到的窗口句柄是沒有問題的,查看MSDN也沒有什么提示,百思不得其解。

          后來看了一些示例代碼,發(fā)現(xiàn)不同之處是我的SendMessage調(diào)用中wParam和lParam參數(shù)都是0,因?yàn)槲抑皇切枰ㄟ^WM_COPYDATA消息通知一下接收程序即可,不用傳遞任何數(shù)據(jù)。試著將這兩個(gè)參數(shù)改為非空,接收方就可以收到消息了。總結(jié)結(jié)論為:wParam參數(shù)是否為0沒有影響,但是lParam參數(shù)必須為非空,即必須指向一個(gè)有效的COPYDATASTRUCT結(jié)構(gòu)體。

          原因是什么呢?查了一些資料發(fā)現(xiàn),SendMessage(WM_COPYDATA)底層是通過文件映射(File Mapping)完成的,大概流程是發(fā)送方線程根據(jù)COPYDATASTRUCT結(jié)構(gòu)體中的傳遞數(shù)據(jù)信息,在共享內(nèi)存中進(jìn)行數(shù)據(jù)復(fù)制,接收方線程則會(huì)到共享內(nèi)存中讀取數(shù)據(jù)進(jìn)行處理。因此如果指向COPYDATASTRUCT結(jié)構(gòu)的指針為空的話,流程是無法進(jìn)行的,所以接收方也理所當(dāng)然收不到消息。

      WM_COPYDATA使用的一個(gè)例子:

      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      進(jìn)程間通信的方法有多種,其中,對(duì)于少量數(shù)據(jù)可以用WM_COPYDATA方便的實(shí)現(xiàn)通信(如果對(duì)于大量數(shù)據(jù)的話,由于SendMessage是阻塞的,只有接收方響應(yīng)了消息,SendMessage才能返回,否則則一直阻塞,所以,對(duì)于大量數(shù)據(jù)來說,用SendMessage就容易造成窗口假死) 。

      本例子分別用WM_COPYDATA 實(shí)現(xiàn)了兩種數(shù)據(jù)類型的發(fā)送,一種為Cstring,另外一種為自定義的結(jié)構(gòu)體Student:

      //**********************************************************

      #pragma pack(1)

      struct Student {

      char ID[10];

      TCHAR Name[20];

      UINT Age;

      UINT Grade;

      char Room[5];

      char Tel[12];

      };

      #pragma pack()

      //**********************************************************

      因?yàn)樾枰诮邮辗降腛nCopyData()函數(shù)中區(qū)分發(fā)送的兩種不同類型數(shù)據(jù)。所以就定義了以下兩個(gè)常量:

      #define STRING 1

      #define STUDENT 2

      發(fā)送方:

      void CSendDataDlg::OnBtSend() //實(shí)現(xiàn)CString類型數(shù)據(jù)的發(fā)送

      {

      UpdateData(TRUE);

      if (m_szData.IsEmpty()) {

      m_szData = _T("Hello");

      UpdateData(FALSE);

      }

      // m_szData += '\0';

      HWND hWndRcv = ::FindWindow(NULL,"Receiver");

      if (hWndRcv == NULL) {

      AfxMessageBox(_T("找不到接收窗口,發(fā)送不成功"));

      return ;

      }

      COPYDATASTRUCT cpd;

      cpd.dwData = STRING; //標(biāo)志為CString類型

      cpd.cbData = m_szData.GetLength() + 1;

      //GetLength()只是取得實(shí)際字符的長度,沒有包括'\0'.

      cpd.lpData = (void*)m_szData.GetBuffer(cpd.cbData);

      ::SendMessage(hWndRcv,WM_COPYDATA,(WPARAM)this->m_hWnd,(LPARAM)&cpd);

      m_szData.ReleaseBuffer();

      AfxMessageBox(_T("發(fā)送成功"));

      }

      void CSendDataDlg::OnBtStu() //實(shí)現(xiàn)Student類型數(shù)據(jù)的發(fā)送

      {

      UpdateData();

      m_szID += '\0';

      m_szName += '\0';

      m_szRoom += '\0';

      m_szTel += '\0';

      m_pStu = new Student();

      strcpy(m_pStu->ID,m_szID.GetBuffer(m_szID.GetLength()));

      _tcscpy(m_pStu->Name,m_szName.GetBuffer(m_szName.GetLength()));

      strcpy(m_pStu->Room,m_szRoom.GetBuffer(m_szRoom.GetLength()));

      strcpy(m_pStu->Tel,m_szTel.GetBuffer(m_szTel.GetLength()));

      m_szID.ReleaseBuffer();m_szName.ReleaseBuffer();

      m_szRoom.ReleaseBuffer();m_szTel.ReleaseBuffer();

      m_pStu->Age = m_nAge;

      m_pStu->Grade = m_nGrade;

      HWND hWndRcv = ::FindWindow(NULL,"Receiver");

      if (hWndRcv == NULL) {

      AfxMessageBox(_T("找不到接收窗口,發(fā)送不成功"));

      return ;

      }

      COPYDATASTRUCT cpd;

      cpd.dwData = STUDENT; // 標(biāo)志為Student類型

      cpd.cbData = sizeof(Student);

      cpd.lpData = (PVOID)m_pStu;

      ::SendMessage(hWndRcv,WM_COPYDATA,(WPARAM)this->m_hWnd,(LPARAM)&cpd);

      delete m_pStu;

      AfxMessageBox(_T("發(fā)送成功"));

      }

      接收方:

      在OnInitDialog方法中:

      //***************************************************************

      //初始化ListCtrl控件

      LVCOLUMN column;

      column.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;

      column.cx = 80;

      column.iSubItem = 0;

      column.pszText = _T("ID");

      m_ListCtl.InsertColumn(0,&column);

      column.cx = 80;

      column.pszText = _T("Name");

      column.iSubItem = 1;

      m_ListCtl.InsertColumn(1,&column);

      column.cx = 55;

      column.pszText = _T("Age");

      column.iSubItem = 2;

      m_ListCtl.InsertColumn(2,&column);

      column.cx = 55;

      column.pszText = _T("Grade");

      column.iSubItem = 3;

      m_ListCtl.InsertColumn(3,&column);

      column.cx = 55;

      column.pszText = _T("Room");

      column.iSubItem = 4;

      m_ListCtl.InsertColumn(4,&column);

      column.cx = 80;

      column.pszText = _T("Tel");

      column.iSubItem = 5;

      m_ListCtl.InsertColumn(5,&column);

       

      BOOL CReceiverDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)

      {

      switch (pCopyDataStruct->dwData) { // 接收到的是CString類型

      case STRING:

      m_szData += (LPCSTR)(pCopyDataStruct->lpData);

      UpdateData(FALSE);

      break;

      case STUDENT: // 接收到的是Student類型

      CString id,name,room,tel;

      UINT age,grade;

      CString str;

      Student* pStu = (Student*)(pCopyDataStruct->lpData);

      id = pStu->ID;

      name = pStu->Name;

      room = pStu->Room;

      tel = pStu->Tel;

      age = pStu->Age;

      grade = pStu->Grade;

      LVITEM item;

      // 把接收到的數(shù)據(jù)顯示到ListCtrl控件

      item.mask = LVIF_TEXT;

      int n = m_ListCtl.GetItemCount();

      item.iItem = n;

      item.iSubItem = 0;

      item.pszText = id.GetBuffer(id.GetLength());

      id.ReleaseBuffer();

      m_ListCtl.InsertItem(&item);

      m_ListCtl.SetItemText(n,1,name);

      str.Format("%d",age);

      m_ListCtl.SetItemText(n,2,str);

      str.Format("%d",grade);

      m_ListCtl.SetItemText(n,3,str);

      m_ListCtl.SetItemText(n,4,room);

      m_ListCtl.SetItemText(n,5,tel);

      UpdateData(FALSE);

      //delete pStu;

      break;

      }

      // return CDialog::OnCopyData(pWnd, pCopyDataStruct);

      return TRUE;

      }

       

      MSDN幫助里面有該消息的例子,說的也很清楚。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多