至于windows操作系统之音信和音信队列

www.301.net 116

1. 问题

1. 窗口进程 
种种窗口会有八个名字为窗口进度的回调函数(WndProc),它满含七个参数,分别为:窗口句柄(Window
Handle),音讯ID(Message ID),和七个消息参数(wParam,
lParam),当窗口收到消息时系统就能够调用此窗口进程来拍卖音信。(所以叫回调函数卡塔 尔(阿拉伯语:قطر‎

音信是指什么?
    
音信系统对此一个win32程序来讲特别珍视,它是一个程序运营的动源泉。一个新闻,是系统定义的一个叁13个人的值,他唯大器晚成的概念了二个平地风波,向
Windows发出二个通报,告诉应用程序有个别事情时有发生了。比如,单击鼠标、改造窗口尺寸、按下键盘上的一个键都会使Windows发送三个音信给应用程序。
   
音讯我是作为二个笔录传递给应用程序的,这一个记录中包含了信息的花色以致别的音讯。比方,对于单击鼠标所产生的消息以来,那个记录中饱含了单击鼠标时的坐标。那些记录类型叫做MSG,MSG含有来自windows应用程序新闻队列的消息消息,它在Windows中宣示如下:

至于windows操作系统之音信和音信队列

有关新闻和音信队列
不像基于MS-DOS的应用程序,基于Windows的次序是事件驱动的。他们不做其余显示调用来赢得输入。而是经过等待系统传递给他俩。

系统为应用程序传递全数输入到程序中的分裂窗口。各种窗口都有一个称呼窗口进程的函数,用于拍卖全数到该窗口的输入。窗口管理进程管理输入,并将决定重临给系统。

假设三个顶层窗口截止响应音讯超越两秒,系统将会以为该窗口为非响应状态。在这里种气象下,系统将潜伏该窗口并用装有同等Z顺序,地点,尺寸和可视化属性的ghost窗口替代该窗口。这种情状下,允许客商移动它,只怕改动她的尺码,以致倒闭应用程序。然后,那也是独自能够做的动作,因为应用程序以往是不响应的。当在调节和测验情形下,系统不会时有发生ghost窗口。

其生机勃勃段子,商量如下大旨:
windows消息
系统以消息的样式传递输入到窗口的管理进程。系统和应用程序均可产生音讯。系统在每便输入事件时,爆发一个新闻,比方,当用于打击,移动鼠标或许点击滚动条风华正茂类的控件。应用程序引起系统改动也会引致系统爆发信息,举个例子叁个应用程序改变了系统的书体财富池只怕改动了他本身窗口的大大小小。一个应用程序可以发生这么的音讯,该消息能够指点她的窗口直接推行职分仍然和其余应用程序的窗口进行交互作用。

音讯分类:
系统定义信息
当系统和应用程序交互作用时,系统发送系统音信,以调节应用程序的操作以致给程序传递输入只怕别的音信。应用程序也足以发送系统音信,应用程序经常用那些音讯来决定通过先行登记的窗口类创建的窗口的一颦一笑。

音信常量标志内定了其所属系统预约义新闻体系。前缀明显能够翻译依旧管理的新闻类别。如下。
AMB/ABN ===application desktop toolbar
acm/acn ===animation control
cb/cbn ===combobox control
ccm ===generatl control
cdm ===common dialog box
dfm ===default contex menu
dl ===drag list box
sb ===status bar
tvm/tvn ===tree view contro
udm/udm === up-down controm
wm === general
……
tcm/tcn === tab control
{
Clipboard Messages Clipboard Notifications Common Dialog Box
Notifications Cursor Notifications Data Copy Message Desktop Window
Manager Messages Device Management Messages Dialog Box Notifications
Dynamic Data Exchange Messages Dynamic Data Exchange Notifications Hook
Notifications Keyboard Accelerator Messages Keyboard Accelerator
Notifications Keyboard Input Messages Keyboard Input Notifications Menu
Notifications Mouse Input Notifications Multiple Document Interface
Messages Raw Input Notifications Scroll Bar Notifications Timer
Notifications Window Messages Window Notifications
}

大概上,windows音讯覆盖了二个相比较宽的范围,包罗鼠标键盘,菜单,对话框输入,窗口创制管理,DDE动态数据沟通

应用程序定义的音信
应用程序能够创立音讯,其自身窗口能够动用,也能够用于和别的进度张开交互作用。

新闻标志符的值应用如下:
1.系统一保险留了0x0000-0x03ff(即wm_user-1),应用程序不得以利用这个值用于个人音讯
2.0×0400(WM_USECRUISER)-0x7fff能够用来个人音讯
3.要是应用程序在4.0系统上,你能够行使0x8000(wm_app)-0xbfff于民用新闻
4.RegisterWindowMessage再次回到的值在0XC000-0XFFFF之间。那么些函数的重返值,能够制止任何进度用同样值而引起的冲突

消息路由
采取使用两种方法来窗口进程音讯的路径:post类新闻是透过先进先出的消息队列格局,新闻队列是不经常存款和储蓄音讯的连串定义内存对象,以至sending类新闻直接达到窗口进度。

队列音信1
系统在同时可以显得任性数量的窗口。为了路由鼠标键盘输入到科学的窗口,系统选取了音讯队列。

系统珍惜了三个体系消息队列,并为每一种GUI线程维护了而三个线程专有消息队列。为了制止为非GUI线程过多成立信息队列,全体线程在开创风尚未音信队列。系统仅仅在线程第一遍发起有个别特地客商函数时,成立线程音讯队列;未有GUI函数调用将唤起新闻队列的创建。

未懂:
The system creates a thread-specific message queue only when the thread
makes its first call to one of the specific user functions; no GUI
function calls result in the creation of a message queue.

队列音信2
别的时候,客商移动鼠标,点击按键恐怕敲击键盘,鼠标大概键盘驱动将转移这一个输入为消息,并将它们放到系统音信队列中。系统在检测它们的目窗口时,同期从系统新闻队列中移除它们。然后将她们发送到音讯相关窗口的窗口成立线程。线程从它们的音信队列中摄取全数鼠标和键盘消息。线程从它们的种类中删去新闻,并引导系统将它们发送到准确的窗口进程进展拍卖。

除了WM_PATIN,WM_TIMER,WM_QUIT音讯外,系统直接将它们发送到音信队列的最后,以有限支持输入音讯的FIFO种类,仅当音讯对用中尚无任何音讯随后,WM_PATIN,WM_TIMER,WM_QUIT才被向前推至窗口管理进度。再不怕,多少个WM_PAINT音讯将被合併为贰个,鲜明全数顾客端无效区域到一个独门的区域。合并WM_PATINT正是为着减小窗口冲回客户区内容的次数。

从音讯队列中除去贰个音信后,应用程序将用DispatchMessage函数direct系统发送那几个音信到窗口管理进程以紧密管理。DispatchMessage未有发送音讯地方和时间到窗口进程,应用程序能够经过GetmessageTime和GetMessagePos函数。

当音信队列中一贯不消息的时候,线程能够利用WaitMessage函数来将调节器交给其余线程,那一个函数暂停线程,知道叁个新消息赶到,该函数才回到。

你也能够调用SetMessageExtraInfo来为当前音信队列附加一个值,通过GetMessageExtraInfo来获取那么些值。

非队列音信
绕过了系统和线程音讯队列,非队列音讯直接发送至窗口进度。系统独立发送非队列新闻来公告叁个窗口,贰个平地风波影响了它。比如,当客商激活叁个新窗口,系统一发布送给窗口
WM_ACTIVATE, WM_SETFOCUS, and
WM_SETCU锐界SO安德拉音讯。这么些音信公告窗口它已经被激活了,键盘输入正指向该窗口,鼠标光标已经移至了窗口边框内。当应用程序调用某个系统函数时,也会窗口非队列音讯,举个例子,应用程序在调用SetWindowPos时,系统将发送WM_WINDOWPOSCHANGED消息。

稍Wechat息发送非队列音信:BroadcastSystemMessage,
布罗兹castSystemMessageEx, SendMessage, SendMessage提姆eout, and
SendNotifyMessage.

新闻管理
多线程应用程序,会在各类创设了窗口的线程包罗一个音讯队列。

MSG msg;
BOOL bRet;

while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
多个应用程序能够通过调用PostQuitMessage来甘休其自己的音讯循环,响应应用程序主窗口的WM_DESTROY新闻,就比较独立。

PostMessage发送多个NULL窗口句柄的新闻,该音信将会被放在脚下线程音讯队列中,应用程序务必管理这么些消息。PostMessage也得以由此HWND_TOPMOST
句柄来给全部顶层窗口发送音讯。

PostMessage平素能够成功发送消息,日常是四个谬误的只要,举个例子音信队列是满的。二个应用程序应该核查PostMessage的重回值。要是退步了,须求再行发送新闻。

SendMessage日常客商父亲和儿子窗口之间的互相。

SendMessageCallback函数发送八个新闻,并登时回去,窗口进度在拍卖完这么些音讯后,系统将调用钦赐的回调函数。该回调函数的具体,请看SendAsyncProc

不时,你恐怕想向装有顶层窗口发送消息。比方,应用程序改动了光阴,能够透过SendMessage,并制订HWND_TOPMOST,发送WM_TIMECHANGE.你也得以经过BroadcastSystemMessage函数,并给lpdwRecipients参数制订BSN_APPLICATIONS

新闻死锁
1.SendMessage会等候窗口进程管理实现后才回到,假设窗口进度那时所在线程激昂调节权扬弃,那么僵早晨死锁。
2.如果接到线程附加到了和发送线程同多少个新闻队列,也将引致应用程序死锁的殡葬

注意,正在采取新闻的线程,不应有出示放任调控权;调用下边函数将引起线程隐秘吐弃调整权。
DialogBox
?DialogBoxIndirect
?DialogBoxIndirectParam
?DialogBoxParam
?GetMessage
?MessageBox
?PeekMessage
?SendMessage

为了制止地下死锁,思谋使用SendNotifyMessage可能SendMessageTimeout。要不然,窗口进程能够经过InSendMessage大概InSendMessageEx检查评定其收受到的音讯是不是来自别的线程.在管理二个新闻时,在调用下面列表中其它函数前,窗口进程应该调用InSendMessage(Ex).如果回去TRUE,窗口进程必需在yeild前,调用ReplyMessage函数。

系统广播新闻-略

总结:
1.消息分为系统定义音讯和客商自定义新闻,其ID值都有和谐的限制。
2.各种线程暗中认可是不曾音信队列的,线程独有在率先次调用顾客接口时(举个例子创设窗口卡塔尔国,系统才为其成立音讯队列。
3.系统本人爱抚贰个体系信息队列,然后还为每一个GUI线程线程维护三个线程特意新闻队列。
4.鼠标、键盘等驱动,首先将事件调换为音讯放置在系统消息队列中,然后系统又通过窗口来分明将其放入到哪些线程音讯队列中。
5.线程音信循环抽取音讯,进行拍卖,将音讯再派发给系统,系统调用消息对应的窗口进程。
6.PostMessage不一定成功,举例队列是满的。
7.制止消息死锁,比如收受新闻的窗口进程,在弃权前,必要检查测验音信是还是不是发自别的线程。不然别的线程将长日子等待。其实作者感到这里无法成为死锁嘛,毕竟照旧也许再施行的,只是岁月长度而已。
8.亟需留意wm_paint,wm_timer,wm_quit等优越信息
9.类别预约义新闻其实大都是那多少个控件音讯,文告音信,系统广播新闻等等。

当在console中调用API
ShellExecuteEx展开”test.iqy”文件时,发掘excel会hang住,console退出后excel才会响应,但一直双击”test.iqy”是向来不难点的,风趣的是其一场所只有在xp爆发,在win7上一向不那么些主题素材。

2 音讯类型 
1) 系统定义音讯(System-Defined Messages)
 
在SDK中优先定义好的新闻,非客户定义的,其范围在[0x0000, 0x03ff]时期,
能够分成以下三类:
1>窗口新闻(Windows Message) 
与窗口的内部运维有关,如成立窗口,绘制窗口,销毁窗口等。能够是相符的窗口,也能够是Dialog,控件等。
如:WM_CREATE, WM_PAINT, WM_MOUSEMOVE, WM_CTLCOLOR, WM_HSCROLL…
2>命令音信(Command Message):注意那类新闻通称为WM_COMMAND
与拍卖顾客诉求有关, 如单击菜单项或工具栏或控件时, 就能够时有发生命令音讯。
WM_COMMAND, LOWOENVISIOND(wParam)表示菜单项,工具栏按键或控件的ID。若是是控件,
HIWO福睿斯D(wParam)表示控件音信类型
3> 控件文告(Notify Message) 
控件通告音讯, 这是最灵敏的消息格式, 其Message, wParam,
lParam分别为:WM_NOTIFY,
控件ID,指向NMHDTiggo的指针。NMHDENVISION包蕴控件通告的剧情, 能够随便扩张。
2) 程序定义音信(Application-Defined Messages) 
顾客自定义的音信, 对于其范围好似下规定:
WM_USER: 0x0400-0x7FFF    (ex. WM_USER+10)
WM_APP(winver>4.0): 0x8000-0xBFFF (ex.WM_APP+4)
RegisterWindowMessage: 0xC000-0xFFFF

www.301.net 1typedef struct tagMsg
www.301.net 2{
www.301.net 3       HWND    hwnd;       //接收该新闻的窗口句柄
www.301.net 4       UINT    message;    //消息常量标记符,约等于我们普通所说的新闻号
www.301.net 5       WPARAM  wParam;     //叁九个人新闻的一定附加新闻,确切含义正视于信息值
www.301.net 6       LPARAM  lParam;     //33个人新闻的一定附加音信,确切含义信任于消息值
www.301.net 7       DWORubiconD   time;       //新闻创立时的日子
www.301.net 8       POINT   pt;         //新闻创立时的鼠标/光标在荧屏坐标系中的地方
www.301.net 9}MSG;
www.301.net 10

消息相关函数:

DispatchMessage

LONG DispatchMessage(
const MSG* lpmsg
);
1.该函数将音讯,通过系统派发给窗口进程
2.万一是一个机械漏刻消息,lParam参数不是空,

 

3 音信队列(Message Queues) 
Windows中有三种等级次序的音讯队列
1) 系统音信队列(System Message Queue) 那是四个种类唯大器晚成的Queue,设备驱动(mouse,
keyboard)会把操作输入转产生新闻存在系统队列中,然后系统会把此音讯放到目标窗口所在的线程的音信队列(thread-specific
message queue)中伺机管理
2) 线程新闻队列(Thread-specific Message Queue) 每一个GUI线程都会维护这么叁个线程信息队列。(这些队列唯有在线程调用GDI函数时才会成立,暗许不创建)。然后线程消息队列中的新闻会被送到对应的窗口进程(WndProc)管理.
专一:
线程音讯队列中WM_PAINT,WM_TIME锐界唯有在Queue中尚无别的音讯的时候才会被拍卖,WM_PAINT音讯还或者会被联合以提升作用。别的具有音信以先进先出(FIFO卡塔尔的办法被处理。

   
消息能够由系统或许应用程序发生。系统在发出输入事件时发出音讯。比如,
当顾客敲键,
移动鼠标只怕单击控件。系统也产生新闻以响应由应用程序带给的扭转,
比方应用程序改变系统字体制纠正变窗体大小。应用程序能够发生音信使窗体实践任务,只怕与别的应用程序中的窗口通信。

lParam指向一个函数地址,被调用的将是那个函数,而非窗口进度

GetMessage
应用程序使用该函数重回值来决定是不是终止新闻循环,并退出程序。

2. 复发步骤

4 队列音讯(Queued Messages)和非队列新闻(Non-Queued Messages)
1)队列信息(Queued Messages)
 
