MFC窗口消息PostMessage和SendMessage
以前这些消息用得比较少,但是今天碰到了个事儿,我看非用消息不可。
事情是这样的,我在线程中需要刷新对话框上面的内容,但是每每执行到UpdateData时就出现了断言错误。
查了相关资料,发现这个可能是多个模块调用同一个方法出现的问题。反正照我之前的逻辑走不通。
我现在将更新对话框信息的函数,通过线程中发窗口消息,让对话框的消息处理函数来负责处理我自定义的消息,为我刷新对话框数据。
// http://blog.csdn.net/a8082649/article/details/7733527
1.自定义消息ID。
#define WM_MY_MESSAGE (WM_USER+100) WM_USER为windows系统为非系统消息保留的ID,这里至少要用100,因为其它控件的消息会占用一部分。
2. 定义消息处理函数。
消息处理函数为消息目标类的成员函数。首先应该在.h 文件中声明。这里以主窗口类为例,主窗口类名 CMainDialog,则首先在CMainDialog.h声明消息处理函数。
protected:
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
3.在CMainDialog.cpp中实现消息处理函数
LPESULT CMainDialog::OnMyMessage(WPARAM wParam, LPARAM lParam) { // TODO: 处理用户自定义消息 ... return 0; }
4.在CMainDialog.cpp中映射消息ID和消息处理函数
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_WM_TIMER()
ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
在创建线程的时候将主窗口句柄作为参数传入线程,就可以用 PostMessage传递消息了。
消息预处理函数
添加消息处理函数PreTranslateMessage,此函数可以通过MFC ClassWizard添加
- BOOL CPreTranslateMessageDlg::PreTranslateMessage(MSG* pMsg)
- {
- if (pMsg->message==WM_LBUTTONDOWN)
- {
- MessageBox("三三四四");
- }
- return CDialog::PreTranslateMessage(pMsg);
- }
此函数为手动添加的消息函数,可通过pMsg->message来判断是什么消息,比如WM_LBUTTONDOWN是左键单击消息,那当单击左键时就会执行此函数,同样当敲击一下键盘也会执行PreTranslateMessage函数
// ===================================================================================================================
SendMessage函数功能:该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。而函数PostMessage不同,将一个消息寄送到一个线程的消息队列后立即返回。
函数原型 :
LRESULT SendMessage(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM IParam);
参数:
hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
wMsg用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量.
wParam通常是一个与消息有关的常量值,也可能是窗口或控件的句柄
lParam通常是一个指向内存中数据的指针。由于WParm、lParam和Pointer都是32位的,因此,它们之间可以相互转换
返回值:返回值指定消息处理的结果,依赖于所发送的消息。
SendMessage用例
1. 系统消息(WM_)
::SendMessage(this->m_hWnd,WM_CLOSE,0,0);
SendMessage(hWnd,WM_KEYDOWN,VK_TAB,0x000f0001);
SendMessage(hWnd,WM_CHAR,VK_TAB,0x000f0001);
SendMessage(hWnd,WM_KEYUP,VK_TAB,0xc00f0001);
SendMessage(hWnd,WM_KEYDOWN,VK_TAB,0x000f0001);
SendMessage(hWnd,WM_CHAR,VK_TAB,0x000f0001);
SendMessage(hWnd,WM_KEYUP,VK_TAB,0xc00f0001);
SendMessage(hWnd,WM_KEYDOWN,VK_TAB,0x000f0001);
SendMessage(hWnd,WM_CHAR,VK_TAB,0x000f0001);
SendMessage(hWnd,WM_KEYUP,VK_TAB,0xc00f0001);
SendMessage(hWnd,WM_KEYDOWN,VK_RETURN,0x001c0001);
SendMessage(hWnd,WM_CHAR,VK_RETURN,0x001c0001);
SendMessage HWND, WM_SHOWWINDOW, SW_HIDE, vbNull '隐藏窗体
SendMessage HWND, WM_SHOWWINDOW, SW_NORMAL, vbNull '显示窗体
SendMessage(HWND, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&) '关闭
SendMessage(HWND, WM_SYSCOMMAND, SC_MINIMIZE, ByVal 0&) '最小化
SendMessage(HWND, WM_PASTE, 0, 0) '粘贴
SendMessage(HWND, WM_COPY, 0, 0) '复制
SendMessage(HWND, WM_UNDO, 0, 0) '撤消
2. 通告消息
比如:给资源ID为IDC_BUTTON2的按钮,发送点击消息:
SendMessage(WM_COMMAND,
MAKELONG(IDC_BUTTON2,BN_CLICKED),
(LPARAM)(GetDlgItem(IDC_BUTTON2)-> GetSafeHwnd()));
或:
::SendMessage(m_hWnd,
WM_COMMAND,
MAKELONG(IDC_BUTTON2,BN_CLICKED),
(LPARAM)(GetDlgItem(IDC_BUTTON2)-> GetSafeHwnd()));
例:给菜单ID为ID_GET的菜单项,发送消息
::SendMessage(AfxGetMainWnd()->m_hWnd,WM_COMMAND,ID_GET,NULL);
3. 用户自定义消息
SendMessge(WM_MYMSG,0,0);
或:
::SendMessge(::AfxGetMainWnd()->m_hWnd,WM_MYMSG,0,0);
4. 向其他应用程序发送消息
也可以为其他应用程序发送消息,前提是找到窗体的句柄,如:与FindWindow()函数一起使用;
如:
CString str="360w.txt -记事本";//向窗口为str的记事本窗口发送WM_CLOSE消息
CWnd *pWnd=CWnd::FindWindow(NULL,str);//获取目的窗口对象
::SendMessage(*pWnd,WM_CLOSE,0,0);
窗口标题的获取方法:
1. 使用VC++自带工具SPY++
2. 编程实现,可用EnumWindows函数实现;详见“枚举所有窗体,并向打开的窗体发送关闭消息”http://download.csdn.net/detail/nuptboyzhb/4162747
举例:
HWND gameh=NULL; gameh=::FindWindow(NULL,"窗口标题");//参看游戏的标题.可以用vc6.0自带的Spy++工具查看
CWnd* pWnd = CWnd::FromHandle(gameh);
//在坐标为(x,y)的点,发送鼠标按下消息//注意,x,y是客户区的坐标
::SendMessage(*pWnd,WM_LBUTTONDOWN,0,(y<<16)+x);
//发送鼠标移动消息,鼠标移动到点(x,y)
::SendMessage(*pWnd,WM_MOUSEMOVE,0,MAKELONG(x,y));
//发送粘贴消息
::SendMessage(dlg_hwnd,WM_PASTE,0,0);
5. 发送自己注册的消息 5.1 发送端:
本示例先通过RegisterWindowMessage函数来注册一条消息,然后用Win32 API函数SendMessage()发送。 主程序端: 建立MFC对话框,添加一个按钮 在对话框CPP文件预处理下加入下面代码: static UINT NEAR WM_RGSMSG=RegisterWindowMessage("MESSAGE");//注册一条发送MESSAGE的自己注册的消息 在按钮单击事件函数中添加后: void CMyDlg::OnButton1() { // TODO: Add your control notification handler code here HWND hwnd=::FindWindow(NULL,"接受窗口");//找到我们要发送消息的窗口句柄 if(hwnd==NULL) { AfxMessageBox("没有找到接受窗口"); return; } else ::SendMessage(hwnd,WM_RGSMSG,1,0);//发送消息 }
5.2 接收端:
本示例接受方,仍然是先通过RegisterWindowMessage函数来注册一条相同的消息,然后定义消息宏,绑定处理函数 接收窗口: 建立MFC对话框工程 在对话框CPP文件预处理下加入下面代码: static UINT NEAR WM_RGSMSG=RegisterWindowMessage("MESSAGE");//注册一条发送MESSAGE的自己注册的消息 在消息宏声明处 将消息声明为: afx_msg LRESULT OnRgsmsg(WPARAM wParam,LPARAM lparam); //声明消息映射函数 在建立消息映射表的地方添加如下代码: ON_REGISTERED_MESSAGE(WM_RGSMSG,OnRgsmsg)//注册的消息宏应放在这个位置 在CPP文件中,添加函数定义,代码如下: LRESULT CMyDlg::OnRgsmsg(WPARAM wParam,LPARAM lParam) { AfxMessageBox("接收到消息"); return TRUE; }
// http://blog.csdn.net/nupt123456789/article/details/7370463
MFC窗口消息PostMessage和SendMessage的更多相关文章
- MFC发送自定义消息-PostMessage和SendMessage
PostMessage:把消息投放到线程的消息队列,不能消息被处理就立即返回SendMessage:消息被处理完后才返回 几种发送消息的写法: ::PostMessage(GetSafeHwnd( ...
- MFC在子线程中创建窗口(PostMessage方法)
1.创建子线程 C++创建线程的方式比较多 1)最简单易用的<thread>头文件,但是这种方法创建的子线程中无法给主线程PostMessage消息(也可能是我操作有误,总之没成功) 2) ...
- PostMessage与SendMessage的区别(二)
在做基于窗口的Windows程序的时候,我们避免不了要向窗口发送消息,有两种方式,一种是PostMessage,另外一种是SendMessage.关于这两个宏,我是通过狠狠的看MSDN才搞明白的,那里 ...
- PostMessage与SendMessage各自的问题
深入解析SendMessage.PostMessage 本文将使用C++语言,在MFC框架的配合下给出PostMessage.SendMessage等的使用方式与使用不当造成的后果(讨论均针对自定义 ...
- MFC窗口重绘
Invalidate()与 UpdateAllViews()有什么分别 Invalidate()是让程序重画窗口. UpdateAllViews()是在DOC/VIEW结构中, 当一个视图的数据改变后 ...
- Windows窗口消息大全(转)
Windows窗口消息大全,全不全自己看 ////////////////////////////////////////////////////////////////////////// #inc ...
- MFC的消息机制
MFC的消息循环(::GetMessage,::PeekMessage)消息泵(CWinThread::PumpMessage)和MFC的消息在窗口之间的路由是两件不同的事情 分两个步骤完成: 1 “ ...
- [8]windows内核情景分析--窗口消息
消息与钩子 众所周知,Windows系统是消息驱动的,现在我们就来看Windows的消息机制. 早期的Windows的窗口图形机制是在用户空间实现的,后来为了提高图形处理效率,将这部分移入内核空间,在 ...
- Windows窗口消息大全
////////////////////////////////////////////////////////////////////////// #include "AFXPRIV.H& ...
随机推荐
- SQLite数据库中rowid使用
SQLite数据库中rowid使用 SQLite中每个表都默认包含一个隐藏列rowid,使用WITHOUT ROWID定义的表除外.通常情况下,rowid可以唯一的标记表中的每个记录.表中插入的第 ...
- BZOJ1367【Baltic2004】sequence
题面 Description Input Output 一个整数R Sample Input 7 9 4 8 20 14 15 18 Sample Output 13 Hint 所求的Z序列为6,7, ...
- mac 安装scrapy
https://jingyan.baidu.com/article/14bd256e748346bb6d2612be.html 1.安装Python 安装完了记得配置环境,将python目录和pyth ...
- linux下添加自动启动项,linux 开机自动启动脚本方法
#service servicename status是当前状态#chkconfig --list servicename是查看启动状态,也就是是否开机自动启动 首先写好脚本,如 mysql,把它放到 ...
- 文件系统之-JAVA Sftp远程操作:
转载:http://blog.csdn.net/lee272616/article/details/52789018 java远程操作文件服务器(linux),使用sftp协议版本会持续更新,当前版本 ...
- Android记录24-WebView实现白天/夜间阅读模式
前言 本篇博客给大家分享一个WebView的使用案例.实现Android调用JavaScript代码来控制白天/夜间模式. 关于WebView怎样使用,官网有非常好的说明,Building Web A ...
- vue2.0 自定义 图片上传(UpLoader)组件
1.自定义组件 UpLoader.vue <!-- 上传图片 组件 --> <template> <div class="vue-uploader"& ...
- 每日一支TED——帕特里夏·瑞安:不要固执于英语
瑞安讲述了她在科威特教学英语30年最大的 关于语言的一个感受:英语在迅速的在全世界传播,而其它的语言在逐渐的消失. 瑞安想要说的是.拥有一种国际性的语言,大家都能够理解,让全部人的 ...
- UVA10317- Equating Equations(回溯+剪枝)
题目链接 题意:给出一个式子,但这个式子不一定是等式,在'+','-','='符号位置不变的情况下,又一次排列数字的位置,使其成为等式.假设能够的话.输出当中一种排列方式. 思路:我们将等号右边的数所 ...
- C语言关键字—-sizeof 、typedef、const、static、register、extern、#define
关键字:sizeof .#define.typedef.const.static.register.extern sizeof 1. 作用:求数据所占得内存空间大小 2. 本质:求数据得类型所占的内存 ...