Windows编程中消息处理函数的问题
rt,TranslateMessage和DispatchMessage函数是干嘛用的?百度百科上说:函数功能:该函数将虚拟键消息转换为字符消息。字符消息被寄送到调用线程的...
rt,TranslateMessage和DispatchMessage函数是干嘛用的?
百度百科上说:函数功能:该函数将虚拟键消息转换为字符消息。字符消息被寄送到调用线程的消息队列里,当下一次线程调用函数GetMessage或PeekMessage时被读出。
什么叫虚拟键消息,什么叫字符消息
为什么要在消息循环中连续调用这两个函数
还有,Window类中的style的值中有一个是CS_CLASSDC,是什么样式 展开
百度百科上说:函数功能:该函数将虚拟键消息转换为字符消息。字符消息被寄送到调用线程的消息队列里,当下一次线程调用函数GetMessage或PeekMessage时被读出。
什么叫虚拟键消息,什么叫字符消息
为什么要在消息循环中连续调用这两个函数
还有,Window类中的style的值中有一个是CS_CLASSDC,是什么样式 展开
4个回答
展开全部
是个挺复杂的问题啊!
1)从消息机制角度讲,WINDOWS里有两类线程。一种是可以接受消息的线程,一种是不接受消息的线程。区别在于,WINDOWS系统会为接受消息的线程开辟一个内存块,在其中维护一个数据结构,而不接受消息的线程则没有这样的数据结构。触发WINDOWS为线程添加这样的数据结构的条件基本上有2种情况:一是在我们的程序里调用了涉及窗口的API,像创建了一个窗口如使用了CREATEWINDOW,或显示一个窗口如SHOWWINDOW;二是调用了涉及消息的API,如GETMESSAGE,PEEKMESSAGE。
2)线程中有关处理消息的这个数据结构中集中了几个队列,按优先处理顺序是1.发送消息队列2.投送消息队列3.虚拟输入队列4.屏幕重画队列5.定时器队列。在程序中调用SENDMESSAGE就把消息发送到了发送消息队列中,通过POSTMESSAGE就把消息发送到了投送消息队列中,键盘按键(分按下和弹起2个动作,因此按一个键时总是先把WM_(SYS)KEYDOWN发送到虚拟消息队列中,然后再将WM_(SYS)KEYUP消息发到虚拟消息队列中)和鼠标按键消息被发送到虚拟消息队列中。
3)对应于每一个队列有一个标志变量,譬如,如果在发送消息队列里有一个WM_CREATE的消息时,发送消息标志变量是打开的(代码理解为标识变量--》a=0表示关闭,a=1表示打开)。当调用GETMESSAGE或PEEKMESSAGE时会首先检查发送消息标志变量,从而能确定在发送消息队列中是否有消息,如果有消息,GETMESSAGE和PEEKMESSAGE直接在它们函数体中调用对应该消息的窗口处理函数来处理该消息(GETMESSAGE和带PM_REMOVE参数的PEEKMESSAGE在发现该消息时,还要把该消息从队列中给删除,否则像不带PM_REMOVE参数的PEEKMESSAGE就会重复去处理该消息)。当该消息处理完后,GETMESSAGE和PEEKMESSAGE是不会结束的,在它们的函数体中是通过WHILE来保持循环检查消息队列的。因此当刚才列举的WM_CREATE消息处理完后,它会重新再检查发送消息队列标识变量,直到发送消息队列中没有消息为止。然后它再去按顺序检查投送消息队列,如果里面发现了一个WM_COMMAND消息,那GETMESSAGE和PEEKMESSAGE就会终止运行,调用RETURN,返回到我们的程序中,返回值为TRUE(看下GETMESSAGE和PEEKMESSAGE的函数声明)。还记得我们再调用这两个函数时,需要传递一个LPMSG的消息结构吗,当GETMESSAGE和PEEKMESSAGE返回前,它会把它在投送消息队列和虚拟输入消息队列中发现的消息复制到这个LPMSG的变量中。
4)当GETMESSAGE和PEEKMESSAGE返回时,如果再调用TRANSLATEMESSAGE时,TRANSLATEMESSAGE会检查参数LPMSG(看TRANSLATEMESSAGE函数声明,它需要接受一个LPMSG类型的参数,该参数是在前面调用GETMESSAGE和PEEKMESSAGE时已经被填充了内容了)。如果在LPMSG发现了WM_(SYS)KEYDOWN消息,TRANSLATEMESSAGE会把该消息处理成为WM_CHAR消息,然后再调用POSTMESSAGE,把该WM_CHAR消息投送到线程的投送消息队列中,当以后再调用GETMESSAGE和PEEKMESSAGE时,该消息才会被这两个函数填充进LPMSG中。
5)TRANSLATEMESSAGE返回后,需要调用DISPATCHMESSAGE。它的作用是对LPMSG中的消息进行处理,譬如当它发现LPMSG中有个WM_CHAR时,它会调用对应于该消息的窗口处理函数进行处理,处理完后该函数返回。
以上是消息机制的一部分(基本上针对了你的问题回答了)
WINDOWS的消息处理机制是非常复杂的,而且当你看有关消息的API以及窗口过程时,会很茫然。初学者是这样的,不要心急,慢慢来。如同七龙珠一般,慢慢搜集,把所有龙珠凑齐了,才能看到神秘的神龙!
1)从消息机制角度讲,WINDOWS里有两类线程。一种是可以接受消息的线程,一种是不接受消息的线程。区别在于,WINDOWS系统会为接受消息的线程开辟一个内存块,在其中维护一个数据结构,而不接受消息的线程则没有这样的数据结构。触发WINDOWS为线程添加这样的数据结构的条件基本上有2种情况:一是在我们的程序里调用了涉及窗口的API,像创建了一个窗口如使用了CREATEWINDOW,或显示一个窗口如SHOWWINDOW;二是调用了涉及消息的API,如GETMESSAGE,PEEKMESSAGE。
2)线程中有关处理消息的这个数据结构中集中了几个队列,按优先处理顺序是1.发送消息队列2.投送消息队列3.虚拟输入队列4.屏幕重画队列5.定时器队列。在程序中调用SENDMESSAGE就把消息发送到了发送消息队列中,通过POSTMESSAGE就把消息发送到了投送消息队列中,键盘按键(分按下和弹起2个动作,因此按一个键时总是先把WM_(SYS)KEYDOWN发送到虚拟消息队列中,然后再将WM_(SYS)KEYUP消息发到虚拟消息队列中)和鼠标按键消息被发送到虚拟消息队列中。
3)对应于每一个队列有一个标志变量,譬如,如果在发送消息队列里有一个WM_CREATE的消息时,发送消息标志变量是打开的(代码理解为标识变量--》a=0表示关闭,a=1表示打开)。当调用GETMESSAGE或PEEKMESSAGE时会首先检查发送消息标志变量,从而能确定在发送消息队列中是否有消息,如果有消息,GETMESSAGE和PEEKMESSAGE直接在它们函数体中调用对应该消息的窗口处理函数来处理该消息(GETMESSAGE和带PM_REMOVE参数的PEEKMESSAGE在发现该消息时,还要把该消息从队列中给删除,否则像不带PM_REMOVE参数的PEEKMESSAGE就会重复去处理该消息)。当该消息处理完后,GETMESSAGE和PEEKMESSAGE是不会结束的,在它们的函数体中是通过WHILE来保持循环检查消息队列的。因此当刚才列举的WM_CREATE消息处理完后,它会重新再检查发送消息队列标识变量,直到发送消息队列中没有消息为止。然后它再去按顺序检查投送消息队列,如果里面发现了一个WM_COMMAND消息,那GETMESSAGE和PEEKMESSAGE就会终止运行,调用RETURN,返回到我们的程序中,返回值为TRUE(看下GETMESSAGE和PEEKMESSAGE的函数声明)。还记得我们再调用这两个函数时,需要传递一个LPMSG的消息结构吗,当GETMESSAGE和PEEKMESSAGE返回前,它会把它在投送消息队列和虚拟输入消息队列中发现的消息复制到这个LPMSG的变量中。
4)当GETMESSAGE和PEEKMESSAGE返回时,如果再调用TRANSLATEMESSAGE时,TRANSLATEMESSAGE会检查参数LPMSG(看TRANSLATEMESSAGE函数声明,它需要接受一个LPMSG类型的参数,该参数是在前面调用GETMESSAGE和PEEKMESSAGE时已经被填充了内容了)。如果在LPMSG发现了WM_(SYS)KEYDOWN消息,TRANSLATEMESSAGE会把该消息处理成为WM_CHAR消息,然后再调用POSTMESSAGE,把该WM_CHAR消息投送到线程的投送消息队列中,当以后再调用GETMESSAGE和PEEKMESSAGE时,该消息才会被这两个函数填充进LPMSG中。
5)TRANSLATEMESSAGE返回后,需要调用DISPATCHMESSAGE。它的作用是对LPMSG中的消息进行处理,譬如当它发现LPMSG中有个WM_CHAR时,它会调用对应于该消息的窗口处理函数进行处理,处理完后该函数返回。
以上是消息机制的一部分(基本上针对了你的问题回答了)
WINDOWS的消息处理机制是非常复杂的,而且当你看有关消息的API以及窗口过程时,会很茫然。初学者是这样的,不要心急,慢慢来。如同七龙珠一般,慢慢搜集,把所有龙珠凑齐了,才能看到神秘的神龙!
展开全部
Win32程序主消息循环的标准写法是:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
首先使用 GetMessage() 函数获取消息,然后用TranslateMessage()函数转化消息,这样做的目的是,获取一些按键消息(虚拟键如ESC、Ctrl、Atl、箭头等等)转化为ASCll字符的键产生WM_CHAR消息(这样系统才可以识别),DispatchMessage再将消息转发给系统。
比如:VK_RETURN 回车键对应的ASCll字符为0x0D
VK_RETURN 就是虚拟键消息,0x0D就是字符消息
连续调用的目的就是使你的程序一直在消息循环中,因为Windows程序运行的机制就是基于消息循环的,没有了消息循环程序就不能相应对它的操作了。
补充:
WNDCLASS结构的第一个成员style表示窗口类的风格,它往往是由一些基本的风格通过位的“或”操作(操作符位“|”)组合而成。以下列出了一些常用的基本窗口风格:
CS_HREDRAW 如果窗口客户区宽度发生改变,重绘整个窗口
CS_VREDRAW 如果窗口客户区高度发生改变,重绘整个窗口
CS_DBLCLKS 能感受用户在窗口中的双击消息
CS_NOCLOSE 禁用系统菜单中的“关闭”命令
CS_OWNDC 为该窗口类的各窗口分配各自独立的设备环境
CS_CLASSDC 为该窗口类的各窗口分配一个共享的设备环境
CS_PARENTDC 指定子窗口继承其父窗口的设备环境
CS_SAVEBITS 把被窗口遮掩的屏幕图象部分作为位图保存起来。当该窗口被移动时,Windows使用被保存的位图来重建屏幕图象
CS_CLASSDC就表示为该窗口类的各窗口分配一个共享的设备环境
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
首先使用 GetMessage() 函数获取消息,然后用TranslateMessage()函数转化消息,这样做的目的是,获取一些按键消息(虚拟键如ESC、Ctrl、Atl、箭头等等)转化为ASCll字符的键产生WM_CHAR消息(这样系统才可以识别),DispatchMessage再将消息转发给系统。
比如:VK_RETURN 回车键对应的ASCll字符为0x0D
VK_RETURN 就是虚拟键消息,0x0D就是字符消息
连续调用的目的就是使你的程序一直在消息循环中,因为Windows程序运行的机制就是基于消息循环的,没有了消息循环程序就不能相应对它的操作了。
补充:
WNDCLASS结构的第一个成员style表示窗口类的风格,它往往是由一些基本的风格通过位的“或”操作(操作符位“|”)组合而成。以下列出了一些常用的基本窗口风格:
CS_HREDRAW 如果窗口客户区宽度发生改变,重绘整个窗口
CS_VREDRAW 如果窗口客户区高度发生改变,重绘整个窗口
CS_DBLCLKS 能感受用户在窗口中的双击消息
CS_NOCLOSE 禁用系统菜单中的“关闭”命令
CS_OWNDC 为该窗口类的各窗口分配各自独立的设备环境
CS_CLASSDC 为该窗口类的各窗口分配一个共享的设备环境
CS_PARENTDC 指定子窗口继承其父窗口的设备环境
CS_SAVEBITS 把被窗口遮掩的屏幕图象部分作为位图保存起来。当该窗口被移动时,Windows使用被保存的位图来重建屏幕图象
CS_CLASSDC就表示为该窗口类的各窗口分配一个共享的设备环境
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
往往等级高的人回答得都不太好。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
比如:当按下键盘和施放键盘时分别产生WM_KEYDOWN或WM_SYSKEYDOWN WM_KEYUP或WM_SYSKEYUP消息并把这些虚拟键消息放入 系统消息队列中 (即 此时系统消息队列中的存储WM_KEYDOWN或WM_SYSKEYDOWN WM_KEYUP或WM_SYSKEYUP) ,对于上面来说虚拟键消息就是WM_KEYDOWN ,WM_SYSKEYDOWN,
WM_KEYUP,WM_SYSKEYUP
某些击键消息可以被转换成字符消息,例如字母键、数字键等。
字符消息:就是在键盘上的一些键(字母键、数字键等)被点击,则产生击键消息,而这些消息可以转换成字符ASCII。
因为线程消息队列存储的只能是WM_CHAR消息,如果你的应用程序必须获得用户输入的字符,那还需要TranslateMessage这个函数。
WM_KEYUP,WM_SYSKEYUP
某些击键消息可以被转换成字符消息,例如字母键、数字键等。
字符消息:就是在键盘上的一些键(字母键、数字键等)被点击,则产生击键消息,而这些消息可以转换成字符ASCII。
因为线程消息队列存储的只能是WM_CHAR消息,如果你的应用程序必须获得用户输入的字符,那还需要TranslateMessage这个函数。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询