windows消息傳送(自定義消息和WM_COPYDATA)


  通過SendMessge實現的進程間通信。

 

0x01 自定義消息

1,WINDOWS中自定義消息的定義和使用;

  (1)在WNDOWS中消息分系統消息和自定義消息。系統消息定義從0到0x3FF,使用0x400到0x7FFF定義自己的消息。Windows把0x400定義為WM_USER。如果想定義自己的一個消息,可以在WM_USER上加上一個值:

   #define UM_MSG  WM_USER+1

 

  (2)另一種自定義窗口消息的方法是用RegisterWindowsMessage()函數來注冊這個消息。與在WM_USER上加上某個數相比,它的好處是不必考慮所表示的消息標識符是否超出工程的允許范圍。如:

   const UINT RM_MSG = RegisterWindowMessage(L"HelloWorld");

   

  在接收消息的程序中,需要對添加對應消息的響應處理函數,並將消息和消息處理函數關聯.

 

 

0x02  WM_COPYDATA

    WM_COPYDATA消息,在win32中用來進行進程間的數據傳輸。

    

typedef struct tagCOPYDATASTRUCT {
    ULONG_PTR dwData;                         //自定義數據
    DWORD cbData;                             //數據的大小(字節數)
    _Field_size_bytes_(cbData) PVOID lpData;  //指向數據的指針
} COPYDATASTRUCT, *PCOPYDATASTRUCT;

  

  注意:該消息只能由SendMessage()來發送,而不能使用PostMessage()。因為系統必須管理用以傳遞數據的緩沖區的生命期,如果使用了PostMessage(),數據緩沖區會在接收方(線程)有機會處理該數據之前,就被系統清除和回收。此外如果lpData指向一個帶有指針或某一擁有虛函數的對象時,也要小心處理。

LRESULT SendMessage(
  HWND hWnd,      // 目標進程窗口句柄
  UINT Msg,       // WM_COPYDATA
  WPARAM wParam,  // 發送進程的窗體句柄
  LPARAM lParam   // 指向COPYDATASTRUCT數據結構的指針
);

  接收進程窗體句柄可以通過FindWindow函數獲取:

CWnd* DlgHwnd = FindWindow(NULL, L"Client");

  

  源代碼:

  1 // ServerDlg.cpp : 實現文件
  2 //
  3 
  4 #include "stdafx.h"
  5 #include "Server.h"
  6 #include "ServerDlg.h"
  7 #include "afxdialogex.h"
  8 
  9 #ifdef _DEBUG
 10 #define new DEBUG_NEW
 11 #endif
 12 #define UM_MSG  WM_USER+1
 13 
 14 // 用於應用程序“關於”菜單項的 CAboutDlg 對話框
 15 
 16 BOOL CStringToChar(char** DestinationString, CString& SourceString);
 17 const UINT RM_MSG = RegisterWindowMessage(L"HelloWorld");
 18 class CAboutDlg : public CDialogEx
 19 {
 20 public:
 21     CAboutDlg();
 22 
 23 // 對話框數據
 24 #ifdef AFX_DESIGN_TIME
 25     enum { IDD = IDD_ABOUTBOX };
 26 #endif
 27 
 28     protected:
 29     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
 30 
 31 // 實現
 32 protected:
 33     DECLARE_MESSAGE_MAP()
 34 };
 35 
 36 CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
 37 {
 38 }
 39 
 40 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
 41 {
 42     CDialogEx::DoDataExchange(pDX);
 43 }
 44 
 45 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
 46 END_MESSAGE_MAP()
 47 
 48 
 49 // CServerDlg 對話框
 50 
 51 
 52 
 53 CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/)
 54     : CDialogEx(IDD_SERVER_DIALOG, pParent)
 55     , m_CEdit_User_Message(0)
 56     , m_CEdit_Register_Message(0)
 57     , m_CEdit_CopyData_Message(_T(""))
 58 {
 59     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 60 }
 61 
 62 void CServerDlg::DoDataExchange(CDataExchange* pDX)
 63 {
 64     CDialogEx::DoDataExchange(pDX);
 65     DDX_Text(pDX, IDC_EDIT_USER_MESSAGE, m_CEdit_User_Message);
 66     DDX_Text(pDX, IDC_EDIT_REGISTER_MESSAGE, m_CEdit_Register_Message);
 67     DDX_Text(pDX, IDC_EDIT_COPYDATA_MESSAGE, m_CEdit_CopyData_Message);
 68 }
 69 
 70 BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx)
 71     ON_WM_SYSCOMMAND()
 72     ON_WM_PAINT()
 73     ON_WM_QUERYDRAGICON()
 74     ON_BN_CLICKED(IDC_BUTTON_USER_MESSAGE, &CServerDlg::OnBnClickedButtonUserMessage)
 75     ON_BN_CLICKED(IDC_BUTTON_REGISTER_MESSAGE, &CServerDlg::OnBnClickedButtonRegisterMessage)
 76     ON_BN_CLICKED(IDC_BUTTON_COPYDATA_MESSAGE, &CServerDlg::OnBnClickedButtonCopydataMessage)
 77 END_MESSAGE_MAP()
 78 
 79 
 80 // CServerDlg 消息處理程序
 81 
 82 BOOL CServerDlg::OnInitDialog()
 83 {
 84     CDialogEx::OnInitDialog();
 85 
 86     // 將“關於...”菜單項添加到系統菜單中。
 87 
 88     // IDM_ABOUTBOX 必須在系統命令范圍內。
 89     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 90     ASSERT(IDM_ABOUTBOX < 0xF000);
 91 
 92     CMenu* pSysMenu = GetSystemMenu(FALSE);
 93     if (pSysMenu != NULL)
 94     {
 95         BOOL bNameValid;
 96         CString strAboutMenu;
 97         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
 98         ASSERT(bNameValid);
 99         if (!strAboutMenu.IsEmpty())
100         {
101             pSysMenu->AppendMenu(MF_SEPARATOR);
102             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
103         }
104     }
105 
106     // 設置此對話框的圖標。  當應用程序主窗口不是對話框時,框架將自動
107     //  執行此操作
108     SetIcon(m_hIcon, TRUE);            // 設置大圖標
109     SetIcon(m_hIcon, FALSE);        // 設置小圖標
110 
111     // TODO: 在此添加額外的初始化代碼
112 
113     return TRUE;  // 除非將焦點設置到控件,否則返回 TRUE
114 }
115 
116 void CServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
117 {
118     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
119     {
120         CAboutDlg dlgAbout;
121         dlgAbout.DoModal();
122     }
123     else
124     {
125         CDialogEx::OnSysCommand(nID, lParam);
126     }
127 }
128 
129 // 如果向對話框添加最小化按鈕,則需要下面的代碼
130 //  來繪制該圖標。  對於使用文檔/視圖模型的 MFC 應用程序,
131 //  這將由框架自動完成。
132 
133 void CServerDlg::OnPaint()
134 {
135     if (IsIconic())
136     {
137         CPaintDC dc(this); // 用於繪制的設備上下文
138 
139         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
140 
141         // 使圖標在工作區矩形中居中
142         int cxIcon = GetSystemMetrics(SM_CXICON);
143         int cyIcon = GetSystemMetrics(SM_CYICON);
144         CRect rect;
145         GetClientRect(&rect);
146         int x = (rect.Width() - cxIcon + 1) / 2;
147         int y = (rect.Height() - cyIcon + 1) / 2;
148 
149         // 繪制圖標
150         dc.DrawIcon(x, y, m_hIcon);
151     }
152     else
153     {
154         CDialogEx::OnPaint();
155     }
156 }
157 
158 //當用戶拖動最小化窗口時系統調用此函數取得光標
159 //顯示。
160 HCURSOR CServerDlg::OnQueryDragIcon()
161 {
162     return static_cast<HCURSOR>(m_hIcon);
163 }
164 
165 
166 
167 void CServerDlg::OnBnClickedButtonUserMessage()
168 {
169     // TODO: 在此添加控件通知處理程序代碼
170     UpdateData(TRUE);
171     
172     CWnd* DlgHwnd = FindWindow(NULL,L"Client");
173     if (DlgHwnd == NULL) {
174         AfxMessageBox(TEXT("No Found"));
175         return;
176     }
177     long ParameterData;
178     ParameterData = m_CEdit_User_Message;
179     DlgHwnd->SendMessage(UM_MSG, NULL, (LPARAM)ParameterData);// 發送.
180 }
181 
182 
183 void CServerDlg::OnBnClickedButtonRegisterMessage()
184 {
185     // TODO: 在此添加控件通知處理程序代碼
186     UpdateData(TRUE);
187     CWnd* DlgHwnd = FindWindow(NULL, L"Client");
188     if (DlgHwnd == NULL) {
189         AfxMessageBox(TEXT("No Found"));
190         return;
191     }
192     long ParameterData;
193     ParameterData = m_CEdit_Register_Message;
194     DlgHwnd->SendMessage(RM_MSG, NULL, (LPARAM)ParameterData);// 發送.
195 
196 }
197 
198 
199 void CServerDlg::OnBnClickedButtonCopydataMessage()
200 {
201     // TODO: 在此添加控件通知處理程序代碼
202     UpdateData(TRUE);
203 
204     CWnd* DlgHwnd = FindWindow(NULL, L"Client");
205     if (DlgHwnd == NULL) {
206         AfxMessageBox(TEXT("No Found"));
207         return;
208     }
209     char* DestinationString = NULL;
210 
211     CStringToChar(&DestinationString, m_CEdit_CopyData_Message);
212 
213 
214 
215     COPYDATASTRUCT ParameterData; // 給COPYDATASTRUCT結構賦值.
216     ParameterData.dwData = 0;
217     ParameterData.cbData = strlen(DestinationString);  //注意這里
218     ParameterData.lpData = DestinationString;
219 
220     DlgHwnd->SendMessage(WM_COPYDATA, NULL, (LPARAM)&ParameterData);// 發送.
221 
222     if (DestinationString!=NULL)
223     {
224         delete[] DestinationString;
225         DestinationString = NULL;
226     }
227 }
228 BOOL CStringToChar(char** DestinationString, CString& SourceString)
229 {
230     if (SourceString.IsEmpty())
231     {
232         return FALSE;
233     }
234     int SourceStringLength = SourceString.GetLength();
235     *DestinationString = (char*)malloc((SourceStringLength * 2 + 1) * sizeof(char));//CString的長度中漢字算一個長度    
236 
237     if (*DestinationString == NULL)
238     {
239         return FALSE;
240     }
241     USES_CONVERSION;
242     strcpy(*DestinationString, W2A(SourceString.LockBuffer()));
243     SourceString.ReleaseBuffer();
244     return TRUE;
245 }
ServerDlg.cpp
  1 // ClientDlg.cpp : 實現文件
  2 //
  3 
  4 #include "stdafx.h"
  5 #include "Client.h"
  6 #include "ClientDlg.h"
  7 #include "afxdialogex.h"
  8 
  9 #ifdef _DEBUG
 10 #define new DEBUG_NEW
 11 #endif
 12 
 13 
 14 #define UM_MSG  WM_USER+1
 15 
 16 // 用於應用程序“關於”菜單項的 CAboutDlg 對話框
 17 const UINT RM_MSG = RegisterWindowMessage(L"HelloWorld");
 18 
 19 class CAboutDlg : public CDialogEx
 20 {
 21 public:
 22     CAboutDlg();
 23 
 24 // 對話框數據
 25 #ifdef AFX_DESIGN_TIME
 26     enum { IDD = IDD_ABOUTBOX };
 27 #endif
 28 
 29     protected:
 30     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
 31 
 32 // 實現
 33 protected:
 34     DECLARE_MESSAGE_MAP()
 35 };
 36 
 37 CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
 38 {
 39 }
 40 
 41 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
 42 {
 43     CDialogEx::DoDataExchange(pDX);
 44 }
 45 
 46 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
 47 END_MESSAGE_MAP()
 48 
 49 
 50 // CClientDlg 對話框
 51 
 52 
 53 
 54 CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/)
 55     : CDialogEx(IDD_CLIENT_DIALOG, pParent)
 56     , m_CEdit_User_Message(0)
 57     , m_CEdit_Register_Message(0)
 58     , m_CEdit_CopyData_Message(_T(""))
 59 {
 60     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 61 }
 62 
 63 void CClientDlg::DoDataExchange(CDataExchange* pDX)
 64 {
 65     CDialogEx::DoDataExchange(pDX);
 66     DDX_Text(pDX, IDC_EDIT_USER_MESSAGE, m_CEdit_User_Message);
 67     DDX_Text(pDX, IDC_EDIT_REGISTER_MESSAGE, m_CEdit_Register_Message);
 68     DDX_Text(pDX, IDC_EDIT_COPYDATA_MESSAGE, m_CEdit_CopyData_Message);
 69 }
 70 
 71 BEGIN_MESSAGE_MAP(CClientDlg, CDialogEx)
 72     ON_WM_SYSCOMMAND()
 73     ON_WM_PAINT()
 74     ON_WM_QUERYDRAGICON()
 75     ON_WM_COPYDATA()
 76     ON_MESSAGE(UM_MSG, (LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM))OnUserReceiveMsg)
 77     ON_REGISTERED_MESSAGE(RM_MSG, (LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM))OnRegisterReceiveMsg)
 78 END_MESSAGE_MAP()
 79 
 80 
 81 // CClientDlg 消息處理程序
 82 
 83 BOOL CClientDlg::OnInitDialog()
 84 {
 85     CDialogEx::OnInitDialog();
 86 
 87     // 將“關於...”菜單項添加到系統菜單中。
 88 
 89     // IDM_ABOUTBOX 必須在系統命令范圍內。
 90     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 91     ASSERT(IDM_ABOUTBOX < 0xF000);
 92 
 93     CMenu* pSysMenu = GetSystemMenu(FALSE);
 94     if (pSysMenu != NULL)
 95     {
 96         BOOL bNameValid;
 97         CString strAboutMenu;
 98         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
 99         ASSERT(bNameValid);
100         if (!strAboutMenu.IsEmpty())
101         {
102             pSysMenu->AppendMenu(MF_SEPARATOR);
103             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
104         }
105     }
106 
107     // 設置此對話框的圖標。  當應用程序主窗口不是對話框時,框架將自動
108     //  執行此操作
109     SetIcon(m_hIcon, TRUE);            // 設置大圖標
110     SetIcon(m_hIcon, FALSE);        // 設置小圖標
111 
112     // TODO: 在此添加額外的初始化代碼
113 
114     return TRUE;  // 除非將焦點設置到控件,否則返回 TRUE
115 }
116 
117 void CClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
118 {
119     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
120     {
121         CAboutDlg dlgAbout;
122         dlgAbout.DoModal();
123     }
124     else
125     {
126         CDialogEx::OnSysCommand(nID, lParam);
127     }
128 }
129 
130 // 如果向對話框添加最小化按鈕,則需要下面的代碼
131 //  來繪制該圖標。  對於使用文檔/視圖模型的 MFC 應用程序,
132 //  這將由框架自動完成。
133 
134 void CClientDlg::OnPaint()
135 {
136     if (IsIconic())
137     {
138         CPaintDC dc(this); // 用於繪制的設備上下文
139 
140         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
141 
142         // 使圖標在工作區矩形中居中
143         int cxIcon = GetSystemMetrics(SM_CXICON);
144         int cyIcon = GetSystemMetrics(SM_CYICON);
145         CRect rect;
146         GetClientRect(&rect);
147         int x = (rect.Width() - cxIcon + 1) / 2;
148         int y = (rect.Height() - cyIcon + 1) / 2;
149 
150         // 繪制圖標
151         dc.DrawIcon(x, y, m_hIcon);
152     }
153     else
154     {
155         CDialogEx::OnPaint();
156     }
157 }
158 
159 //當用戶拖動最小化窗口時系統調用此函數取得光標
160 //顯示。
161 HCURSOR CClientDlg::OnQueryDragIcon()
162 {
163     return static_cast<HCURSOR>(m_hIcon);
164 }
165 
166 void CClientDlg::OnUserReceiveMsg(WPARAM wParam, LPARAM lParam)
167 {
168     m_CEdit_User_Message = long(lParam);
169     // 更新數據.
170     UpdateData(FALSE);
171 }
172 
173 void CClientDlg::OnRegisterReceiveMsg(WPARAM wParam, LPARAM lParam)
174 {
175     m_CEdit_Register_Message = long(lParam);
176     // 更新數據.
177     UpdateData(FALSE);
178 }
179 
180 BOOL CClientDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
181 {
182     // TODO: 在此添加消息處理程序代碼和/或調用默認值
183     m_CEdit_CopyData_Message = (LPSTR)pCopyDataStruct->lpData;
184     m_CEdit_CopyData_Message = m_CEdit_CopyData_Message.Left(pCopyDataStruct->cbData);
185 
186     // 更新數據.
187     UpdateData(FALSE);
188     return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
189 }
ClientDlg.cpp

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM