大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
TranslateMessage(&msg);
TranslateMessage是用来把快捷键消息转换为字符消息,并将转换后的新消息投递到调用线程的消息队列中。
由于Windows对所有键盘编码都是采用虚拟键的定义,这样当按键按下时,并不得字符消息,需要键盘映射转换为字符的消息。字符消息被投递到调用线程的消息队列中,当下一次调用GetMessage函数时被取出。
LONG DispatchMessage(CONST MSG*lpmsg);
函数功能:该函数分发一个消息给窗口程序,即把消息推送到afxwndproc,最后流向pwnd->windowproc,而DispatchMessage是在cwinapp::run 调用pumpmessage,而pumpmessage又调用DispatchMessage。通常消息从GetMessage函数获得或者TranslateMessage函数传递的。消息被分发到回调函数(过程函数),作用是消息传递给操作系统,然后操作系统去调用我们的回调函数,也就是说我们在窗体的过程函数中处理消息
在mfc2.5时代(九几年代),所有窗口类共享同一个窗口函数(即afxwndproc)。
但现在使用的是钩子技术(即hook),所以要关联hook章节一起看。
hook操作是在每一个cwnd派生类之对象产生之际发生。
所以DispatchMessage把消息推送到hook技术中的afxwndproc.
HOOK(钩子,挂钩)是一种实现Windows平台下类似于中断的机制。HOOK机制允许应用程序拦截并处理Windows消息或指定事件,当指定的消息发出后,HOOK程序就可以在消息到达目标窗口之前将其捕获,从而得到对消息的控制权,进而可以对该消息进行处理或修改,加入我们所需的功能。
定义钩子函数
钩子函数是一种特殊的回调函数。钩子监视的特定事件发生后,系统会调用钩子函数进行处理。不同事件的钩子函数的形式是各不相同的。下面以鼠标钩子函数举例说明钩子函数的原型:
LRESULT CALLBACK HookProc(int nCode ,WPARAM wParam,LPARAM lParam)
参数wParam和 lParam包含所钩消息的信息,比如鼠标位置、状态,键盘按键等。
安装钩子
在程序初始化的时候,调用函数SetWindowsHookEx安装钩子。其函数原型为:
HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId )
参数idHook表示钩子类型,它是和钩子函数类型一一对应的。比如,WH_KEYBOARD表示安装的是键盘钩子,WH_MOUSE表示是鼠标钩子等等。
卸载钩子
当不再使用钩子时,必须及时卸载。简单地调用函数:
BOOL UnhookWindowsHookEx( HHOOK hhk)即可。
PeekMessage和GetMessage函数的主要区别有:
GetMessage的主要功能是从消息队列中“取出”消息,消息被取出以后,就从消息队列中将其删除;而PeekMessage的主要功能是“窥视”消息,如果有消息,就返回true,否则返回false。也可以使用PeekMessage从消息队列中取出消息,这要用到它的一个参数(UINT wRemoveMsg),如果设置为PM_REMOVE,消息则被取出并从消息队列中删除;如果设置为PM_NOREMOVE,消息就不会从消息队列中取出。
如果GetMessage从消息队列中取不到消息,则线程就会被操作系统挂起,等到OS重新调度该线程时,两者的性质不同:使用GetMessage线程仍会被挂起,使用PeekMessage线程会得到CPU的控制权,运行一段时间。
GetMessage每次都会等待消息,直到取到消息才返回;而PeekMessage只是查询消息队列,没有消息就立即返回,从返回值判断是否取到了消息
PeekMessage是一个具有线程异步行为的函数,不管消息队列中是否有消息,函数都会立即返回。而GetMessage则是一个具有线程同步行为的函数,如果消息队列中没有消息的话,函数就会一直等待,直到消息队列中至少有一条消息时才返回。
另外:PumpMessage起到消息泵的作用,其原理就是使用GetMessage或PeekMessage函数从消息队列中逐个读取消息,然后进行必要处理之后再发送出去。我们可以使用PumpMessage默认处理过程,当然也可以自己修改消息处理的方式。通常我们在我们自己设计窗口时也会自己设计消息循环方式。即PumpMessage函数会调用GetMessage、TranslateMessage、DispatchMessage
一般wm_xx消息
wm_command
/*********************
1.windows消息循环
if (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg); //消息转化
DispatchMessage(&msg); //消息派遣. 把TranslateMessage转换的消息发送到窗口的消息处理函数,此函数在窗口注册时已经指定
}
执行过程:
消息循环调用GetMessage()从消息队列中查找消息进行处理,如果消息队列为空,程序将停止执行并等待(程序阻塞)。
事件发生时导致一个消息加入到消息队列(例如系统注册了一个鼠标点击事件),GetMessage()将返回一个正值,这表明有消息需要被处理,并且消息已经填充到传入的MSG参数中;当传入WM_QUIT消息时返回0;如果返回值为负表明发生了错误。
取出消息(在Msg变量中)并将其传递给TranslateMessage()函数,这个函数做一些额外的处理:将虚拟键值信息转换为字符信息。这一步实际上是可选的,但有些地方需要用到这一步。
DispatchMessage()函数将消息分发到消息的目标窗口,并且查找目标窗口过程函数,给窗口过程函数传递窗口句柄、消息、wParam、lParam等参数然后调用该函数。
在窗口过程函数中,检查消息和其他参数,你可以用它来实现你想要的操作。如果不想处理某些特殊的消息,你应该总是调用DefWindowProc()函数,系统将按按默认的方式处理这些消息(通常认为是不做任何操作)。
一旦一个消息处理完成,窗口过程函数返回,DispatchMessage()函数返回,继续循环处理下一个消息。
2. 函数定义
2.1GetMessage
BOOL WINAPI GetMessage(
_Out_ LPMSG lpMsg,
_In_opt_ HWND hWnd,
_In_ UINT wMsgFilterMin,
_In_ UINT wMsgFilterMax
);
GetMessage 函数的作用是从当前线程的消息队列里获取一个消息并填入 MSG 结构 中。
该函数只能获取调用线程的消息,不能获得其他线程的消息。成功获取消息后,线程将从消息队列中删除该消息。
使用 GetMessage 函数,如果消息队列为空,函数会一直等待直到有消息到来才有返回值。
2.2 TranslateMessage
//BOOL TranslateMessage(CONST MSG *lpMsg);
1
参数:lpMsg
指向一个含有用GetMessage或PeekMessage函数从调用线程的消息队列中取得消息信息的MSG结构的指针
函数功能描述:
将虚拟键消息转换为字符消息。字符消息被送到调用线程的消息队列中,在下一次线程调用函数GetMessage或PeekMessage时被读出。
TranslateMessage函数不修改由参数lpMsg指向的消息。
2.3 DispatchMessage
函数原型:LONG DispatchMessage(CONST MSG*lpmsg);
1
参数:
lpmsg:指向含有消息的MSG结构的指针。
返回值:
返回值是窗口程序返回的值。尽管返回值的含义依赖于被调度的消息,但返回值通常被忽略。
备注:
MSG结构必须包含有效的消息值。如果参数lpmsg指向一个WM_TIMER消息,并且WM_TIMER消息的参数IParam不为NULL,则调用IPa1ram指向的函数,而不是调用窗口程序。
3. 程序实例
如果处理时间大于定时器时间,按照处理时间循环。
如果处理时间小于定时器时间,按照定时器时间。
#pragma comment(lib,”user32″)
#include <stdio.h>
#include <time.h>
#include <sys/timeb.h>
#include <windows.h>
char datestr[16];
char timestr[16];
char mss[4];
void log(char *s) {
struct tm *now;
struct timeb tb;
ftime(&tb);
now = localtime(&tb.time);
sprintf(datestr, “%04d-%02d-%02d”, now->tm_year + 1900, now->tm_mon + 1, now->tm_mday);
sprintf(timestr, “%02d:%02d:%02d”, now->tm_hour, now->tm_min, now->tm_sec);
sprintf(mss, “%03d”, tb.millitm);
printf(“%s %s.%s %s”, datestr, timestr, mss, s);
}
VOID CALLBACK myTimerProc1(
HWND hwnd, // handle of window for timer messages
UINT uMsg, // WM_TIMER message ************
UINT idEvent, // timer identifier
DWORD dwTime // current system time)
{
log(“In myTimerProc1\n”);
}
VOID CALLBACK myTimerProc2(
HWND hwnd, // handle of window for timer messages
UINT uMsg, // WM_TIMER message
UINT idEvent, // timer identifier
DWORD dwTime // current system time)
{
log(“In myTimerProc2\n”);
}
int main()
{
MSG msg;
SetTimer(NULL, 0, 4000, myTimerProc1);
SetTimer(NULL, 1, 2000, myTimerProc2);
for (int i = 0; i<20; i++)
{
Sleep(1000);
log(“In main\n”);
if (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg); //消息处理
DispatchMessage(&msg); //消息派遣. 把TranslateMessage转换的消息发送到窗口的消息处理函数,此函数在窗口注册时已经指定
}
}
return 0;
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/194337.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...