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 窗口消息 与窗口的内部运作有关,如创建窗口,绘制窗口,销毁窗口等.可以 ...
随机推荐
- learn the python the hard way习题26~30总结
考试试题26错误总结: 漏写字母,括号 写错字母 write(),read()的使用:只能打开使用了 open() 后返回的文件对象(file object),而不能直接使用文件名 if 语句中,条件 ...
- 以太坊 web3.js 文档翻译及说明
这些天,为了录制以太坊DAPP开发实战课程,我准备把web3文档全部翻译一下(并做适当的补充),目前web3.js 0.20.x 版本 已经翻译完成,欢迎大家前往查阅. 这里还几个实用DEMO,供大家 ...
- win10系统同时安装python2和python3
1.官网下载python2和python3版本 2.安装python3,勾上Add Python3.5 to PATH,自定义选择安装目录,安装,验证:WIN+R--->cmd,输入python ...
- win10+cpu+tensorflow+pycharm
1.安装64位的python3.5 选择windowsx86-64 executable installer安装 2.安装tensorflow cmd->进入到安装python的Scripts文 ...
- python生成随机整数
python生成随机不重复的整数,用random中的sample index = random.sample(range(0,10),10) 上面是生成不重复的10个从1~10的整数 python生成 ...
- List<String> 和 ArrayList<String>的区别(转载)
最近对这两个问题比较懵逼,关于List和ArrayList.List<String> list = new ArrayList<String>(); 好了,先搞明白List 和 ...
- php开启redis
看下自己phpinfo的信息 php 5.5以下的都有这些文件 到这个地方下载所需要的文件:https://github.com/nicolasff/phpredis/downloads 下载解压 ...
- Boosting
Boosting is a greedy alogrithm. The alogrithm works by applying the weak learner sequentially to wei ...
- Activiti手动执行的应用(UserTask)
工作流模拟某公司请假流程情景如下: 1.开发人员请假流程,如果开发人员请假,如果请假天数小于3天,组长批准,人事批准即可请假. 2.如果请假大约三天,需要项目经理或者产品经理批准,并且项目总监 ...
- 【LeetCode】大数相乘
1. 模拟手工计算 原理: 将 string 反转存储在 int 数组中,如 A = 17 = (7, 1),B = 25 = (5, 2),亦即幂表示法,幂次是从低位到高位. 作逐位相乘,即 ai ...