消息会先保存在新闻队列中,音讯循环会自此队列中取音讯并散发到各窗口管理
如鼠标,键盘音讯。
2) 非队列音讯(NonQueued Messages) 音讯会绕过系统音讯队列和线程新闻队列直接发送到窗口进度被拍卖
如: WM_ACTIVATE, WM_SETFOCUS, WM_SETCURSOR, WM_WINDOWPOSCHANGED 
瞩目: postMessage发送的新闻是队列信息,它会把信息Post到新闻队列中;
SendMessage发送的消息是非队列音信, 被直接送到窗口进程管理

消息中有哪些?
   我们提交了下边包车型客车笺注,是或不是会对音信结构有了二个相比清楚的认知?要是还没曾,那么大家再试着提交上边包车型地铁解说:
     hwnd
31位的窗口句柄。窗口能够是任何项目标显示器对象,因为Win32能力所能达到保险大超多可视对象的句柄(窗口、对话框、按键、编辑框等)。
    
message用于区分其余消息的常量值,这一个常量能够是Windows单元中预订义的常量,也能够是自定义的常量。信息标记符以常量命名的点子提议音信的含义。当窗口进度采取到音信随后,他就能够利用音信标志符来决定如哪处理信息。举个例子、WM_PAINT告诉窗口进度窗体客商区被转移了急需重绘。符号常量内定系统新闻归属的档案的次序,其前缀指明了处了解释音信的窗体的系列。
     wParam 经常是一个与音信有关的常量值,也大概是窗口或控件的句柄。
     lParam
经常是三个针对性内部存款和储蓄器中数量的指针。由于WParam、lParam和Pointer都以三十几个人的,由此,它们中间可以并行转换。

该函数将获得和hWnd也许其子窗口相关的新闻。

DWORD GetMessagePos(void);

