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
原文地址:https://www.cnblogs.com/lsh123/p/7441403.html