Windows消息机制VC
在Windows中,用户或系统中所发生的任何活动被当作事件来处理,例如,用户按下了鼠标按钮,就产生一鼠标事件。对于所发生的每一个事件,Windows将其转换成消息的形式放在一个称为消息队列的内存区中,然后由Windows的消息发送程序选择适合的对象,将消息队列中的消息发送到欲接受消息的对象上。Windows的消息可分为四种类型:
(1)输入消息:对键盘和鼠标输入作反应。这类输入消息首先放在系统消息队列中,然后Windows将它们送入应用程序的消息队列,使消息得到处理。
(2)控制消息:用来与Windows的特殊控制对象,例如,对话框、列表框、按钮等进行双向通信。这类消息一般不通过应用程序的消息队列,而是直接发送到控制对象上。
(3)系统消息:对程式化的事件或系统时钟中断作出反应。有些系统消息,例如大部分DDE消息(程序间进行动态数据交换时所使用的消息)要通过Windows的系统消息队列。而有些系统消息,例如窗口的创建及删除等消息直接送入应用程序的消息队列。
(4)用户消息:这些消息是程序员创建的,通常,这些消息只从应用程序的某一部分进入到该应用程序的另一部分而被处理,不会离开应用程序。用户消息经常用来处理选单操作:一个用户消息与选单中的一选项相对应,当它在应用程序队列中出现时被处理。
Windows应用程序通过执行一段称为消息循环的代码来轮询应用程序的消息队列,从中检索出该程序要处理的消息,并立即将检索到的消息发送到有关的对象上。典型的Windows应用程序的消息循环的形式为:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0L))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
函数GetMessage从应用程序队列中检索出一条消息,并将它存于具有MSG类型的一个变量中,然后交由函数TranslateMessage对该消息进行翻译,紧接着,函数DispatchMessage将消息发送到适当的对象上。
关于自定义消息的参数
自定义消息如果光是消息那只能是一个通知。
你知道什么时候该干什么事了。但是有的情况下需要具体的数据。这样参数就起作用了。
比如说要在消息处理中填充一个结构。
如struct mystruct{
int i;
char buf[255];
}
可以把这个结构的一个指针强制转换为long ,即(lparam)&mystruct,然后做为消息参数进入消息处理函数。 其他结构可以此类推。
消息处理函数只要将WParam 或是LParam 强制转换为mystruct * 就可以只用这个结构指针。可以为这个结构中的成员附值。或是使用这个结构中的数据。
1.SendMessage函数功能描述:将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口过程,直到窗口过程处理完消息后才返回。
.函数原型:
LRESULT SendMessage(
HWND hWnd, // 目标窗口句柄
UINT Msg, // 被发送的消息
WPARAM wParam, // 第一个消息参数
LPARAM lParam // 第二个消息参数
);
.参数:
hWnd
窗口过程接收消息的窗口句柄。如果此参数为HWND_BROADCAST,则消息被送到系统的所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口。消息不被送到子窗口。
Msg
指定被发送的消息;
wParam
指定附加消息的特定信息;
lParam
指定附加消息的特定信息。
.返回值:
返回值返回消息处理的结果,其依赖于所发送的消息。
.备注:
需要以 HWND_BROADCAST 方式通信的应用程序应该使用 RegisterWindowMessage 函数来获得应用程序间通信的独特消息。
如果指定的窗口通过调用线程被创建,则窗口过程作为子程序被立即调用。如果指定的窗口通过调用不同线程被创建,则系统切换到该线程并调用适当的窗口过程。线程间的消息只有在接收线程执行消息检索代码时才被处理。发送线程将被阻塞到接收线程处理完消息为止。
Windows CE:Windows CE不支持Windows桌面平台所支持的所有消息。在使用SendMessage函数之前,应检查发送的消息是否被Windows CE所支持。
.使用环境:
Windows NT: 3.1及以上版本;
Windows:95及以上版本;
Windows CE:1.0及以上版本;
头文件:winuser.h;
输入库:user32.lib;
Unicode:在WindowsNT(Windows2000)环境下以Unicode和ANSI方式实现。
.示例代码:
case WM_KEYDOWN: switch (wParam) { case VK_HOME: SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0) ; break ; case VK_END: SendMessage (hwnd, WM_VSCROLL, SB_BOTTOM, 0) ; break ; case VK_PRIOR: SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0) ; break ; ... } return 0 ; ...
.常见问题
1)使用SendMessage来实现剪切、复制和粘贴
SendMessage(hwnd, WM_COPY, 0, 0); SendMessage(hwnd, WM_CUT, 0, 0); SendMessage(hwnd, WM_PASTE, 0, 0);
2)SendMessage与PostMessage的区别
PostMessage将消息放入消息队列后马上返回,而SendMessage直到窗口过程处理完消息后才返回
3)SendMessage发送WM_COPYDATA消息在进程间传送数据
WM_COPYDATA消息主要目的是允许在进程间传递少量只读数据。SDK文档推荐用户使用SendMessage()函数,接收方在数据复制完成前不返回,这样发送方就不可能删除和修改数据。
例如:
std:string strData = "VC知识库 VCKBASE.COM"; COPYDATASTRUCT cds; cds.dwData = 0; cds.cbData = strData.Length(); cds.lpData = strData.c_str(); ::SendMessage(hwnd, WM_COPYDATA, NULL, (LPARAM)&cds);
SendMessageCallback(hWnd,WM_LBUTTONUP,0,0,SendAsyncProc,0);
VOID CALLBACK SendAsyncProc(HWND hwnd,UINT uMsg,DWORD dwData,LRESULT lResult)
{
MessageBox(NULL,"Back From Main Window","SendMessageCallback",MB_OK);
//下面可以进行更进一步的处理
}
的线程也死掉了,
下面是我的代码
大概就是在用SendMessageCallback发送消息给对话框之前,创建一个Event,设置为无信号,然后在
对话框的消息响应中等待Event变为有信号才继续执行,根据书上所说,SendMessageCallback()在发送会就返回,
那么发送消息的线程就应该不会因为对话框在处理消息时候因为等待Event而给堵塞住,这样发送线程就可以继续执行下面的SetEvent,
这样对话框WaitForSingleObject()得以返回,这样它也可以得以继续执行
。
void CMainFrame::OnOpendialog()
{
//该函数创建一个无模式对话框
CWorkingDialog* pdlg=new CWorkingDialog;
ASSERT_VALID(pdlg);
//Create the modeless dialog . represents this dialog.
BOOL bResult = pdlg-> Create(IDD_DIALOG1);
CString strMsg= "From MainFrame ";
HANDLE hEvent=CreateEvent(NULL,TRUE,FALSE, "wait ");//创建事件通知 ,手动,无信号
SendMessageCallback(pdlg-> GetSafeHwnd(),WM_MSG,(WPARAM)(LPCTSTR)strMsg,0,FunCallback,0);
strMsg= "Yes ";
SetEvent(hEvent);
}
//响应wm_msg
void CWorkingDialog::OnTestMsg(WPARAM wParam ,LPARAM lParam)
{
HANDLE hEvent = CreateEvent(NULL,TRUE,FALSE, "wait ");
ASSERT(GetLastError()==ERROR_ALREADY_EXISTS);
CString str((LPCTSTR)wParam);
WaitForSingleObject(hEvent,INFINITE);//等到有信号才执行下面的代码
MessageBox(str);
}
但是这段代码运行结果跟我上面的猜想不一致,是不是我对SendMessageCallback的“发送就返回”理解错误?
原因是对于SendMessageCallback()函数, 如果发送到当前线程中,则直接调用窗口过程,发送到其它线程中则立即返回。
HANDLE hThread;
DWORD ThreadID;
//创建一个线程,把当前的窗口句柄作为参数传递给新线程
hThread=CreateThread(NULL,0,Thread1,hWnd,NULL,&ThreadID);
break;
case WM_LBUTTONDOWN:
MessageBox(NULL,"Receiving Message:WM_LBUTTONDOWN","MESSAGE",MB_OK);
break;
DWORD WINAPI Thread1(LPVOID param)
{
HWND hWnd=(HWND)param;
SendNotifyMessage(hWnd,WM_LBUTTONDOWN,0,0);
//一般情况下,这个消息框要比上面那个消息框早出现,因为函数并不等待消息
//处理完成之后才返回
MessageBox(NULL,"Return From SendNotifyMessage","SendNotifyMessage",MB_OK);
return 1;
}
HANDLE hThread;
DWORD ThreadID;
//创建一个线程,把当前的窗口句柄作为参数传递给新线程
hThread=CreateThread(NULL,0,Thread1,hWnd,NULL,&ThreadID);
break;
case WM_LBUTTONDOWN:
Sleep(5000);//睡眠5秒
MessageBox(NULL,"Receving Messageg:LBUTTONDOWN","MESSAGE",MB_OK);
break;
{
HWND hWnd=(HWND)param;
DWORD dwResult;
LRESULT ret;
//只等待三秒
ret=SendMessageTimeout(hWnd,WM_LBUTTONDOWN,0,0,SMTO_BLOCK,3000,&dwResult);
if(ret==0)
MessageBox(NULL,"Fail To Process Message","SendMessageTimeout",MB_OK);
else
MessageBox(NULL,"Success To Process Message","SendMessageTimeout",MB_OK);
return 1;
}
后 if(ret==0);但是Sleep(5000);先 if(ret==0)后MessageBox(NULL,"Receving Messageg:LBUTTONDOWN","MESSAGE",MB_OK);
HANDLE hThread;
DWORD ThreadID,LocalThreadID;
//将当前线程ID作为参数传递给新线程
LocalThreadID=GetCurrentThreadId();
hThread=CreateThread(NULL,0,Thread1,(LPVOID)LocalThreadID,NULL,&ThreadID);
break;
DWORD WINAPI Thread1(LPVOID param)
{
DWORD MainThreadID;
MainThreadID=(DWORD)param;
//向主线程发送一条消息
PostThreadMessage(MainThreadID,WM_LBUTTONDOWN,0,0);
return 1;
}
#define WM_POSTMESSAGE WM_USER+2
MessageBox(NULL,"本对话框结束之后SendMessage才会返回!","SendMessage",MB_OK);
break;
case WM_POSTMESSAGE:
MessageBox(NULL,"本对话框结束之前PostMessage已经返回!","SendMessage",MB_OK);
break;
case WM_RBUTTONDOWN:
HANDLE hThread;
DWORD ThreadID;
//创建一个线程,将当前的窗口句柄作为参数传递给该新创建的线程
hThread=CreateThread(NULL,0,Thread1,hWnd,NULL,&ThreadID);
break;
DWORD WINAPI Thread1(LPVOID param)
{
HWND hWnd;
hWnd=(HWND)param;
//可以比较下面两种发送消息的差别
PostMessage(hWnd,WM_POSTMESSAGE,0,0);
// SendMessage(hWnd,WM_SENDMESSAGE,0,0);
return 1;
}
PostQuitMessage(1);
我想用BroadcastSystemMessage来在两个进程之间通讯,我从一个进程发送了一个用 RegisterWindowMessage注册过的消息,但在目的进程中却没有收到该消息.
A:我认为你应该在两个进程的最高级窗口中都注册该消息.请看下例:
static UINT sBroadcastCommand = ::RegisterWindowMessage( _T("BroadcastCommand")); BEGIN_MESSAGE_MAP( Gui_Top_Level_MainFrame, Gui_MainFrame ) ON_REGISTERED_MESSAGE( sBroadcastCommand, onBroadcastCommand ) END_MESSAGE_MAP() LRESULT Gui_MainFrame :: onBroadcastCommand( UINT aMsg, LPARAM lParam ) { your code... }
然后发送进行应该包含:
While the sending process would contain: static UINT sBroadcastCommand = ::RegisterWindowMessage( _T("BroadcastCommand")); void Someclass :: someMethod( void ) { ::PostMessage( (HWND)HWND_BROADCAST,sBroadcastCommand, 0,yourMessageId ); }
9.ReplyMessage
函数功能:该函数用于应答由函数SendMessage发送的消息,不返回控制给调用SendMessage的函数。函数原型:BOOL ReplyMessage(LRESULTIResult);参数:IResult:指定消息处理的结果。可能的值由所发送的消息确定。返回值:如果调用线程正处理从其他线程或进程发送的消息,返回非零值。如果调用线程不是正处理从其他线程或进程发送的消息,返回值是零。备注:调用此函数,接收消息的窗口程序允许调用SendMessage的线程继续运行,尽管接收消息的线程已返回控制。调用ReplyMessage的线程也继续运行。如果消息不是通过SendMessage发送的,或者消息由同一个线程发送,ReplyMessage不起作用。
case WM_LBUTTONDOWN: LRESULT result; result=1; //去掉下面语句,则SendMessage函数将等待5秒钟才会返回 ReplyMessage(result); Sleep(5000); break;
//具体的线程函数实现DWORD WINAPI Thread1(LPVOID param){ HWND hWnd=(HWND)param; SendMessage(hWnd,WM_LBUTTONDOWN,0,0); MessageBox(NULL,"Come Back","SendMessage",MB_OK); return 1;}
while (WaitMessage()){ PeekMessage(&msg,NULL,0,0,PM_REMOVE); if(msg.message==WM_QUIT) break; //上面的几条语句相当于while(GetMessage(&msg,NULL,0,0) if(msg.hwnd==NULL) MessageBox(NULL,"Receive Message From PostThreadMessage", "PostThreadMessage",MB_OK); if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
10.
函数GetMessage 是 从调用线程的消息队列里取得一个消息并将其放于指定的结构。此函数可取得与指定窗口联系的消息和由PostThreadMesssge寄送的线程消息。此函数接收一定范围的消息值。GetMessage不接收属于其他线程或应用程序的消息。获取消息成功后,线程将从消息队列中删除该消息。函数会一直等待直到有消息到来才有返回值。
GetMessage
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
MSG msg1;
//从这里可以看出,该函数将WM_KEYDOWN消息转换为WM_CHAR等消息
//在消息队列中只有WM_KEYDOWN消息的情况下就将其转换为WM_CHAR了
if(PeekMessage(&msg1,NULL,WM_CHAR,WM_CHAR,PM_NOREMOVE))
MessageBox(NULL,"Find WM_CHAR Message","WM_CHAR",MB_OK);
DispatchMessage(&msg);
}
}
转载于:https://www.cnblogs.com/springmvc-hibernate/archive/2011/03/31/2484145.html
Windows消息机制VC相关推荐
- windows消息机制详解-3
1. 引言 Windows 在操作系统平台占有绝对统治地位,基于Windows 的编程和开发越来越广泛. Dos 是过程驱动的,而Windows 是事件驱动的[6],这种差别的存在使得很多Dos 程序 ...
- Windows消息机制学习笔记(三)—— 消息的接收与分发
Windows消息机制学习笔记(三)-- 消息的接收与分发 要点回顾 消息循环 消息队列 消息的接收 GetMessage 实验1:理解GetMessage 第一步:编译并运行程序A 第二步:编译并运 ...
- Windows消息机制学习笔记(二)—— 窗口与线程
Windows消息机制学习笔记(二)-- 窗口与线程 要点回顾 消息从哪里来? 实验一:Spy++捕获消息 实验二:消息捕获 消息到哪里去? 窗口在哪? 实验:分析CreateWindowExW 窗口 ...
- Windows消息机制学习笔记(一)—— 消息队列
Windows消息机制学习笔记(一)-- 消息队列 基本概念 实验一:使用代码画出最简单窗口 第一步:编译并运行以下代码 第二步:查看运行结果 第三步:使用其它窗口对其进行覆盖,观察效果 总结 消息队 ...
- windows消息机制和Linux,Windows消息机制初谈 (转)
Windows消息机制初谈 (转)[@more@]是一个消息的OS,什么是消息呢?我很难说得清楚,也很难下一个定义(谁在嘘我),我下面从不同的几个方面讲解一下,希望大家看了后有一点了解. 1.消息的组 ...
- Windows消息机制-PreTranslateMessage
PreTranslateMessage作用和使用方法 Windows消息机制的流程: A. 操作系统接收应用程序的窗口消息,将消息投递到该应用程序的消息队列中 B. 应用程序在消息循环中调用GetMe ...
- Windows消息机制详解-5
一. 什么是消息 在解释什么是消息之前,我们先讨论一下程序的执行机制问题.大体上说,程序按照执行机制可以分为两类: 第一类是过程驱动.比如我们最早接触编程时写的C程序,又或者单片机程序.这类程序往往预 ...
- 【转】深入理解Windows消息机制
转自:https://blog.csdn.net/liulianglin/article/details/14449577 今天我们来学一学Windows消息机制,我们知道在传统的C语音程序中,当我们 ...
- SendMessage和PostMessage及Windows消息机制简介
SendMessage: The SendMessage function sends the specified message to a window or windows. It calls t ...
最新文章
- PyTorch 源码解读之分布式训练了解一下?
- 对于U盘做系统,win8降级到win7系统的心得体会
- IIS 7.x Application Request Routing(ARR) 502错误的解决方法
- 操作系统开发系列—2.进入32位保护模式
- UAF学习之Adobe reader CVE-2013-3346
- 我现在编程方面的特别大的问题
- [html] iframe框架都有哪些优缺点?
- 论文浅尝 - ICLR2020 | You Can Teach an Old Dog New Tricks!关于训练知识图谱嵌入
- SLAM方向公众号、知乎、博客学习参考
- Java、Android引用类型
- C语言回溯算法求幂集,回溯求幂集算法
- labview制成app_图形化编程软件(labview)
- python3 web服务器运行
- java resource文件_利用java如何实现读取resource目录下文件
- 二 关键词---关键词扩展(五)
- python算法详解 张玲玲_Python算法详解
- 免费下载音乐的爬虫小程序
- 习题 3.12 给出一个不多于5位的正整数,要求:1. 求出它是几位数;2. 分别打印出每一位数字;3. 按逆序打印出各位数字,例如原数位321,应输出123。
- 百度信息流是什么?哪些行业适合投放百度信息流?
- NetLogo基础代码
热门文章
- 深度学习的实用层面 —— 1.1 训练/开发/测试集
- windows下安装nodejs多版本管理工具nvm-windows
- Harris及Shi-Tomasi原理及源码【转载】
- Androidstudio项目更换gradle版本
- runtime批处理mysql导出_【原】使用批处理BAT文件处理Mysql数据库 | 学步园
- linux 自定义键盘布局,Ubuntu自定义键位xmodmap
- linux系统优化 io,Linux硬件IO的优化简介
- matlab inline feval,matlab中关于函数句柄、feval函数以及inline函数的解析
- android 自定义dialog 定时关闭,Android 快速实现自定义 Dialog
- hbase 预写日志_HBase存储结构