复出情形:XP sp3 / Office 二〇〇五(其余office版本应该也得以,未有测量检验卡塔尔

5 PostMessage(PostThreadMessage), SendMessage 
PostMessage:把新闻放到钦赐窗口所在的线程新闻队列中后登时重返。
PostThreadMessage:把音讯放到内定线程的新闻队列中后立刻回去。
SendMessage:直接把信息送到窗口进度处理,管理完了才回去。

音讯标记符的值
    
系统一保险留新闻标记符的值在0x0000在0x03ff(WM_USEEnclave-1)范围。那几个值被系统定义新闻使用。应用程序不能动用那些值给和谐的音信。应用程序音讯从WM_USER(0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USE大切诺基到
0X7FFF范围的新闻由应用程序本身行使;0XC000到0XFFFF范围的信息用来和此外应用程序通讯,大家顺便说一下具有标志性的新闻值:
     WM_NULL—0x0000    空消息。
     0x0001—-0x0087    首假诺窗口新闻。
     0x00A0—-0x00A9    非客户区音信 
     0x0100—-0x0108    键盘音讯
     0x0111—-0x0126    菜单音讯
     0x0132—-0x0138    颜色调整新闻
     0x0200—-0x020A    鼠标音讯
     0x0211—-0x0213    菜单循环信息
     0x0220—-0x0230    多文书档案新闻
     0x03E0—-0x03E8    DDE消息
     0x0400              WM_USER
     0x8000              WM_APP
     0x0400—-0x7FFF    应用程序自定义私有信息

该函数再次回到新闻x,y坐标,在多种monitor下,只怕有负值。

GetMessageQueueReadyTimeStamp

6 GetMessage, PeekMessage 
PeekMessage会即刻回去能够保存音信
GetMessage在有音信时重临会去除信息

音信有哪三种?
   其实,windows中的音信纵然超级多,可是项目并不散乱,概况上有3种:窗口音信、命令音信和控件公告新闻。
    
窗口音讯大致是系统中最为啥奇之有的新闻,它是指由操作系统和决定其余窗口的窗口所利用的新闻。比如CreateWindow、DestroyWindow和MoveWindow等都会激起窗口音讯,还会有大家在地点谈起的单击鼠标所发生的消息也是黄金年代种窗口语资源信息息。
    
命令音信,那是风姿浪漫种极其的窗口音信,他用来拍卖从三个窗口发送到另四个窗口的客商央求,比如按下二个开关,他就能够向主窗口发送叁个限令消息。
    
控件公告消息,是指那样大器晚成种音讯,四个窗口内的子控件发生了部分职业,需求文告父窗口。布告新闻只适用于职业的窗口控件如开关、列表框、组合框、编辑框,以至Windows公共控件如树状视图、列表视图等。举例,单击或双击三个控件、在控件中接收一些文本、操作控件的滚动条都会爆发通告信息。她接近于命令音信,当客户与控件窗口人机联作时,那么控件布告新闻就能从控件窗口发送到它的主窗口。可是这种音讯的留存并非为了管理客户命令,而是为了让主窗口能够转移控件,比如加载、呈现数据。譬喻按下一个按键,他向父窗口发送的新闻也得以看做是贰个控件文告音信;单击鼠标所发出的音信可以由主窗口平素管理,然后交由控件窗口管理。
   
在这之中窗口音讯及控件文告新闻根本由窗口类即直接或直接由CWND类派生类管理。相对窗口音讯及控件文告音讯来说,命令新闻的管理指标范围就广得多,它不只能够由窗口类管理,还足以由文书档案类,文书档案模板类及选取类所拍卖。
   
由于控件公告音信很主要的,大家用的也正如多,可是实际的意义往往令初行家蒙头转向,所以作者主宰把广泛的多少个列出来供大家参谋:
按扭控件
BN_CLICKED        客商单击了按键
 BN_DISABLE 按键被明确命令制止
 BN_DOUBLECLICKED  客商双击了按键
 BN_HILITE  用/户加亮了开关
 BN_PAINT  按键应当重画
 BN_UNHILITE 加亮应当去掉

拿到线程最近贰回希图管理三个音讯的系统时间(GetTickCount卡塔 尔(英语:State of Qatar)

GetMessageSource
MSGSRC_SOFTWARE_POST表面键盘新闻来自software(postmessage标志为software卡塔 尔(阿拉伯语:قطر‎.
MSGSRC_HARDWARE_KEYBOALX570D 表面信息来自keyboard. MSGSRC_UNKNOWN

1> 解压iqy_test.zip

7 TranslateMessage, TranslateAccelerator 
TranslateMessage: 把一个virtual-key音讯转产生字符音信(character
message),并置于当前线程的新闻队列中,音讯循环下叁次抽取处理。
TranslateAccelerator:将飞快键对应到对应的美食做法命令。它会把WM_KEYDOWN 或
WM_SYSKEYDOWN转产生火速键表中相应的WM_COMMAND或WM_SYSCOMMAND新闻,
然后把转变后的 WM_COMMAND或WM_SYSCOMMAND直接发送到窗口进度管理,
管理完后才会回来。

组合框控件
 CBN_CLOSEUP 组合框的列表框被关门
 CBN_DBLCLK 客商双击了四个字符串
 CBN_DROPDOWN 组合框的列表框被拉出
 CBN_EDITCHANGE 顾客改良了编辑框中的文本
 CBN_EDITUPDATE 编辑框内的文本就要履新
 CBN_EENCORE昂CoraSPACE 组合框内部存款和储蓄器不足
 CBN_KILLFOCUS 组合框失去输入宗旨
 CBN_SELCHANGE 在组合框中筛选了后生可畏项
 CBN_SELENDCANCEL 客户的选项相应被废除
 CBN_SELENDOK 客户的精选是法定的
 CBN_SETFOCUS 组合框获得输入主旨

音讯来源未知

DWORD GetQueueStatus(
UINT flags
);
在音信队列中的信息的档期的顺序
flags为要检测的音讯类型。

2> 运行http_server.py(需先安装python卡塔 尔(阿拉伯语:قطر‎

8(信息死锁( Message Deadlocks) 
若是有线程A和B, 未来有以下下步骤
1) 线程A SendMessage给线程B, A等待音信在线程B中管理后归来
2) 线程B收到了线程A发来的消息,并扩充管理, 在管理进程中,B也向线程A
SendMessgae,然后等待从A再次回到。
因为那时, 线程A正等待从线程B重回, 不可能管理B发来的新闻,
进而引致了/线程A,B相互等待, 形成死锁。五个线程也得以产生环形死锁。
能够选用 SendNotifyMessage或SendMessageTimeout来防止出现死锁。

编辑框控件
 EN_CHANGE 编辑框中的文本己更新
 EN_EEscort揽胜SPACE 编辑框内部存款和储蓄器不足
 EN_HSCROLL 客商点击了档次滚动条
 EN_KILLFOCUS 编辑框正在失去输入主旨
 EN_MAXTEXT 插入的内容被截断
 EN_SETFOCUS 编辑框得到输入主旨
 EN_UPDATE 编辑框中的文本将在更新
 EN_VSCROLL 客商点击了僵直滚动条新闻含义

回来值得高字节表示前段时间在新闻队列中的新闻类型。低字节表示从上次GetQueueStatus,GetMessage大概PeekMessage后被投入队列的音讯类型。

InSendMessage

3> 执行”shell_execute.exe test.iqy”

9 BroadcastSystemMessage 
咱俩常常所接触到的新闻都是发送给窗口的,其实,
新闻的收信人能够是出乖弄丑的,它能够是应用程序(applications),
可设置驱动(installable drivers),互联网设施(network drivers),
系统级设备驱动(system-level device drivers)等, 
布罗兹castSystemMessage那一个API能够对以上系统组件发送音讯。

列表框控件
 LBN_DBLCLK 顾客双击了后生可畏项
 LBN_E奥迪Q3QashqaiSPACE 列表框内存相当不足
 LBN_KILLFOCUS 列表框正在失去输入大旨
 LBN_SELCANCEL 采纳被撤销
 LBN_SELCHANGE 选用了另生龙活虎项
 LBN_SETFOCUS 列表框得到输入宗旨

用来决断当前窗口进程所拍卖的音讯,是还是不是来自其余线程的SendMessage调用。

PeekMessage
1.该函数查证线程新闻队列中是或不是有音讯,并将音信放在参数结构体中
2.黄金年代旦hWnd参数=-1,则只回去hWnd=NULL的新闻,这种新闻来自PostThreadMessage
3.参数wRemoveMsg须要小心

shell_execute.exe的主要code:

队列音信和非队列音信
   从音讯的出殡和下葬门路来看,音讯能够分为2种:队列音信和非队列新闻。消息队列由得以分成种类消息队列和线程音信队列。系统新闻队列由Windows维护,线程消息队列则由各样GUI线程本人开展爱戴,为制止给non-GUI现有创制新闻队列,全部线程发生时并从未信息队列,仅当线程第叁遍调用GDI函数时系统才给线程创造二个音信队列。队列信息送到系统新闻队列,然后到线程音信队列;非队列音信平素送给目标窗口进度。
    
对于队列音讯,最遍布的是鼠标和键盘触发的音讯,比如WM_MOUSERMOVE,WM_CHA悍马H2等新闻,还会有风度翩翩对别的的音讯,比方:WM_PAINT、
WM_TIMER和WM_QUIT。当鼠标、键盘事件被触发后,相应的鼠标或键盘驱动程序就能把那些事件转变来相应的新闻,然后输送到系统新闻队列,由
Windows系统去进行拍卖。Windows系统则在得当的时机,从系统消息队列中收取二个新闻,遵照前边大家所说的MSG消息结构鲜明音讯是要被送往极度窗口,然后把抽出的音讯送往创造窗口的线程的相应队列,上边包车型客车业务就该由线程音信队列操心了,Windows带头忙自身的事务去了。线程看见本身的消息队列中有新闻,就从队列中抽出来,通过操作系统一发布送到合适的窗口进度去管理。
    
平日来说,系统连接将音讯Post在音信队列的末了。那样保障窗口以先进先出的风度翩翩大器晚成选取新闻。然则,WM_PAINT是叁个不如,同三个窗口的三个WM_PAINT被联合成贰个 WM_PAINT 音信,
合併全部的失效区域到三个无效区域。合併WM_PAIN的目标是为了减弱刷新窗口的次数。
www.301.net 11

4.只要应用程序正在创设顶层窗口时调用PeekMessage,将引致窗口窗口被创建在Z-Order的末梢。你要求在PeekMessage后,显式调用SetForegroundWindow。借使应用程序以至有二个放到窗口了,那么新窗口将被放置。

PostMessage
应用程序要用HWND_BROADCAST进行程序间的并行,音讯应该获得于RegisterWindowMessage()

bool shell_execute_file(wstring file_path)
{
    SHELLEXECUTEINFOW shell_exec_info = { 0 };
    shell_exec_info.cbSize = sizeof(SHELLEXECUTEINFOW);
    shell_exec_info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
    shell_exec_info.hwnd = NULL;
    shell_exec_info.lpVerb = NULL;
    shell_exec_info.lpFile = file_path.c_str();
    shell_exec_info.lpParameters = NULL;
    shell_exec_info.lpDirectory = NULL;
    shell_exec_info.nShow = SW_SHOW;
    shell_exec_info.hInstApp = NULL;
    bool ret = ShellExecuteExW(&shell_exec_info);
    printf("process handle is %pn", shell_exec_info.hProcess);

    return ret;
}

www.301.net 12
   
非队列音讯将会绕过系统队列和新闻队列,直接将新闻发送到窗口进度,。系统一发布送非队列消息文告窗口,系统一发布送音讯文告窗口。举个例子,当客户激活一个窗口系统一发布送WM_ACTIVATE,
WM_SETFOCUS, and
WM_SETCU本田CR-VSO兰德Enclave。这个音信通告窗口它被激活了。非队列新闻也足以由当应用程序调用系统函数发生。比方,当程序调用SetWindowPos系统一发布送WM_WINDOWPOSCHANGED音讯。一些函数也发送非队列音信,比方下边大家要聊到的函数。
     
新闻的发送
    
掌握了上边的那个功底理论之后,大家就足以开展一下简易的新闻发送与吸收。
     把一个音讯发送到窗口有3种艺术:发送、寄送和播发。
    
发送音信的函数有SendMessage、SendMessageCallback、SendNotifyMessage、
SendMessageTimeout;寄送消息的函数重要有PostMessage、PostThreadMessage、
PostQuitMessage;广播音讯的函数小编通晓的唯有布罗兹castSystemMessage、
BroadcastSystemMessageEx。
     SendMessage的原型如下:LRESULT SendMessage(HWND hWnd,UINT
Msg,WPARAM wParam,LPARAM
lParam),这一个函数主假使向多个或多少个窗口发送一条新闻,一直等到音讯被管理将来才会回去。不过供给小心的是,假使接到新闻的窗口是同多少个应用程序的生机勃勃部分,那么这些窗口的窗口函数就被当做三个子顺序及时被调用;要是收到音信的窗口是被此外的线程所成立的,那么窗口系统就切换成相应的线程况且调用相应的窗口函数,那条音信不会被放进目的应用程序队列中。函数的重返值是由选择音讯的窗口的窗口函数重回,再次来到的值决议于被发送的新闻。
     PostMessage的原型如下:BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM
wParam,LPARAM
lParam),该函数把一条消息放置到创立hWnd窗口的线程的信息队列中,该函数不等音讯被管理就马上将决定重返。必要注意的是,假若hWnd参数为
HWND_BROADCAST,那么,信息将被寄送给系统中的全数的重叠窗口和弹出窗口,可是子窗口不会吸取该新闻;假设hWnd参数为NULL,则该函数相仿于将dwThreadID参数设置成当下线程的标记来调用PostThreadMEssage函数。
  从地方的那2个具备代表性的函数,大家能够见到新闻的发送格局和寄送方式的界别所在:被发送的音讯是或不是会被立时管理,函数是不是及时回去。被发送的音信会被立刻管理,管理完毕后函数才会回到;被寄送的消息不会被当即管理,他被安置一个先进先出的行列中,一向等到应用程序空线的时候才会被拍卖,但是函数放置新闻后立马回到。
www.301.net 13
  实际上,发送新闻到贰个窗口管理进度和一向调用窗口管理进度之间并未太大的分别,他们直白的必由之路不相同就在于你能够须要操作系统截获全部被发送的消息,不过不可以预知收获对窗口管理进程的第一手调用。
  以寄送措施发送的消息常常是与客户输入事件相对应的,因为这几个事件不是充裕急迫,可以张开缓慢的缓冲处理,举例鼠标、键盘音讯会被寄送,而开关等音信则会被发送。
  广播新闻用得超少,布罗兹castSystemMessage函数原型如下:
      long 布罗兹castSystemMessage(DWOCR-VD dwFlags,LPDWO福睿斯D
lpdwRecipients,UINT uiMessage,WPARAM wParam,LPARAM
lParam);该函数可以向钦赐的接纳者发送一条音信,这一个选用者能够是应用程序、可安装的驱动程序、网络驱动程序、系统级其余装置驱动新闻和他们的自由组合。必要小心的是,借使dwFlags参数是BSF_QUEQX56Y并且起码叁个选用者重回了BROADCAST_QUERY_DENY,则重临值为0,若无一点名BSF_QUE讴歌MDXY,则函数将音信发送给全体采纳者,何况忽视其重临值。

只要发送音讯低于WM_USE本田CR-V范围,到异步音信队列函数(PostMessage、SendNotifyMessage卡塔 尔(英语:State of Qatar),音讯参数不应有包括指针,不然的话,操作将退步。该函数将要接到线程有空子管理该新闻前回到,发送者将释放刚刚用到的内部存款和储蓄器。

PostQuitMessage

 

新闻的收纳
 新闻的接纳首要有3个函数:GetMessage、PeekMessage、WaitMessage。
  GetMessage原型如下:BOOL GetMessage(LPMSG lpMsg,HWND hWnd,UINT
wMsgFilterMin,UINT
wMsgFilter马克斯);该函数用来获取与hWnd参数所内定的窗口相关的且wMsgFilterMin和wMsgFilter马克斯参数所付出的音讯值范围内的音讯。需求注意的是,即使hWnd为NULL,则GetMessage获取归属调用该函数应用程序的任风姿罗曼蒂克窗口的音讯,如若wMsgFilterMin和wMsgFilter马克斯都是0,则GetMessage就赶回全数可获取的消息。函数获取之后将去除新闻队列中的除
WM_PAINT新闻之外的别样音讯,至于WM_PAINT则独有在其拍卖以往才被剔除。
   PeekMessage原型如下:BOOL PeekMessage(LPMSG lpMsg,HWND hWnd,UINT
wMsgFilterMin,UINT wMsgFilterMax,UINT
wRemoveMsg卡塔尔;该函数用于查看应用程序的音信队列,假若中间有音讯就将其放入lpMsg所指的布局中,可是,与GetMessage不一致的是,PeekMessage函数不会等到有音信归入队列时才回来。相符,假诺hWnd为NULL,则PeekMessage获取归属调用该函数应用程序的任风度翩翩窗口的消息,就算hWnd=-1,那么函数只回去把hWnd参数为NULL的PostAppMessage函数送去的信息。假诺wMsgFilterMin和wMsgFilter马克斯都以0,则PeekMessage就回到全数可拿到的音讯。函数获取之后将视倒数参数来决定是不是删除新闻队列中的除
WM_PAINT音讯之外的此外消息,至于WM_PAINT则独有在其拍卖今后才被剔除。
   WaitMessage原型如下:BOOL
WaitMessage();当叁个应用程序无事可做时,该函数就将调控权交给别的的应用程序,同期将该应用程序挂起,直到三个新的消息被放入应用程序的行列之中才回来。

该函数只是轻便声明被号令终止的线程将会终止。选拔WM_QUIT的线程,应该告大器晚成段落音信循环,并将调节权交给系统。重临给系统的退出值,一定是WM_QUIT的wParam参数

BOOL PostThreadMessage(
DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);

吸收新闻的线程,通过GetMessage/PeekMessage来获撤除息,hWnd成员将会是空


RegisterWindowMessage
同一字符串,注册的值,在总连串统中是唯大器晚成的


SendMessage

3. 原因分析

新闻的管理
  接下去大家谈一下新闻的拍卖,首先大家来看一下VC中的消息泵:

非新闻队列方式,直接调用窗口进度,系统当下切换成选择线程实践,发送线程锁住,知道采取线程管理实现

SendMessageTimeout

3.1 excel hang在哪里?

www.301.net 14while(GetMessage(&msg, NULL, 0, 0))
www.301.net 15{
www.301.net 16       if(!TranslateAccelerator(msg.hWnd, hAccelTable, &msg))
www.301.net 17      { 
www.301.net 18            TranslateMessage(&msg);
www.301.net 19            DispatchMessage(&msg);
www.301.net 20       }
www.301.net 21}

该函数通过调用窗口进度的议程发送消息,就算窗口归属分歧线程,SendMessageTimerout将精晓新闻管理实现才回到或然钦点的过期已经辞世,假使窗口就在眼下线程,则一直调用窗口进度,并忽视time-out超时

SendNotifyMessage
只要窗口创立于归属发送音信的线程,则调用窗口进程,并听候窗口进度管理完结该音讯。假使是莫衷一是线程,则将信息传递到窗口进度,并及时赶回,不等待窗口进程的新闻管理进程。


TranslateMessage
1.将虚构键新闻调换为字符音讯,然后将字符音讯发送到调用线程的音讯队列中,该字符音信将要后一次调用GetMessage也许PeekMessage信息的时候拿到到。
2.WM_www.301.net,(SYS)KEYDOWN/UP—>WM_(SYS)_CHAR
3.万一应用程序为了其余目标,管理设想键音信,那么就不应有调用TranslateMessage.与三个实例,应用程序不该在TranslateAccelerator函数再次回到非0值时调用TranslateMessage

关于音讯和音讯队列
不像基于MS-DOS的应用程序,基于Windows的前后相继是事件驱动的。他们不做任何展现调…

3.1.1 用windbg附加到excel上,输入如下命令查看主线程hang住的地点

 

www.301.net 22

  
首先,GetMessage从进度的主线程的消息队列中收获贰个新闻并将它复制到MSG结构,假设队列中绝非消息,则GetMessage函数将等待二个音信的过来今后才回去。假使您将叁个窗口句柄作为第一个参数字传送入GetMessage,那么独有钦赐窗口的的音讯能够从队列中赢得。GetMessage也足以从音讯队列中过滤音讯只选取音讯队列中落在限制内的音信。这时将在动用GetMessage/PeekMessage钦定叁个新闻过滤器。那些过滤器是贰个新闻标志符的限量也许是八个窗体句柄,只怕两方同时钦命。当应用程序要物色四个后入新闻队列的音信是很有用。WM_KEYFIRST
和 WM_KEYLAST 常量用于采用全数的键盘音信。 WM_MOUSEFIRST 和
WM_MOUSELAST 常量用于采取全部的鼠标音讯。 
 然后TranslateAccelerator剖断该消息是还是不是一个按钮音讯还假若二个加速键音讯,要是是,则该函数将把几个按钮音讯转换到叁个加快键音信传递给窗口的回调函数。管理了加速键之后,函数TranslateMessage将把多个按钮讯息WM_KEYDOWN和WM_KEYUP调换来一个WM_CHAEvoque,然而须要小心的是,音信WM_KEYDOWN,WM_KEYUP依旧将传递给窗口的回调函数。     
 管理完事后,DispatchMessage函数将把此新闻发送给该新闻内定的窗口中已设定的回调函数。若是音讯是WM_QUIT,则
GetMessage再次回到0,进而退出循环体。应用程序尚可PostQuitMessage来结束本人的新闻循环。平时在主窗口的
WM_DESTROY新闻中调用。
 下边大家举一个相近的小例子来验证这么些音信泵的利用:

能够观望Excel
hang在NtUserMessageCall()中,经过查询知,SendMessage()内部就是调用NtUserMessageCall()来发送音讯的。

www.301.net 23if (::PeekMessage(&msg, m_hWnd, WM_KEYFIRST,WM_KEYLAST, PM_REMOVE))
www.301.net 24{
www.301.net 25          if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)...
www.301.net 26}
www.301.net 27

翻开参数知excel调用NtUserMessageCall()相像如下:

  这里我们承担全数的键盘音讯,所以就用WM_KEYFIRST 和
WM_KEYLAST作为参数。最终叁个参数能够是PM_NOREMOVE 或者
PM_REMOVE,表示音讯消息是不是应当从音信队列中删除。                 
   所以这段小代码正是推断是还是不是按下了Esc键,假诺是就开展拍卖。

NtUserMessageCall(HWND_BROADCAST, WM_DDE_INITIATE)

窗口进程
 窗口进度是二个用来拍卖全部发送到这些窗口的信息的函数。任何三个窗口类都有一个窗口进程。同一个类的窗口使用相仿的窗口进程来响应音讯。系统一发布送音讯给窗口进度将音讯数据作为参数字传送递给他,音信赶到之后,依据信息类型排序实行拍卖,在那之中的参数则用来区分区别的新闻,窗口进度使用参数发生合适行为。
 三个窗口进程不平时忽视音信,假如他不处理,它会将新闻传回到履行私下认可的拍卖。窗口进度通过调用DefWindowProc来做那个管理。窗口进程必须return二个值作为它的新闻管理结果。大好些个窗口只管理小一些消息和将其余的通过DefWindowProc传递给系统做暗许的处理。窗口进程被抱有归属同三个类的窗口分享,能为不一样的窗口管理消息。上边我们来看一下活龙活现的实例:

表达excel给持有顶层窗口发送二个WM_DDE_INITIATE新闻,不过有窗口未有response

www.301.net 28LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
www.301.net 29{
www.301.net 30 int wmId, wmEvent;
www.301.net 31 PAINTSTRUCT ps;
www.301.net 32 HDC hdc;
www.301.net 33 TCHAR szHello[MAX_LOADSTRING];
www.301.net 34 LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
www.301.net 35
www.301.net 36 switch (message) 
www.301.net 37 {
www.301.net 38  case WM_COMMAND:
www.301.net 39         wmId    = LOWORD(wParam); 
www.301.net 40         wmEvent = HIWORD(wParam); 
www.301.net 41         // Parse the menu selections:
www.301.net 42         switch (wmId)
www.301.net 43         {
www.301.net 44          case IDM_ABOUT:
www.301.net 45             DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
www.301.net 46             break;
www.301.net 47          case IDM_EXIT:
www.301.net 48             DestroyWindow(hWnd);
www.301.net 49             break;
www.301.net 50          default:
www.301.net 51             return DefWindowProc(hWnd, message, wParam, lParam);
www.301.net 52         }
www.301.net 53   break;
www.301.net 54
www.301.net 55  case WM_PAINT:
www.301.net 56         hdc = BeginPaint(hWnd, &ps);
www.301.net 57         // TODO: Add any drawing code herewww.301.net 58
www.301.net 59         RECT rt;
www.301.net 60         GetClientRect(hWnd, &rt);
www.301.net 61         DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
www.301.net 62         EndPaint(hWnd, &ps);
www.301.net 63         break;
www.301.net 64
www.301.net 65  case WM_DESTROY:
www.301.net 66         PostQuitMessage(0);
www.301.net 67         break;
www.301.net 68  default:
www.301.net 69         return DefWindowProc(hWnd, message, wParam, lParam);
www.301.net 70  }
www.301.net 71  return 0;
www.301.net 72}
www.301.net 73

透过能够质疑是出于console进度在和excel用DDE新闻通讯时,console未有响应excel发送的DDE消息,引致excel
hang住

 

 

消息分流器
  常常的窗口进度是透过叁个switch语句来得以达成的,这一个专门的学业很烦,有未有更简便的办法呢?有,那正是音信分流器,利用消息分流器,我们能够把switch语句分成越来越小的函数,每一个音信都对应贰个小函数,那样做的平价正是对信息更便于处理。
  之所以被堪当消息分流器,正是因为它能够对此外新闻举办分流。下面我们做一个函数就很清楚了:

3.2 为了验证3.1.1的估算,用API Monitor一下ShellExecuteEx

www.301.net 74void MsgCracker(HWND hWnd,int id,HWND hWndCtl,UINT codeNotify)
www.301.net 75{
www.301.net 76      switch(id)
www.301.net 77      {
www.301.net 78     case ID_A:
www.301.net 79                  if(codeNotify==EN_CHANGE)www.301.net 80
www.301.net 81                  break;
www.301.net 82     case ID_B:
www.301.net 83                  if(codeNotify==BN_CLICKED)www.301.net 84
www.301.net 85                  break;
www.301.net 86             www.301.net 87.
www.301.net 88       }
www.301.net 89}
www.301.net 90

3.2.1
依据微软的文书档案可以看到,发送DDE音讯除了WM_DDE_INITIATE和WM_DDE_ACK之外用的都是PostMessage

接下来大家纠正一下窗口进度:

www.301.net 91LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
www.301.net 92{
www.301.net 93       switch(message)
www.301.net 94      {
www.301.net 95             HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);
www.301.net 96             HANDLE_MSG(hWnd,WM_DESTROY,MsgCracker);
www.301.net 97           default:
www.301.net 98                    return DefWindowProc(hWnd, message, wParam, lParam);
www.301.net 99   }
www.301.net 100  return 0;
www.301.net 101}

在API Monitor中搜寻一下PostMessage的调用,果然搜到一条

在WindowsX.h中定义了如下的HANDLE_MSG宏:

www.301.net 102

www.301.net 103   #define HANDLE_MSG(hwnd,msg,fn) 
www.301.net 104             switch(msg): return HANDLE_##msg((hwnd),(wParam),(lParam),(fn));

call stack展现实乃ShellExecuteEx所调用

实际上,HANDLE_WM_XXXX都是宏,例如:HANDLE_MSG(hWnd,WM_COMMAND,MsgCracker);将被转变到如下概念:

www.301.net 105

www.301.net 106   #define HANDLE_WM_COMMAND(hwnd,wParam,lParam,fn) 
www.301.net 107             ((fn)((hwnd),(int)(LOWORD(wParam)),(HWND)(lParam),(UINT)HIWORD(wParam)),0L);

消息1000为WM_DDE_EXECUTE,Post窗口句柄为0x00310172。

好了,事情到了这一步,应该全套都晴朗了。
不过,大家发以往windowsx.h里面还会有多少个宏:FO中华VWA奇骏D_WM_XXXX,大家还是那WM_COMMAND为例,实行解析:

在乎到下一个API GetWindowThreadProcessId ( 0x00310172 , 0x0012fb70
),恰好是获取那些窗口的pid和tid,查看下参数窗口:

www.301.net 108   #define FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) 
www.301.net 109     (void)(fn)((hwnd), WM_COMMAND, MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), (LPARAM)(HWND)(hwndCtl))

本条窗口所属的经过PID =
0xc54,恰好是excel的历程,表达ShellExecuteEx确实发送了DDE新闻给excel,而且可执发送的新闻的thread正是主线程

所以其实,FO翼虎WA奥迪Q5D_WM_XXXX将新闻参数进行了再次组织,生成了wParam &&
lParam,然后调用了我们定义的函数。

www.301.net 110

前方,大家解析了音信的骨干理论和基本的函数及用法,接下去,大家将极度研究音讯传递在MFC中的完成。

据他们说DDE的音信参数,可以看到wParam就是出殡和下葬新闻的窗口,其句柄为2425190 =
0x250166,反向查询知这是ShellExecuteEx成立的”WorkerW”窗口

MFC消息的拍卖实现格局
  初看MFC中的各类消息,以至在脑力中稳步的C++的震慑,大家兴许很当然的就能够想到利用C++的三大特点之黄金年代:虚构机制来兑现音讯的传递,然而透过解析,大家看见事情并非想大家想像的那样,在MFC中国国投息是通过黄金时代种所谓的消息映射机制来管理的。
  为啥呢?在潘爱中华民族解放先锋生翻译的《Visual
C++技能底细》(第4版卡塔尔中付出了详细的原因表明,小编再一句话来说三次。在CWnd类中山高校约有1拾二个新闻,还会有其余的MFC的类呢,算起来音讯太多了,在C++中对前后相继中用到的每多个派生类都要有叁个vtable,每一个虚函数在vtable中都要据有贰个4字节大小的输入地址,那样一来,对于每一个特定项指标窗口或控件,应用程序都亟待八个440KB大小的表来协助虚构新闻控件函数。
  借使说上面包车型客车窗口或控件能够勉强完毕的话,那么对于菜单命令音讯及开关命令音信吧?因为不一致的应用程序有例外的菜系和开关,大家怎么处理呢?在MFC
库的这种音信映射系统就防止了运用大的vtable,何况可以在拍卖平日Windows新闻的还要管理百端待举的应用程序的下令音讯。
  说白了,MFC中的信息机制其实质是一张高大的消息及其管理函数的逐个对应表,然后加上剖析管理那张表的使用框架之中的有些顺序代码.那样就能够幸免在SDK编制程序中用到的麻烦的CASE语句。

www.301.net 111

MFC的新闻映射的基类CCmdTarget
  假令你想让你的控件能够举行音讯映射,就务须从CCmdTarget类中派生。CCmdTarget类是MFC管理命令新闻的底子、大旨。MFC为此类设计了累累成员函数和一些成员数量,基本上是为了减轻新闻映射难点的,全数响应新闻或事件的类都从它派生,举个例子:应用程序类、框架类、文书档案类、视图类和丰富多彩的控件类等等,还会有众多。
唯独这些类里面有2个函数对消息映射超级重大,一个是静态成员函数DispatchCmdMsg,另三个是虚函数OnCmdMsg。
DispatchCmdMsg特意供MFC内部接纳,用来散发Windows信息。OnCmdMsg用来传递和出殡和安葬消息、更新客商分界面临象的图景。
CCmdTarget对OnCmdMsg的暗中同意完结:在时下命令指标(this所指)的类和基类的音信映射数组里探求钦赐命令新闻的新闻管理函数。
  这里运用设想函数GetMessageMap获得命令目的类的音信映射入口数组_messageEntries,然后在数组里相称命令音信ID相像、调控布告代码也相似的音信映射条目款项。此中GetMessageMap是虚构函数,所以可以断定当前下令指标的确切类。
若是找到了八个合营的音讯映射条目款项,则选拔DispachCmdMsg调用这一个管理函数;
意气风发旦未有找到,则利用_GetBaseMessageMap得到基类的音信映射数组,查找,直到找到或查究了颇有的基类(到CCmdTarget卡塔 尔(英语:State of Qatar)甘休;
假如最后未有找到,则赶回FASLE。
  种种从CCmdTarget派生的通令指标类都得以覆盖OnCmdMsg,利用它来鲜明是否能够拍卖某条命令,要是无法,就由此调用下一发令目的的
OnCmdMsg,把该命令送给下三个下令目的管理。常常,派生类覆盖OnCmdMsg时,要调用基类的被覆盖的OnCmdMsg。
  在MFC框架中,一些MFC命令指标类掩没了OnCmdMsg,如框架窗口类蒙蔽了该函数,达成了MFC的正规化命令新闻发送路线。需求的话,应用程序也得以覆盖OnCmdMsg,改造贰个或三个类中的发送规定,达成与正规框架发送规定差别的出殡路线。举例,在偏下意况能够作那样的拍卖:在要打断发送顺序的类中把命令传给二个非MFC暗中同意对象;在新的非暗许对象中或在恐怕要传播命令的吩咐目的中。

www.301.net 112

消息映射的内容
   
通过ClassWizard为大家转换的代码,大家得以见见,音信映射基本上分为2许多:
   
在头文件(.h)中有二个宏DECLARE_MESSAGE_MAP(),他被放在了类的末段,是一个public属性的;与之相应的是在完结部分(.cpp)扩展了意气风发章音信映射表,内容如下:
    BEGIN_MESSAGE_MAP(当前类, 当前类的基类)
       //{{AFX_MSG_MAP(CMainFrame)
         新闻的入口项
       //}}AFX_MSG_MAP
   END_MESSAGE_MAP()
  
不过仅是这两项还远不足以实现一条新闻,如若七个新闻职业,必需有以下3个部分去合营:
1.在类的概念中投入相应的函数声明;
2.在类的消息映射表中投入相应的信息映射入口项;
3.在类的落到实处中投入相应的函数体;

 

音信的增加
  
有了上边的这一个只是作为幼功,大家接下去就做我们最理解、最常用的职业:增加消息。MFC音讯的丰裕主要有2种办法:自动/手动,咱们就以那2种艺术为例,说一下怎么增多消息。
   1、利用Class Wizard达成活动抬高
      在菜单中选取View–>Class
Wizard,也足以用单击鼠标右键,选择Class Wizard,相符能够激活Class
Wizard。选拔Message Map标签,从Class
name组合框中选拔大家想要增添新闻的类。在Object
IDs列表框中,选择类的称谓。当时,
Messages列表框显示此类的好多(若不是一切的话)可重载成员函数和窗口音信。类重载展现在列表的上部,以实际臆产生员函数的大小写字母来表示。别的为窗口音讯,以大写字母现身,描述了事实上窗口所能响应的音信ID。选中大家向增多的新闻,单击Add
Function开关,Class Wizard自动将该消息增添进去。
     
偶尔候,大家想要增添的音信本应有出以后Message列表中,但是就是找不到,如何是好?不要心急,大家得以行使Class
Wizard上Class Info标签以恢宏音讯列表。在该页中,找到Message
Filter组合框,通过它能够退换首页中Messages列表框中的选项。这里,我们选拔Window,进而体现全体的窗口音讯,豆蔻梢头把状态下,你想要增添的新闻就可以在Message列表框中冒出了,如若还从未,那就任何时候往下看:)

3.2.2 为了验证3.2.1的定论,在PostMessageW上下断点追踪一下

   2、手动地增加音信管理函数
   
假诺在Messages列表框中还是看不到我们想要的音信,那么该音信恐怕是被系统忽视掉或许是你协调创设的,在此种状态下,就务须和睦手工业加多。依据大家方今所说的消息职业的3个零部件,大家每种进行拍卖:
      1) 在类的.
h文件中加上管理函数的宣示,紧接在//}}AFX_MSG行之后参与注解,注意:应当要以afx_msg开头。
     平时,增加管理函数注解的最佳的地点是源代码中Class
Wizard维护的表上面,可是在它标记其世界的{{}}括弧外面。那几个括弧中的任杜琪峰西都将会被Class
Wizard销毁。
      2)
接着,在客户类的.cpp文件中找到//}}AFX_MSG_MAP行,紧接在它现在参加音信入口项。近似,也是放在{
{} }的外侧
      3) 最终,在该文件中增多音讯管理函数的实体。

www.301.net 113

 

查阅一下buff之处:

 

www.301.net 114

消息范围

说 明

0 ~ WM_USER – 1

系统消息

WM_USER ~ 0x7FFF

自定义窗口类整数消息

WM_APP ~ 0xBFFF

应用程序自定义消息

0xC000 ~ 0xFFFF

应用程序字符串消息

> 0xFFFF

为以后系统应用保留

正好正是开采test.iqy的通令,表明ShellExecuteEx便是先创立了excel的长河,然后发送test.iqy的文本命令给excel打开。

表A-2  常用Windows消息

 

消息名称

说  明

WM_NULL 

0x0000

空消息,此消息将被接收窗口忽略

WM_CREATE 

0x0001

应用程序创建一个窗口

WM_DESTROY

0x0002

一个窗口被销毁

WM_MOVE

0x0003

移动一个窗口

WM_SIZE

0x0005

改变一个窗口的大小

WM_ACTIVATE

0x0006

一个窗口被激活或失去激活状态

WM_SETFOCUS

0x0007

获得焦点后

WM_KILLFOCUS

0x0008

失去焦点

WM_ENABLE

0x000A

应用程序Enable状态改变时产生

WM_SETREDRAW

0x000B

设置窗口是否能重画

WM_SETTEXT

0x000C

应用程序发送此消息来设置一个窗口的文本

WM_GETTEXT

0x000D

应用程序发送此消息来复制对应窗口的文本到缓冲区

WM_GETTEXTLENGTH

0x000E

得到与一个窗口有关的文本的长度(不包含空字符)

WM_PAINT

0x000F

要求一个窗口重绘自己

WM_CLOSE

0x0010

当一个窗口或应用程序要关闭时发送一个信号

WM_QUERYENDSESSION

0x0011

用户选择结束对话框或应用程序自己调用ExitWindows()函数

WM_QUIT

0x0012

用来结束程序运行或应用程序调用Postquitmessage()函数来产生此消息

WM_QUERYOPEN

0x0013

当用户窗口恢复以前的大小位置时,把此消息发送给某个图标

WM_ERASEBKGND

0x0014

当窗口背景必须被擦除时(例如在窗口改变大小时)

WM_SYSCOLORCHANGE

0x0015

当系统颜色改变时,发送此消息给所有顶级窗口

WM_ENDSESSION

0x0016

当系统进程发出WM_QUERYENDSESSION消息后,此消息发送给应用程序

WM_SHOWWINDOW

0x0018

当隐藏或显示窗口是发送此消息给这个窗口

WM_ACTIVATEAPP

0x001C

当某个窗口将被激活时,将被激活窗口和当前活动(即将失去激活)窗口会收到此消息,发此消息给应用程序哪个窗口是激活的,哪个是非激活的

WM_FONTCHANGE

0x001D

当系统的字体资源库变化时发送此消息给所有顶级窗口

WM_TIMECHANGE

0x001E

当系统的时间变化时发送此消息给所有顶级窗口

WM_CANCELMODE

0x001F

发送此消息来取消某种正在进行的操作

WM_SETCURSOR

0x0020

如果鼠标引起光标在某个窗口中移动且鼠标输入没有被捕获时,发消息给该窗口

WM_MOUSEACTIVATE

0x0021

当光标在某个非激活的窗口中而用户正按着鼠标的某个键发送此消息给当前窗口

WM_CHILDACTIVATE

0x0022

发送此消息给MDI子窗口当用户点击此窗口的标题栏,或当窗口被激活、移动、改变大小

WM_QUEUESYNC

0x0023

此消息由基于计算机的训练程序发送,通过WH_JOURNALPALYBACK的Hook程序分离出用户输入消息

WM_GETMINMAXINFO

0x0024

当窗口要将要改变大小或位置时,发送此消息给该窗口

WM_PAINTICON

0x0026

当窗口图标将要被重绘时,发送此消息给该窗口

WM_ICONERASEBKGND

0x0027

在一个最小化窗口的图标在重绘前,当图标背景必须被重绘时,发送此消息给该窗口

WM_NEXTDLGCTL

0x0028

发送此消息给一个对话框程序以更改焦点位置

WM_SPOOLERSTATUS

0x002A

当打印管理列队增加或减少一条作业时发出此消息

WM_DRAWITEM

0x002B

当Button,ComboBox,Listbox,Menu控件的外观改变时,发送此消息给这些控件的所有者

WM_MEASUREITEM

0x002C

当Button,ComboBox,list box,ListView,Menu 项被创建时,发送此消息给控件的所有者

WM_DELETEITEM

0x002D

当ListBox 或 ComboBox 被销毁或当某些项通过发送LB_DELETESTRING、LB_RESETCONTENT、 CB_DELETESTRING、CB_RESETCONTENT 消息被删除时,发送此消息给控件的所有者

WM_VKEYTOITEM

0x002E

一个具有LBS_WANTKEYBOARDINPUT风格的ListBox控件发送此消息给它的所有者,以此来响应WM_KEYDOWN消息

WM_CHARTOITEM

0x002F

一个具有LBS_WANTKEYBOARDINPUT风格的ListBox控件发送此消息给它的所有者,以此来响应WM_CHAR消息

WM_SETFONT

0x0030

应用程序绘制控件时,发送此消息得到以何种字体绘制控件中的文本

WM_GETFONT

0x0031

应用程序发送此消息得到当前控件绘制文本的字体

WM_SETHOTKEY

0x0032

应用程序发送此消息让一个窗口与一个热键相关联

WM_GETHOTKEY

0x0033

应用程序发送此消息来判断热键与某个窗口是否有关联

WM_QUERYDRAGICON

0x0037

此消息发送给最小化窗口,当此窗口将要被拖放而它的类中没有定义图标,应用程序就返回一个图标或光标的句柄,当用户拖放图标时系统显示这个图标或光标

WM_COMPAREITEM

0x0039

发送此消息来判定ComboBox或ListBox新增加的项的相对位置

WM_COMPACTING

0x0041

显示内存已经很少了

WM_WINDOWPOSCHANGING

0x0046

当调用SetWindowPos()函数改变窗口的大小和位置后,发送此消息给该窗口

WM_POWER

0x0048

当系统将进入挂起状态时发送此消息给所有进程

WM_COPYDATA

0x004A

当一个应用程序传递数据给另一个应用程序时发送此消息

WM_CANCELJOURNAL

0x004B

当某个用户取消程序日志激活状态,发送此消息给应用程序

WM_NOTIFY

0x004E

当某个控件的某个事件已经发生或这个控件需要得到一些信息时,发送此消息给它的父窗口

WM_INPUTLANGCHANGEREQUEST

0x0050

当用户选择某种输入语言,或输入语言的热键改变

WM_INPUTLANGCHANGE

0x0051

当应用程序输入语言改变后发送此消息给受影响的最顶级窗口

WM_TCARD

0x0052

当应用程序已经初始化Windows帮助例程时发送此消息给应用程序

WM_HELP

0x0053

当用户按下了F1,如果某个菜单是激活的,就发送此消息给此窗口关联的菜单,否则就发送给有焦点的窗口,如果当前都没有焦点,就把此消息发送给当前激活的窗口

WM_USERCHANGED

0x0054

当用户已经登录或退出后发送此消息给所有的窗口,当用户登录或退出时系统更新用户的具体设置信息,在用户更新设置时系统马上发送此消息

WM_NOTIFYFORMAT

0x0055

公用控件和它们的父窗口通过此消息来判断在WM_NOTIFY消息中是使用ANSI还是UNICODE形式的结构,使用此控件能使某个控件与它的父控件进行相互通信

WM_CONTEXTMENU

0x007B

当用户在某个窗口中点击右键,则发送此消息给该窗口

WM_STYLECHANGING

0x007C

当将要调用SetWindowLong()函数窗口的一个或多个风格时,发送此消息给该窗口

WM_STYLECHANGED

0x007D

当调用SetWindowLong()函数改变了窗口的一个或多个风格后,发送此消息给该窗口

WM_DISPLAYCHANGE

0x007E

当显示器的分辨率改变后发送此消息给所有的窗口

WM_GETICON

0x007F

发送此消息给某个窗口,返回与某个窗口有关联的大图标或小图标的句柄

WM_SETICON

0x0080

应用程序发送此消息让一个新的大图标或小图标与某个窗口关联

WM_NCCREATE

0x0081

当某个窗口第一次被创建时,此消息在WM_CREATE消息被发送前发送

WM_NCDESTROY

0x0082

此消息通知某个窗口,正在销毁非客户区

WM_NCCALCSIZE

0x0083

当计算某个窗口的客户区大小和位置时发送此消息

WM_NCHITTEST

0x0084

移动鼠标,按住或释放鼠标时产生此消息

WM_NCPAINT

0x0085

当某个窗口的框架必须被绘制时,应用程序发送此消息给该窗口

WM_NCACTIVATE

0x0086

通过改变某个窗口的非客户区来表示窗口是处于激活还是非激活状态时,此消息被发送给该窗口

WM_NCMOUSEMOVE

0x00A0

当光标在窗口的非客户区(窗口标题栏及边框)内移动时发送此消息给该窗口

WM_NCLBUTTONDOWN

0x00A1

当光标在窗口的非客户区并按下鼠标左键时发送此消息

WM_NCLBUTTONUP

0x00A2

当光标在窗口的非客户区并释放鼠标左键时发送此消息

WM_NCLBUTTONDBLCLK

0x00A3

当光标在窗口的非客户区并双击鼠标左键时发送此消息

WM_NCRBUTTONDOWN

0x00A4

当光标在窗口的非客户区并按下鼠标右键时发送此消息

WM_NCRBUTTONUP

0x00A5

当光标在窗口的非客户区并释放鼠标右键时发送此消息

WM_NCRBUTTONDBLCLK

0x00A6

当光标在窗口的非客户区并双击鼠标右键时发送此消息

WM_NCMBUTTONDOWN

0x00A7

当光标在窗口的非客户区并按下鼠标中键时发送此消息

WM_NCMBUTTONUP

0x00A8

当光标在窗口的非客户区并释放鼠标中键时发送此消息

WM_NCMBUTTONDBLCL

0x00A9

当光标在窗口的非客户区并双击鼠标中键时发送此消息

WM_KEYDOWN

0x0100

按下一个非系统键(按下键时未按下“ALT”键)

WM_KEYUP

0x0101

释放一个非系统键

WM_CHAR

0x0102

按下某键,当TranslateMessage()转发WM_KEYDOWN后发送本消息

WM_DEADCHAR

0x0103

释放某键,当TranslateMessage()转发WM_KEYUP后发送本消息

WM_SYSKEYDOWN

0x0104

当按住ALT键同时按下其他键时发送此消息给拥有键盘焦点的窗口

WM_SYSKEYUP

0x0105

当释放一个键同时按住ALT键时发送此消息给拥有键盘焦点的窗口

WM_SYSCHAR

0x0106

当TranslateMessage()转发WM_SYSKEYDOWN后发送此消息给拥有键盘焦点的窗口

WM_SYSDEADCHAR

0x0107

当TranslateMessage()转发WM_SYSKEYUP后发送此消息给拥有键盘焦点的窗口

WM_INITDIALOG

0x0110

在被显示前发送此消息对话框,通常用此消息初始化控件和执行其他任务

WM_COMMAND

0x0111

选择窗口菜单项或某个控件发送一条消息给它的父窗口或按下一个快捷键时产生此消息

WM_SYSCOMMAND

0x0112

选择窗口菜单项或选择最大化或最小化时,发送此消息给该窗口

WM_TIMER

0x0113

发生了定时器事件

WM_HSCROLL

0x0114

当窗口水平滚动条产生一个滚动事件时发送此消息给该窗口和滚动条的所有者

WM_VSCROLL

0x0115

当窗口垂直滚动条产生一个滚动事件时发送此消息给该窗口和滚动条的所有者

WM_INITMENU

0x0116

当一个菜单将要被激活时发送此消息,它发生在按下菜单项或按下菜单快捷键时,它允许程序在显示前更改菜单

WM_INITMENUPOPUP

0x0117

当一个下拉菜单或子菜单将要被激活时发送此消息,它允许显示前在修改菜单而不必更改整个菜单

WM_MENUSELECT

0x011F

选择一条菜单项时发送此消息给菜单的所有者(一般是窗口)

WM_MENUCHAR

0x0120

当菜单已被激活且用户按下了某个键(非快捷键),发送此消息给菜单的所有者

WM_ENTERIDLE

0x0121

当一个有模式对话框或菜单进入空闲状态时发送此消息给它的所有者,空闲状态指在处理完一条或几条先前的消息后,消息列队为空

WM_MENURBUTTONUP

0x0122

当光标位于菜单项上时,释放鼠标右键产生此消息

WM_MENUDRAG

0x0123

当拖动菜单项时,发送此消息给拖放菜单的所有者

WM_MENUGETOBJECT

0x0124

当光标移入菜单项或者从菜单项中心移到菜单项顶部或底部时,发送此消息给拖放菜单的所有者

WM_UNINITMENUPOPUP

0x0125

当下拉菜单或者子菜单被销毁时产生此消息

WM_MENUCOMMAND

0x0126

当用户选择菜单项时产生此消息

WM_CHANGEUISTATE

0x0127

应用程序发送此消息表明用户界面(UI)状态应当被改变

WM_UPDATEUISTATE

0x0128

应用程序发送此消息改变指定窗口及其子窗口的用户界面(UI)状态

WM_QUERYUISTATE

0x0129

应用程序发送此消息得到某个窗口的用户界面(UI)状态

WM_CTLCOLORMSGBOX

0x0132

绘制消息框前发送此消息给它的父窗口,通过响应这条消息,父窗口可以通过使用给定的相关显示设备的句柄来设置消息框的文本和背景颜色

WM_CTLCOLOREDIT

0x0133

绘制编辑型控件前发送此消息给它的父窗口,可用来设置编辑框的文本和背景颜色

WM_CTLCOLORLISTBOX

0x0134

绘制列表框控件前发送此消息给它的父窗口,可用来设置编辑框的文本和背景颜色

WM_CTLCOLORBTN

0x0135

绘制按钮控件前发送此消息给它的父窗口,可用来设置编辑框的文本和背景颜色

WM_CTLCOLORDLG

0x0136

绘制对话框前发送此消息给它的父窗口,可用来设置编辑框的文本和背景颜色

WM_CTLCOLORSCROLLBAR

0x0137

绘制滚动条控件前发送此消息给它的父窗口,可用来设置滚动条控件的文本和背景颜色

WM_CTLCOLORSTATIC

0x0138

绘制静态控件前发送此消息给它的父窗口,可用来设置静态控件的文本和背景颜色

WM_MOUSEMOVE

0x0200

鼠标移动

WM_LBUTTONDOWN

0x0201

按下鼠标左键

WM_LBUTTONUP

0x0202

释放鼠标左键

WM_LBUTTONDBLCLK

0x0203

双击鼠标左键

WM_RBUTTONDOWN

0x0204

按下鼠标右键

WM_RBUTTONUP

0x0205

释放鼠标右键

WM_RBUTTONDBLCLK

0x0206

双击鼠标右键

WM_MBUTTONDOWN

0x0207

按下鼠标中键

WM_MBUTTONUP

0x0208

释放鼠标中键

WM_MBUTTONDBLCLK

0x0209

双击鼠标中键

WM_MOUSEWHEEL

0x020A

当鼠标滚轮转动时发送此消息给当前获得焦点的窗口

WM_PARENTNOTIFY

0x0210

当MDI子窗口被创建或被销毁,或当光标位于子窗口上且用户按了一下鼠标键时,发送此消息给它的父窗口

WM_ENTERMENULOOP

0x0211

发送此消息通知应用程序的主窗口进程已经进入了菜单模式循环

WM_EXITMENULOOP

0x0212

发送此消息通知应用程序的主窗口进程已经退出了菜单模式循环

WM_SIZING

0x0214

调整窗口大小时发送此消息给窗口,通过此消息应用程序可以监视或修改窗口大小和位置

WM_CAPTURECHANGED

0x0215

当窗口设定为不捕获鼠标事件时,发送此消息给该窗口

WM_MOVING

0x0216

移动窗口时发送此消息给窗口,通过此消息应用程序可以监视或修改窗口大小和位置

WM_POWERBROADCAST

0x0218

发送此消息给应用程序通知它有关电源管理事件

WM_DEVICECHANGE

0x0219

当设备的硬件配置改变时发送此消息给应用程序或设备驱动程序

WM_MDICREATE

0x0220

应用程序发送此消息给多文档的客户窗口来创建一个MDI 子窗口

WM_MDIDESTROY

0x0221

应用程序发送此消息给多文档的客户窗口来关闭一个MDI 子窗口

WM_MDIACTIVATE

0x0222

应用程序发送此消息给多文档的客户窗口通知客户窗口激活另一个MDI子窗口,当客户窗口收到此消息后,它发出WM_MDIACTIVE消息给MDI子窗口(未激活)来激活它

WM_MDIRESTORE

0x0223

应用程序发送此消息给MDI客户窗口通知子窗口恢复到原来大小

WM_MDINEXT

0x0224

应用程序发送此消息给MDI客户窗口激活下一个或前一个窗口

WM_MDIMAXIMIZE

0x0225

应用程序发送此消息给MDI客户窗口以最大化一个MDI子窗口

WM_MDITILE

0x0226

应用程序发送此消息给MDI客户窗口以平铺方式重新排列所有MDI子窗口

WM_MDICASCADE

0x0227

应用程序发送此消息给MDI客户窗口以层叠方式重新排列所有MDI子窗口

WM_MDIICONARRANGE

0x0228

应用程序发送此消息给MDI客户窗口重新排列所有最小化的MDI子窗口

WM_MDIGETACTIVE

0x0229

应用程序发送此消息给MDI客户窗口以找到激活的子窗口的句柄

WM_MDISETMENU

0x0230

应用程序发送此消息给MDI客户窗口用MDI菜单代替子窗口的菜单

WM_ENTERSIZEMOVE

0x0231

当窗口进入移动或改变大小模式循环时,发送此消息给该窗口

WM_EXITSIZEMOVE

0x0232

当窗口退出移动或改变大小模式循环时,发送此消息给该窗口

WM_DROPFILES

0x0233

当用户在应用程序窗口中拖动某个文件时,产生此消息

WM_MDIREFRESHMENU

0x0234

应用程序发送此消息给MDI客户窗口以刷新窗口菜单

WM_MOUSEHOVER

0x02A1

当光标在窗口客户区悬停超过TrackMouseEvent()指定的时间时,发送此消息给该窗口

WM_MOUSELEAVE

0x02A3

当光标离开窗口客户区超过TrackMouseEvent()指定的时间时,发送此消息给该窗口

WM_CUT

0x0300

应用程序发送此消息给一个编辑框或ComboBox以删除当前选择的文本

WM_COPY

0x0301

应用程序发送此消息给一个编辑框或ComboBox以复制当前选择的文本到剪贴板

WM_PASTE 

0x0302

应用程序发送此消息给一个编辑框或ComboBox以从剪贴板中得到数据

WM_CLEAR

0x0303

应用程序发送此消息给一个编辑框或ComboBox以清除当前选择的内容

WM_UNDO

0x0304

应用程序发送此消息给一个编辑框或ComboBox以撤消最后一次操作

WM_DESTROYCLIPBOARD

0x0307

当调用EmptyClipboard()清空剪贴板时,发送此消息给剪贴板所有者

WM_DRAWCLIPBOARD

0x0308

当剪贴板的内容变化时发送此消息给剪贴板观察链中的第一个窗口,它允许用剪贴板观察窗口来显示剪贴板的新内容

WM_PAINTCLIPBOARD

0x0309

当剪贴板包含CF_OWNERDIPLAY格式的数据且剪贴板观察窗口的客户区需要重绘时,发送此消息给剪贴板所有者

WM_VSCROLLCLIPBOARD

0x030A

当剪贴板包含CF_OWNERDIPLAY格式的数据且剪贴板观察窗口发生垂直滚动条事件时,剪贴板观察窗口发送此消息给剪贴板所有者

WM_SIZECLIPBOARD

0x030B

当剪贴板包含CF_OWNERDIPLAY格式的数据且剪贴板观察窗口的客户区域的大小已经改变时,剪贴板观察窗口发送此消息给剪贴板的所有者

WM_ASKCBFORMATNAME

0x030C

剪贴板观察窗口发送此消息给剪贴板所有者以获得CF_OWNERDISPLAY剪贴板格式的名字

WM_CHANGECBCHAIN

0x030D

当一个窗口从剪贴板观察链中移去时发送此消息给剪贴板观察链中的第一个窗口

WM_HSCROLLCLIPBOARD

0x030E

当剪贴板包含CF_OWNERDIPLAY格式的数据且剪贴板观察窗口发生水平滚动条事件时,剪贴板观察窗口发送此消息给剪贴板所有者

WM_QUERYNEWPALETTE

0x030F

发送此消息给将要获得键盘焦点的窗口,此消息使窗口在获得焦点时同时有机会实现它的逻辑调色板

WM_PALETTEISCHANGING

0x0310

应用程序将要实现它的逻辑调色板时发送此消息通知所有应用程序

WM_PALETTECHANGED

0x0311

获得焦点的窗口实现它的逻辑调色板后发送此消息给所有顶级并重叠的窗口,以此

来改变系统调色板

WM_HOTKEY

0x0312

当用户按下由RegisterHotKey()注册的热键时产生此消息

WM_PRINT

0x0317

应用程序发送此消息给窗口,要求窗口在指定设备环境中绘制自己,一般情况下是打印机设备环境

WM_PRINTCLIENT

0x0318

应用程序发送此消息给窗口,要求窗口在指定设备环境中绘制窗口客户区,一般情况下是打印机设备环境

WM_APP

0x8000

帮助用户自定义消息,自定义消息可以为WM_APP+X,X为正整数

WM_USER

0x0400

帮助用户自定义消息,自定义消息可以为WM_USER+X,X为正整数

3.3 总结

  表A-3  公告音信-按键

1> ShellExecuteEx展开test.iqy的时先创造excel进度

消息名称

说 明

BN_CLICKED

单击按钮

BN_DISABLE

按钮被禁止

BN_DOUBLECLICKED

双击按钮

BN_HILITE

加亮按钮

BN_PAINT

按钮应当重画

BN_UNHILITE

加亮应当去掉

2> 然后创建一个”WorkerW”的窗口用于DDE通讯

表A-4  通知音讯-组合框

3> Post WM_DDE_EXECUTE给excel,告知展开test.iqy的授命

消息名称

说 明

CBN_CLOSEUP

组合框的列表框被关闭

CBN_DBLCLK

用户双击了一个字符串

CBN_DROPDOWN

组合框的列表框被拉下

CBN_EDITCHANGE

用户修改了组合框中的文本

CBN_EDITUPDATE

组合框内的文本即将更新

CBN_ERRSPACE

组合框内存不足

CBN_KILLFOCUS

组合框失去输入焦点

CBN_SELCHANGE

在组合框中选择了一项

CBN_SELENDCANCEL

用户的选择将被忽略

CBN_SELENDOK

用户的选择将被执行

CBN_SETFOCUS

组合框获得输入焦点

4> ShellExecuteEx实施达成,但并不destroy “WorkerW”窗口

表A-5  布告音信-编辑框

5>
excel收到WM_DDE_EXECUTE音讯后会广播WM_DDE_INITIATE新闻,”WorkerW”窗口所在的console进度由于没有定义新闻管理函数,ShellExecuteEx定义的”WorkerW”窗口音讯处理函数得不到CPU执行时机,招致不会response该音信,进而导致excel
hang住

消息名称

说 明

EN_CHANGE

编辑框中的文本己更新

EN_ERRSPACE

编辑框内存不足

EN_HSCROLL

用户点击了水平滚动条

EN_KILLFOCUS

编辑框失去输入焦点

EN_MAXTEXT

插入的内容被截断

EN_SETFOCUS

编辑框获得输入焦点

EN_UPDATE

编辑框中的文本将要更新

EN_VSCROLL

用户点击了垂直滚动条

仿佛,我们得以创设一个带窗口的程序,运营后将其挂起,那时候,即使直接双击展开test.iqy也会hang住。

表A-6  文告音信-列表框

 

消息名称

说 明

LBN_DBLCLK

用户双击了一项

LBN_ERRSPACE

列表框内存不足

LBN_KILLFOCUS

列表框正在失去输入焦点

LBN_SELCANCEL

用户选择被取消

LBN_SELCHANGE

用户选择将改变

LBN_SETFOCUS

列表框获得输入焦点

4. 怎么双击展开excel不会hang住

Windows新闻大全

因为双击展开实际是用explorer.exe张开,而explorer.exe是有窗口的,能够健康的吸纳管理WM_DDE_INITIATE消息

  Windows是意气风发音信(Message卡塔尔驱动式系统,Windows音讯提供了应用程序与应用程序之间、应用程序与Windows系统之间实行电视发表的招数。应用程序要促成的职能由消息来触发,并靠对新闻的响应和管理来形成。Windows系统中有二种音讯队列,风姿洒脱种是系统消息队列,另大器晚成种是应用程序音讯队列。计算机的有所输入设备由
Windows监察和控制,当贰个事变爆发时,Windows先将输入的新闻归入系统音讯队列中,然后再将输入的音讯拷贝到相应的应用程序队列中,应用程序中的音信循环从它的新闻队列中探究每三个音讯并发送给相应的窗口函数中。五个风浪的发出,达到管理它的窗口函数必需资历上述进程。值得注意的是新闻的非超过性,即无论事件的急与缓,总是按达到的主次排队(一些系统消息除了那些之外),那就使得有个别外表实时事件可能得不到马上的处理。

 

  由于Windows自个儿是由音信使得的,举贰个例子来注脚那几个难题。打开记事本程序,该程序有一个File菜单,那么,在运转该应用程序的时候,借使顾客单击了File菜单里New命令时,这么些动作将被Windows
(并不是应用程序本人!卡塔 尔(英语:State of Qatar)所捕获,Windows经过剖判获悉这一个动作应该由地点所说的丰盛应用程序去管理,既然是如此,Windows就发送了个名称叫WM_COMMAND的新闻给应用程序,该新闻所蕴藏音讯报告应用程序:”客户单击了New菜单”,应用程序得到消息这朝气蓬勃音信之后,选拔对应的动作来响应它,那一个历程称为音讯管理。Windows为每一个应用程序(确切地说是每三个线程)维护了相应的新闻队列,应用程序的任务正是不停的从它的音信队列中赢得新闻,解析消息和拍卖音讯,直到一条吸收名称为WM_QUIT消息结束,这么些进度平常是由后生可畏种名称叫消息循环的程序结构来得以完结的。

5. 怎么win7上不会有那样的难点

  音信作者是作为三个记下传递给应用程序的,那几个记录中满含了音讯的品种以致其余新闻。比如,对于单击鼠标所发生的新闻的话,那几个记录中含有了单击鼠标时的坐标。这么些记录类型叫做T
M s g,它在Wi n d o w s单元中是那样证明的:

5.1 在API Monitor中看下PostMessageW

type

www.301.net 115

TMsg = packedrecord

注意到win7下PostMessageW是用的线程2调用的,搜一下线程创设API
CreateThread

hwnd: HWND / /窗口句柄

www.301.net 116

message: UINT / /新闻常量标志符

可见是ShellExecuteEx内部创造的线程,所以win7上ShellExecuteEx创造了多少个线程专门用来拍卖和excel的DDE消息通讯,那样就会健康的收随地理excel发过来的WM_DDE_INITIATE消息了

wParam: WPA Qashqai AM  // 31位音讯的特定附加音讯

lParam: LPA 酷威 AM  // 叁15个人新闻的一定附加消息

time: DWORAV4D / /音讯创造时的年华

pt: TPoint / /音信创造时的鼠标地点

end

 

新闻中有啥?

是否感觉一个新闻记录中的音讯像克罗地亚语相仿?假设是那般,那么看意气风发看上边包车型客车降解:

hwnd
三十人的窗口句柄。窗口能够是其他项指标显示屏对象,因为Win32能力所能达到有限帮助大大多可视对象的句柄(窗口、对话框、开关、编辑框等)。

message
用于区分别的新闻的常量值,这么些常量能够是Windows单元中预约义的常量,也足以是自定义的常量。

wParam 日常是二个与新闻有关的常量值,也恐怕是窗口或控件的句柄。

lParam
平时是叁个照准内部存储器中数据的指针。由于WParm、lParam和Pointer都是34人的,由此,它们之间能够相互转变。

 

WM_NULL = 0

WM_CREATE = 1

应用程序创造三个窗口

WM_DESTROY = 2

一个窗口被灭绝

WM_MOVE = 3

一抬手一动脚二个窗口

WM_SIZE = 5

修改七个窗口的尺寸

WM_ACTIVATE = 6

贰个窗口被激活或失去激活状态;

WM_SETFOCUS = 7

收获大旨后

WM_KILLFOCUS = 8

错开核心

WM_ENABLE = 10

改变enable状态

WM_SETREDRAW = 11

安装窗口是不是能重画

WM_SETTEXT = 12

应用程序发送此音信来设置三个窗口的文件

WM_GETTEXT = 13

应用程序发送此新闻来复制对应窗口的文件到缓冲区

WM_GETTEXTLENGTH =14

拿到与二个窗口有关的文件的长短(不包涵空字符卡塔 尔(阿拉伯语:قطر‎

WM_PAINT = 15

渴求二个窗口重画自身

WM_CLOSE = 16

当三个窗口或应用程序要关门时发送三个非复信号

WM_QUERYENDSESSION= 17

当客户筛选截止对话框或程序本人调用ExitWindows函数

WM_QUIT = 18

用来终止程序运营或当程序调用postquitmessage函数

WM_QUERYOPEN = 19

当客商窗口恢复生机原先的轻重地点时,把此消息发送给有个别Logo

WM_ERASEBKGND = 20

当窗口背景必得被擦除时(例在窗口改造大小时卡塔尔国

WM_SYSCOLORCHANGE =21

当系统颜色校勘时,发送此音信给全部一流窗口

WM_ENDSESSION = 22

当系统经过产生WM_QUEEscortYENDSESSION消息后,此音讯发送给应用程序,

通知它对话是或不是截至

WM_SYSTEMERROR = 23

WM_SHOWWINDOW = 24

当隐敝或出示窗口是发送此音信给那些窗口

WM_ACTIVATEAPP = 28

发此音信给应用程序哪个窗口是激活的,哪个是非激活的;

WM_FONTCHANGE = 29

当系统的书体能源库变化时发送此消息给全体一流窗口

WM_TIMECHANGE = 30

当系统的时日改造时发送此新闻给持有超级窗口

WM_CANCELMODE = 31

发送此音信来撤除某种正在开展的摸态(操作卡塔尔国

WM_SETCURSOR = 32

假定鼠标引起光标在有些窗口中移动且鼠标输入未有被破获时,就发音讯给有个别窗口

WM_MOUSEACTIVATE =33

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图