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 窗口消息 与窗口的内部运作有关,如创建窗口,绘制窗口,销毁窗口等.可以 ...
随机推荐
- C# FTP上传文件至服务器代码
C# FTP上传文件至服务器代码 /// <summary> /// 上传文件 /// </summary> /// <param name="fileinfo ...
- H.264开源解码器评测
转自:http://wmnmtm.blog.163.com/blog/static/38245714201142883032575/ 要播放HDTV,就首先要正确地解开封装,然后进行视频音频解码.所以 ...
- LeetCode--409--最长回文串
问题描述: 给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串. 在构造过程中,请注意区分大小写.比如 "Aa" 不能当做一个回文字符串. 注意: 假设字 ...
- 部署的error和排查,注意服务器内存占用!
mysqladmin: connect to server at 'localhost' failed error: 'Can't connect to local MySQL server thro ...
- 纯js无缝滚动
HTML代码 <!--父容器要使用overflow: hidden;--> <div id="imgsList" style="height:150px ...
- kibana的 timelion工具
时序控件(Timelion)是一款时间序列数据可视化工具,它可以将多种独立的数据源合并呈现到一张视图上. .es函数 index 指明索引 .es(index=nginx-access-log- ...
- Dropout的理解
https://zhuanlan.zhihu.com/p/23178423 这篇知乎文章讲的比较好,在神经网络权重取平均值和减少神经元之间复杂的共适应关系两个方面分析了为什么dropout可以解决过拟 ...
- SPL之AccessArray
<?php /** * Class MyArrayAccess * 提供像访问数组一样访问对象的能力的接口 */ class MyArrayAccess implements ArrayAcce ...
- smarty插件
smarty插件 1.目录:放在Smarty类库下的plugins目录下面(默认存放的都是smarty自带的插件) smarty3.0提供了自定义插件目录的方式: $ ...
- Northcott Game HDU - 1730
Tom和Jerry正在玩一种Northcott游戏,可是Tom老是输,因此他怀疑这个游戏是不是有某种必胜策略,郁闷的Tom现在向你求救了,你能帮帮他么? 游戏规则是这样的: 如图所示,游戏在一个n行m ...