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");
源代码:
// ServerDlg.cpp : 实现文件
// #include "stdafx.h"
#include "Server.h"
#include "ServerDlg.h"
#include "afxdialogex.h" #ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define UM_MSG WM_USER+1 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 BOOL CStringToChar(char** DestinationString, CString& SourceString);
const UINT RM_MSG = RegisterWindowMessage(L"HelloWorld");
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg(); // 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现
protected:
DECLARE_MESSAGE_MAP()
}; CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
} void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
} BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP() // CServerDlg 对话框 CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_SERVER_DIALOG, pParent)
, m_CEdit_User_Message()
, m_CEdit_Register_Message()
, m_CEdit_CopyData_Message(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
} void CServerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_USER_MESSAGE, m_CEdit_User_Message);
DDX_Text(pDX, IDC_EDIT_REGISTER_MESSAGE, m_CEdit_Register_Message);
DDX_Text(pDX, IDC_EDIT_COPYDATA_MESSAGE, m_CEdit_CopyData_Message);
} BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_USER_MESSAGE, &CServerDlg::OnBnClickedButtonUserMessage)
ON_BN_CLICKED(IDC_BUTTON_REGISTER_MESSAGE, &CServerDlg::OnBnClickedButtonRegisterMessage)
ON_BN_CLICKED(IDC_BUTTON_COPYDATA_MESSAGE, &CServerDlg::OnBnClickedButtonCopydataMessage)
END_MESSAGE_MAP() // CServerDlg 消息处理程序 BOOL CServerDlg::OnInitDialog()
{
CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
} // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
} void CServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
} // 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。 void CServerDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), ); // 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + ) / ;
int y = (rect.Height() - cyIcon + ) / ; // 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
} //当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CServerDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
} void CServerDlg::OnBnClickedButtonUserMessage()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE); CWnd* DlgHwnd = FindWindow(NULL,L"Client");
if (DlgHwnd == NULL) {
AfxMessageBox(TEXT("No Found"));
return;
}
long ParameterData;
ParameterData = m_CEdit_User_Message;
DlgHwnd->SendMessage(UM_MSG, NULL, (LPARAM)ParameterData);// 发送.
} void CServerDlg::OnBnClickedButtonRegisterMessage()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
CWnd* DlgHwnd = FindWindow(NULL, L"Client");
if (DlgHwnd == NULL) {
AfxMessageBox(TEXT("No Found"));
return;
}
long ParameterData;
ParameterData = m_CEdit_Register_Message;
DlgHwnd->SendMessage(RM_MSG, NULL, (LPARAM)ParameterData);// 发送. } void CServerDlg::OnBnClickedButtonCopydataMessage()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE); CWnd* DlgHwnd = FindWindow(NULL, L"Client");
if (DlgHwnd == NULL) {
AfxMessageBox(TEXT("No Found"));
return;
}
char* DestinationString = NULL; CStringToChar(&DestinationString, m_CEdit_CopyData_Message); COPYDATASTRUCT ParameterData; // 给COPYDATASTRUCT结构赋值.
ParameterData.dwData = ;
ParameterData.cbData = strlen(DestinationString); //注意这里
ParameterData.lpData = DestinationString; DlgHwnd->SendMessage(WM_COPYDATA, NULL, (LPARAM)&ParameterData);// 发送. if (DestinationString!=NULL)
{
delete[] DestinationString;
DestinationString = NULL;
}
}
BOOL CStringToChar(char** DestinationString, CString& SourceString)
{
if (SourceString.IsEmpty())
{
return FALSE;
}
int SourceStringLength = SourceString.GetLength();
*DestinationString = (char*)malloc((SourceStringLength * + ) * sizeof(char));//CString的长度中汉字算一个长度 if (*DestinationString == NULL)
{
return FALSE;
}
USES_CONVERSION;
strcpy(*DestinationString, W2A(SourceString.LockBuffer()));
SourceString.ReleaseBuffer();
return TRUE;
}
ServerDlg.cpp
// ClientDlg.cpp : 实现文件
// #include "stdafx.h"
#include "Client.h"
#include "ClientDlg.h"
#include "afxdialogex.h" #ifdef _DEBUG
#define new DEBUG_NEW
#endif #define UM_MSG WM_USER+1 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
const UINT RM_MSG = RegisterWindowMessage(L"HelloWorld"); class CAboutDlg : public CDialogEx
{
public:
CAboutDlg(); // 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现
protected:
DECLARE_MESSAGE_MAP()
}; CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
} void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
} BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP() // CClientDlg 对话框 CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_CLIENT_DIALOG, pParent)
, m_CEdit_User_Message()
, m_CEdit_Register_Message()
, m_CEdit_CopyData_Message(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
} void CClientDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_USER_MESSAGE, m_CEdit_User_Message);
DDX_Text(pDX, IDC_EDIT_REGISTER_MESSAGE, m_CEdit_Register_Message);
DDX_Text(pDX, IDC_EDIT_COPYDATA_MESSAGE, m_CEdit_CopyData_Message);
} BEGIN_MESSAGE_MAP(CClientDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_COPYDATA()
ON_MESSAGE(UM_MSG, (LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM))OnUserReceiveMsg)
ON_REGISTERED_MESSAGE(RM_MSG, (LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM))OnRegisterReceiveMsg)
END_MESSAGE_MAP() // CClientDlg 消息处理程序 BOOL CClientDlg::OnInitDialog()
{
CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
} // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
} void CClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
} // 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。 void CClientDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), ); // 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + ) / ;
int y = (rect.Height() - cyIcon + ) / ; // 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
} //当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CClientDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
} void CClientDlg::OnUserReceiveMsg(WPARAM wParam, LPARAM lParam)
{
m_CEdit_User_Message = long(lParam);
// 更新数据.
UpdateData(FALSE);
} void CClientDlg::OnRegisterReceiveMsg(WPARAM wParam, LPARAM lParam)
{
m_CEdit_Register_Message = long(lParam);
// 更新数据.
UpdateData(FALSE);
} BOOL CClientDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_CEdit_CopyData_Message = (LPSTR)pCopyDataStruct->lpData;
m_CEdit_CopyData_Message = m_CEdit_CopyData_Message.Left(pCopyDataStruct->cbData); // 更新数据.
UpdateData(FALSE);
return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
}
ClientDlg.cpp
windows消息传送(自定义消息和WM_COPYDATA)的更多相关文章
- duilib进阶教程 -- 响应windows原生消息和自定义消息(13)
一.windows原生消息 同样,入门教程只是给出了响应windows原生消息的方法,并没给出例子,这里以自适应屏幕分辨率为例.迅雷播放器虽然可以在启动的时候自动调整窗口大小,但是当屏幕分辨率实时改变 ...
- windows消息机制详解(转载)
消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了.例如,单击鼠标.改变窗口尺寸.按下键盘上的一个键都会使Windows发送一个消息给应用程序.消息本身是作为一个记录传递给应用程序的 ...
- Windows消息大全(转)
原链接地址: http://www.cnblogs.com/icebutterfly/archive/2011/08/05/2128864.html 表A-1 Windows消息分布 消息范围说 明 ...
- Windows消息拦截技术的应用
Windows消息拦截技术的应用 民航合肥空管中心 周毅 一.前 言 众所周知,Windows程式的运行是依靠发生的事件来驱动.换句话说,程式不断等待一个消息的发生,然后对这个消息的类型进行判断,再做 ...
- Windows消息拦截技术的应用(作者博客里有许多相关文章)
民航合肥空管中心 周毅 一.前 言 众所周知,Windows程式的运行是依靠发生的事件来驱动.换句话说,程式不断等待一个消息的发生,然后对这个消息的类型进行判断,再做适当的处理.处理完此次消息后又回到 ...
- Delphi里的Windows消息(可查MSDN指定位置)
各种控件的通知消码和控制消息可由MSDN-> Platform SDK-> User Interface Services->Windows User Interface->C ...
- C# 重写WndProc 拦截 发送 系统消息 + windows消息常量值
接收拦截+发送消息 对于处理所有消息.net 提供了wndproc进行重写 WndProc(ref Message m)protected override void WndProc(ref Mess ...
- windows消息机制(转)
1. 引言Windows 在操作系统平台占有绝对统治地位,基于Windows 的编程和开发越来越广泛.Dos 是过程驱动的,而Windows 是事件驱动的[6],这种差别的存在使得很多Dos 程序员不 ...
- Windows消息机制知识点总结
1.windows消息类型 以下四种,前三种是系统消息,范围在[0x0000, 0x03ff],第四种是用户自定义消息. 1.1 窗口消息 与窗口的内部运作有关,如创建窗口,绘制窗口,销毁窗口等.可以 ...
随机推荐
- Linux ----> debian中环境的常见配置
环境: (debian 9)/(lubuntu18.0.4+virtualbox) 1.配置下载源: gedit /etc/apt/sources.list #163 deb http://mirro ...
- 老老实实学WCF
老老实实学WCF 第三篇 在IIS中寄宿服务 通过前两篇的学习,我们了解了如何搭建一个最简单的WCF通信模型,包括定义和实现服务协定.配置服务.寄宿服务.通过添加服务引用的方式配置客户端并访问服务.我 ...
- int __get_order(unsigned long size)
2017-12-6 10:26:504.9.51int __get_order(unsigned long size){ int order; size--; size >>= ...
- Misha and Palindrome Degree CodeForces - 501E (回文串计数)
大意: 给定字符串, 求多少个区间重排后能使原串为回文串. 先特判掉特殊情况, 对于两侧已经相等的位置之间可以任意组合, 并且区间两端点至少有一个在两侧相等的位置处, 对左右两种情况分别求出即可. # ...
- 一篇文章一张思维导图看懂Android学习最佳路线(转载)
Android学习路线从4个阶段来对Android的学习过程做一个全面的分析:Android初级.中级.高级以及资深工程师.只针对Android应用开发,不针对Rom开发和逆向工程等.方便起见虚拟“小 ...
- php-fpm.conf文件的位置在哪里
在php的安装目录下的etc目录下:
- java骰子求和算法
//扔 n 个骰子,向上面的数字之和为 S.给定 Given n,请列出所有可能的 S 值及其相应的概率public class Solution { /** * @param n an intege ...
- kohana task 编写计划任务
kohana 框架 我们经常使用gleez作为我们二次开发. 收先我们要把文件建在Task文件夹下,比如新建文件为:testcron <?phpdefined('SYSPATH') or di ...
- windows下进程间通信与线程间通信
进程间通信: 1.文件映射(Memory-Mapped Files) 文件映射(Memory-Mapped Files)能使进程把文件内容当作进程地址区间一块内存那样来对待.因此,进程不必使用文件I/ ...
- P2756 飞行员配对方案问题
题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外 ...