通过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 }