Windows新闻机制要点

通过可以怀疑是出于console进度在和excel用DDE音讯通讯时,console没有响应excel发送的DDE音信,导致excel
hang住

8(新闻死锁( Message Deadlocks) 
假诺有线程A和B, 现在有以下下步骤
1) 线程A SendMessage给线程B, A等待新闻在线程B中拍卖后归来
2) 线程B收到了线程A发来的信息,并展开拍卖, 在处理进程中,B也向线程A
SendMessgae,然后等待从A重返。
因为那时, 线程A正等待从线程B重临, 无法处理B发来的音信,
从而导致了/线程A,B彼此等待, 形成死锁。七个线程也能够形成环形死锁。
可以使用 SendNotifyMessage或SendMessage提姆eout来防止出现死锁。

重返一个图标或光标的句柄,当用户拖放图标时系统展现这么些图标或光标

该函数通过调用窗口进程的方法发送信息,如若窗口属于分化线程,SendMessageTimerout将驾驭信息处理已毕才回去或者指定的超时已经过去,借使窗口就在脚下线程,则直接调用窗口进程,并忽略time-out超时

SendNotifyMessage
比方窗口创造于属于发送音信的线程,则调用窗口进度,并等候窗口进度处理落成该信息。若是是差异线程,则将音信传递到窗口进度,并立刻重返,不等待窗口进度的音信处理进程。


TranslateMessage
1.将虚拟键信息转换为字符新闻,然后将字符音讯发送到调用线程的音信队列中,该字符音讯将在下次调用GetMessage或者PeekMessage信息的时候获获得。
2.WM_(SYS)KEYDOWN/UP—>WM_(SYS)_CHAR
3.只要应用程序为了其他目标,处理虚拟键新闻,那么就不该调用TranslateMessage.与一个实例,应用程序不应有在TranslateAccelerator函数再次回到非0值时调用TranslateMessage

关于信息和新闻队列
不像基于MS-DOS的应用程序,基于Windows的顺序是事件驱动的。他们不做此外突显调…

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直接发送到窗口进程处理,
处理完后才会回去。

当用户按下由REGISTERHOTKEY函数注册的热键时提交此新闻

得到线程近日三次准备处理一个消息的系统时间(GetTickCount)

GetMessageSource
MSGSRC_SOFTWARE_POST表面键盘信息来源于software(postmessage标记为software).
MSGSRC_HARDWARE_KEYBOARD 表面音讯来源于keyboard. MSGSRC_UNKNOWN

图片 1

5 PostMessage(PostThreadMessage), SendMessage 
PostMessage:把新闻放到指定窗口所在的线程新闻队列中后随即回去。
PostThreadMessage:把信息放到指定线程的音讯队列中后当即回到。
SendMessage:直接把新闻送到窗口进程处理,处理完了才回去。

L B N _ K I L L F OC U S列表框正在失去输入主旨

归来值得高字节表示近日在新闻队列中的新闻类型。低字节表示从上次GetQueueStatus,GetMessage或者PeekMessage后被投入队列的新闻类型。

InSendMessage

表明excel给持有顶层窗口发送一个WM_DDE_INITIATE音讯,不过有窗口没有response

WM_MENUSELECT = 287

该函数将取得和hWnd或者其子窗口相关的新闻。

DWORD GetMessagePos(void);

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_TIMER唯有在Queue中从不其余音信的时候才会被拍卖,WM_PAINT新闻还会被合并以提升效能。其他具备音信以先进先出(FIFO)的点子被处理。

当平台现场一度被转移后发送此信息给受影响的最顶级窗口

信息来源未知

DWORD GetQueueStatus(
UINT flags
);
在音讯队列中的音信的体系
flags为要检测的音讯类型。

3.2.1
根据微软的文档可见,发送DDE信息除了WM_DDE_INITIATE和WM_DDE_ACK之外用的都是PostMessage

6 GetMessage, PeekMessage 
PeekMessage会立即赶回可以保存新闻
GetMessage在有新闻时重临会去除音信

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

非信息队列格局,直接调用窗口进度,系统立刻切换来接受线程执行,发送线程锁住,知道接收线程处理达成

SendMessageTimeout

因为双击打开实际是用explorer.exe打开,而explorer.exe是有窗口的,可以健康的吸收处理WM_DDE_INITIATE消息

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

WM_IME_KEYDOWN =656

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

GetMessage
应用程序使用该函数再次回到值来支配是不是终止音讯循环,并退出程序。

 

9 BroadcastSystemMessage 
我们一般所接触到的新闻都是发送给窗口的,其实,
新闻的收信人可以是数见不鲜的,它可以是应用程序(applications),
可安装驱动(installable drivers),网络设施(network drivers),
系统级设备驱动(system-level device drivers)等, 
BroadcastSystemMessage那几个API可以对以上系统组件发送信息。

当屏幕的分辨率改变后发送此信息给所有的窗口

4.一旦应用程序正在成立顶层窗口时调用PeekMessage,将导致窗口窗口被创立在Z-Order的末梢。你需求在PeekMessage后,显式调用SetForegroundWindow。即使应用程序以及有一个放到窗口了,那么新窗口将被内置。

PostMessage
应用程序要用HWND_BROADCAST进行程序间的交互,音信应该得到于RegisterWindowMessage()

3. 缘故剖析

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, LOWORD(wParam)表示菜单项,工具栏按钮或控件的ID。如果是控件,
HIWORD(wParam)表示控件信息类型
3> 控件通告(Notify Message) 
控件文告音信, 那是最灵敏的新闻格式, 其Message, wParam,
lParam分别为:WM_NOTIFY,
控件ID,指向NMHDR的指针。NMHDR包括控件通告的内容, 能够肆意扩展。
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

出殡此新闻来判断combobox或listbox新扩展的项的相持地点

至于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_USER)-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没有发送新闻地方和时间到窗口进度,应用程序可以经过Getmessage提姆e和GetMessagePos函数。

当新闻队列中绝非新闻的时候,线程可以行使WaitMessage函数来将控制器交给其余线程,那个函数暂停线程,知道一个新音信赶到,该函数才回到。

你也可以调用SetMessageExtraInfo来为当下音信队列附加一个值,通过GetMessageExtraInfo来获取那个值。

非队列信息
绕过了系统和线程信息队列,非队列音信直接发送至窗口进程。系统卓绝发送非队列信息来打招呼一个窗口,一个轩然大波影响了它。例如,当用户激活一个新窗口,系统发送给窗口
WM_ACTIVATE, WM_SETFOCUS, and
WM_SETCURSOR新闻。这一个信息通告窗口它曾经被激活了,键盘输入正指向该窗口,鼠标光标已经移至了窗口边框内。当应用程序调用某些系统函数时,也会窗口非队列信息,比如,应用程序在调用SetWindowPos时,系统将发送WM_WINDOWPOSCHANGED消息。

稍微音信发送非队列新闻:BroadcastSystemMessage,
BroadcastSystemMessageEx, 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或者SendMessage提姆eout。要不然,窗口进度可以透过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.连串预定义音讯其实大都是那几个控件新闻,文告音讯,系统广播信息等等。

 

1. 窗口进度 
种种窗口会有一个叫做窗口进度的回调函数(WndProc),它包括三个参数,分别为:窗口句柄(Window
Handle),音信ID(Message ID),和八个音信参数(wParam,
lParam),当窗口收到音信时系统就会调用此窗口进度来处理信息。(所以叫回调函数)

当用户按下鼠标右键同时光标又在窗口的非客户区时发送此信息

若果发送音信低于WM_USER范围,到异步新闻队列函数(PostMessage、SendNotifyMessage),音信参数不应当包蕴指针,不然的话,操作将破产。该函数将在收到线程有机遇处理该音信前重临,发送者将释放刚刚用到的内存。

PostQuitMessage

图片 2

WM_CANCELMODE = 31

该函数重临音讯x,y坐标,在多重monitor下,可能有负值。

GetMessageQueueReadyTimeStamp

1. 问题

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

新闻相关函数:

DispatchMessage

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

 

WM_ENDSESSION = 22

用来判断当前窗口进度所拍卖的音讯,是不是来自别的线程的SendMessage调用。

PeekMessage
1.该函数核查线程新闻队列中是不是有信息,并将信息放在参数结构体中
2.只要hWnd参数=-1,则只回去hWnd=NULL的音信,那种信息来源于PostThreadMessage
3.参数wRemoveMsg要求小心

1> ShellExecuteEx打开test.iqy的时先创设excel进度

该函数只是简短申明被呼吁终止的线程将会为止。接收WM_QUIT的线程,应该甘休音讯循环,并将控制权交给系统。再次来到给系统的退出值,一定是WM_QUIT的wParam参数

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

接收音信的线程,通过GetMessage/PeekMessage来获取信息,hWnd成员将会是空


RegisterWindowMessage
同一字符串,注册的值,在方方面面系统中是绝无仅有的


SendMessage

据悉DDE的新闻参数,可见wParam就是殡葬信息的窗口,其句柄为2425190 =
0x250166,反向查询知那是ShellExecuteEx创制的”WorkerW”窗口

图片 3typedef struct tagMsg
图片 4{
图片 5       HWND    hwnd;       //接受该音讯的窗口句柄
图片 6       UINT    message;    //信息常量标识符,也就是大家常见所说的信息号
图片 7       WPARAM  wParam;     //32位信息的特定附加音信,确切含义着重于信息值
图片 8       LPARAM  lParam;     //32位信息的特定附加信息,确切含义爱护于音信值
图片 9       DWORD   time;       //信息成立时的时光
图片 10       POINT   pt;         //信息创设时的鼠标/光标在屏幕坐标系中的地点
图片 11}MSG;
图片 12

当在console中调用API
ShellExecuteEx打开”test.iqy”文件时,发现excel会hang住,console退出后excel才会响应,但直接双击”test.iqy”是绝非难点的,有意思的是其一景况唯有在xp爆发,在win7上未曾那些题材。

 

接近,大家能够创立一个带窗口的次第,启动后将其挂起,那时,纵然直接双击打开test.iqy也会hang住。

WM_SETICON = 128

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

WM_PASTE = 770

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

经过行使给定的连锁展现设备的句柄来安装静态控件的文本和背景颜色

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 %p\n", shell_exec_info.hProcess);

    return ret;
}

次第发送此新闻给MDI客户窗口以平铺格局重新排列所有MDI子窗口

图片 13

WM_GETFONT = 49

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

在一个对话框程序被突显前发送此新闻给它,经常用此音讯伊始化控件和实践其余职分

3.3 总结

发送此信息给某个与对话框程序关联的控件,widdows控制方位键和TAB键使输入进去此控件

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

WM_ERASEBKGND = 20

其一窗口所属的历程PID =
0xc54,正好是excel的长河,表明ShellExecuteEx确实发送了DDE音讯给excel,而且可执发送的音信的thread就是主线程

当调用SETWINDOWLONG函数一个或多少个 窗口的品格后发送此新闻给那么些窗口

5. 怎么win7上不会有如此的难题

WM_IME_REQUEST =648

3.1 excel hang在哪里?

WM_IME_KEYLAST =271

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

共控件如树状视图、列表视图等。例如,单击或双击一个控件、在控件中拔取一些文件、操作控件的

2> 运行http_server.py(需先安装python)

当用户按住ALT键同时按下任何键时提交此音信给持有大旨的窗口;

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

一个DDE客户程序提交此新闻给一个DDE服务程序来呼吁一个数量项的值;

 

出殡此新闻文告应用程序的主窗口that已退出了菜单循环方式

图片 14

当button, combo box, list box, list view control, or menu item 被成立时

shell_execute.exe的主要code:

C B N _ E R R S PAC E组合框内存不足

3.2 为了验证3.1.1的推断,用API Monitor一下ShellExecuteEx

WM_IME_COMPOSITIONFULL= 644

复出环境:XP sp3 / Office 2007(其余office版本应该也可以,没有测试)

发送此新闻公告应用程序的主窗口that已经进来了菜单循环方式

图片 15

出殡此新闻给一个会话框程序去改变宗旨地方

图片 16

好了,事情到了这一步,应该全套都晴朗了。
只是,大家发现在windowsx.h里面还有一个宏:FORWARD_WM_XXXX,大家照旧那WM_COMMAND为例,举行剖析:

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

次第发送此音讯给某个窗口当它(窗口)的框架必须被绘制时;

NtUserMessageCall(HWND_BROADCAST, WM_DDE_INITIATE)

WM_COPY = 769

 

WM_DDE_EXECUTE =WM_DDE_FIRST + 8

4. 为何双击打开excel不会hang住

WM_NCCALCSIZE = 131

瞩目到下一个API GetWindowThreadProcessId ( 0x00310172 , 0x0012fb70
),刚好是获取这么些窗口的pid和tid,查看下参数窗口:

公告音信(Notification
message)是指那样一种音信,一个窗口内的子控件发生了一部分事情,需求通

图片 17

一个DDE应用程序(无论是客户仍然服务器)提交此信息来终止一个会话;

call stack呈现的确是ShellExecuteEx所调用

WM_DDE_POKE =WM_DDE_FIRST + 7

翻看一下buff的地方:

当某个控件的某个事件早已发生或以此控件须要取得部分音信时,发送此信息给它的父窗口

 

图片 18LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
图片 19{
图片 20 int wmId, wmEvent;
图片 21 PAINTSTRUCT ps;
图片 22 HDC hdc;
图片 23 TCHAR szHello[MAX_LOADSTRING];
图片 24 LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
图片 25
图片 26 switch (message) 
图片 27 {
图片 28  case WM_COMMAND:
图片 29         wmId    = LOWORD(wParam); 
图片 30         wmEvent = HIWORD(wParam); 
图片 31         // Parse the menu selections:
图片 32         switch (wmId)
图片 33         {
图片 34          case IDM_ABOUT:
图片 35             DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
图片 36             break;
图片 37          case IDM_EXIT:
图片 38             DestroyWindow(hWnd);
图片 39             break;
图片 40          default:
图片 41             return DefWindowProc(hWnd, message, wParam, lParam);
图片 42         }
图片 43   break;
图片 44
图片 45  case WM_PAINT:
图片 46         hdc = BeginPaint(hWnd, &ps);
图片 47         // TODO: Add any drawing code here图片 48
图片 49         RECT rt;
图片 50         GetClientRect(hWnd, &rt);
图片 51         DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
图片 52         EndPaint(hWnd, &ps);
图片 53         break;
图片 54
图片 55  case WM_DESTROY:
图片 56         PostQuitMessage(0);
图片 57         break;
图片 58  default:
图片 59         return DefWindowProc(hWnd, message, wParam, lParam);
图片 60  }
图片 61  return 0;
图片 62}
图片 63

正要就是打开test.iqy的吩咐,表达ShellExecuteEx就是先创建了excel的进度,然后发送test.iqy的文本命令给excel打开。

WM_MDITILE = 550

5.1 在API Monitor中看下PostMessageW

WM_MBUTTONDBLCLK =521

可以是ShellExecuteEx内部创制的线程,所以win7上ShellExecuteEx创立了一个线程专门用来处理和excel的DDE音信通讯,那样就能正常的吸纳处理excel发过来的WM_DDE_INITIATE消息了

//释放一个键

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

应用程序发送此消息仅当WINDOWS或任何应用程序发出一个请求须求绘制一个应用程序的一部分;

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

当用户挑选一条菜单命令项或当某个控件发送一条新闻给它的父窗口,一个火速键被翻译

翻看参数知excel调用NtUserMessageCall()类似如下:

 

  
首先,GetMessage从进度的主线程的信息队列中取得一个新闻并将它复制到MSG结构,若是队列中从未音讯,则GetMessage函数将拭目以待一个新闻的到来未来才重回。若是你将一个窗口句柄作为第四个参数传入GetMessage,那么唯有指定窗口的的新闻可以从队列中取得。GetMessage也足以从音信队列中过滤新闻只接受音讯队列中落在限定内的新闻。这时候就要采纳GetMessage/PeekMessage指定一个音信过滤器。那么些过滤器是一个音信标识符的限制或者是一个窗体句柄,或者双方同时指定。当应用程序要物色一个后入信息队列的音信是很有用。WM_KEYFIRST
和 WM_KEYLAST 常量用于接受所有的键盘信息。 WM_MOUSEFIRST 和
WM_MOUSELAST 常量用于接受所有的鼠标信息。 
 然后TranslateAccelerator判断该音讯是否一个按键信息还如若一个加速键音信,假使是,则该函数将把多少个按键音讯转换成一个加快键音讯传递给窗口的回调函数。处理了加快键之后,函数TranslateMessage将把七个按键新闻WM_KEYDOWN和WM_KEYUP转换成一个
WM_CHAR,然则必要小心的是,音信WM_KEYDOWN,WM_KEYUP依然将传递给窗口的回调函数。     
 处理完事后,DispatchMessage函数将把此音信发送给该音讯指定的窗口中已设定的回调函数。假设新闻是WM_QUIT,则
GetMessage重回0,从而退出循环体。应用程序能够动用PostQuitMessage来截止自己的新闻循环。常常在主窗口的
WM_DESTROY音信中调用。
 上边我们举一个常见的小例子来证实这一个信息泵的运用:

图片 64

此音信由一个LBS_WANTKEYBOARDINPUT风格的列表框发送给他的持有者来响应WM_CHAR消息

4> ShellExecuteEx执行落成,但并不destroy “WorkerW”窗口

WM_PAINTCLIPBOARD =777

2. 重现步骤

WM_ACTIVATE = 6

3> Post WM_DDE_EXECUTE给excel,告知打开test.iqy的指令

来改变系统调色板

图片 65

B N _ C L I C K E D//用户单击了按钮

 

WM_PENWINFIRST =896

图片 66

此信息通过一个剪贴板观看窗口发送给剪贴板的持有者;它发出在当剪贴板包涵CFOWNERDISPALY格式的多少同时有个事件在剪贴板观望窗的品位滚动条上;所有者应滚动剪贴板图象并创新滚动条的值;

此音信给这么些空件的所有者

message: UINT / /音讯常量标识符

WM_SETTEXT = 12

WM_CLEAR = 771

 

按扭

//按下鼠标左键

B N _ PA I N T按钮应当重画

WM_CREATE = 1

WM_INITDIALOG = 272

WM_PRINT = 791

WM_ASKCBFORMATNAME= 780

此音讯发送给应用程序来通告它有关电源管监护人件;

WM_NCRBUTTONUP =165

每当打印管理列队增添或收缩一条作业时发生此新闻

当剪贴板的内容变更时发送此新闻给剪贴板观察链的第三个窗口;它同意用剪贴板寓目窗口来

当用户自由鼠标左键同时光标某个窗口在非客户区十发送此新闻;

WM_DDE_FIRST = 992

当调用SETWINDOWLONG函数将要改变一个或多少个窗口的品格时发送此音信给那多少个窗口

此音讯呈现用户按下了F1,如若某个菜单是激活的,就发送此音信个此窗口关联的食谱,否则就

WM_ENTERSIZEMOVE =561

当剪贴板包罗CF_OWNERDIPLAY格式的数量同时剪贴板观望窗口的客户区域的尺寸已经转移是此信息通过剪贴板观望窗口发送给剪贴板的持有者;

//释放鼠标中键

 

//释放鼠标右键

  那里咱们承受所有的键盘新闻,所以就用WM_KEYFIRST 和
WM_KEYLAST作为参数。最后一个参数可以是PM_NOREMOVE 或者
PM_REMOVE,表示音讯新闻是或不是相应从音信队列中剔除。                 
   所以那段小代码就是判定是不是按下了Esc键,倘使是就举办拍卖。

B N _ U N H I L I TE加亮应当去掉

  音信我是用作一个记下传递给应用程序的,那么些记录中包括了音讯的种类以及其余音信。例如,对于单击鼠标所爆发的信息的话,这些记录中富含了单击鼠标时的坐标。那一个记录类型叫做T
M s g,它在Wi n d o w s单元中是这么阐明的:

WM_MDIDESTROY = 545

此音讯有一个LBS_WANTKEYBOARDINPUT风格的暴发给它的所有者来响应WM_KEYDOWN消息

wParam: WPA R AM  // 32位信息的一定附加新闻

WM_SETFONT = 48

hwnd
32位的窗口句柄。窗口可以是别的项目的显示屏对象,因为Win32可以爱抚半数以上可视对象的句柄(窗口、对话框、按钮、编辑框等)。

WM_POWER = 72(适用于16位的windows)

WM_CTLCOLORBTN =309

此音信发送给将要收到主题的窗口,此音讯能使窗口在接受主旨时同时有时机完毕他的逻辑调色板

WM_MDISETMENU = 560

新闻分流器
  平日的窗口进度是透过一个switch语句来达成的,那些业务很烦,有没有更便捷的法子吗?有,那就是新闻分流器,利用音信分流器,大家可以把switch语句分成更小的函数,每一个音讯都对应一个小函数,那样做的好处就是对音讯更便于管理。
  之所以被称呼新闻分流器,就是因为它可以对其余新闻进行分流。上面我们做一个函数就很了解了:

也得以修改他们

通过运用给定的有关突显设备的句柄来设置列表框的文书和背景颜色

WM_VSCROLLCLIPBOARD= 778

错开主旨

当用户选用窗口菜单的一条命令或当用户挑选最大化或不大化时这么些窗口会吸纳此音讯

此音讯文告某个窗口,非客户区正在销毁

//双击鼠标中键

一个DDE服务程序提交此音讯给DDE客户程序来传递个一数额项给客户或通告客户的一条可用数据项

MFC新闻的拍卖落成格局
  初看MFC中的各个信息,以及在脑子中牢固的C++的影响,大家可能很自然的就会想到利用C++的三大特色之一:虚拟机制来促成新闻的传递,可是通过分析,大家看来工作并不是想大家想像的那么,在MFC中音讯是经过一种所谓的新闻映射机制来拍卖的。
  为啥吧?在潘爱民先生翻译的《Visual
C++技术内幕》(第4版)中付出了详尽的原故表达,我再一句话来说一次。在CWnd类中大概有110个音信,还有此外的MFC的类呢,算起来信息太多了,在C++中对先后中用到的每一个派生类都要有一个vtable,每一个虚函数在vtable中都要占有一个4字节大小的输入地址,那样一来,对于每个特定类型的窗口或控件,应用程序都亟待一个440KB大小的表来接济虚拟新闻控件函数。
  即便说下边的窗口或控件可以勉强已毕的话,那么对于菜单命令音讯及按钮命令音讯啊?因为分化的应用程序有区其余菜谱和按钮,我们怎么处理吧?在MFC
库的那种音讯映射系统就防止了利用大的vtable,并且可以在拍卖正常Windows音讯的还要处理丝丝缕缕的应用程序的授命消息。
  说白了,MFC中的音讯机制其实质是一张高大的新闻及其处理函数的依次对应表,然后加上分析处理这张表的应用框架之中的有些顺序代码.那样就可以幸免在SDK编程中用到的繁琐的CASE语句。

WM_DDE_INITIATE =WM_DDE_FIRST + 0

发送此音讯来废除某种正在展开的摸态(操作)

程序发送此新闻给editcontrol或combobox从剪贴板中获得数码

L B N _ S E L C H AN G E拔取了另一项

WM_PAINT = 15

WM_IME_COMPOSITION= 271

WM_RBUTTONUP = 517

当某个用户裁撤程序日志激活状态,提交此音讯给程序

TMsg = packedrecord

消息范围

说 明

0 ~ WM_USER – 1

系统消息

WM_USER ~ 0x7FFF

自定义窗口类整数消息

WM_APP ~ 0xBFFF

应用程序自定义消息

0xC000 ~ 0xFFFF

应用程序字符串消息

> 0xFFFF

为以后系统应用保留

WM_MDIICONARRANGE =552

WM_SETREDRAW = 11

WM_CHANGECBCHAIN =781

图片 67while(GetMessage(&msg, NULL, 0, 0))
图片 68{
图片 69       if(!TranslateAccelerator(msg.hWnd, hAccelTable, &msg))
图片 70      { 
图片 71            TranslateMessage(&msg);
图片 72            DispatchMessage(&msg);
图片 73       }
图片 74}

WM_MENUCOMMAND =294

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

转载:

当剪贴板包含CF_OWNERDIPLAY格式的数量同时剪贴板观看窗口的客户区需求重画;

图片 75   #define HANDLE_MSG(hwnd,msg,fn) \
图片 76             switch(msg): return HANDLE_##msg((hwnd),(wParam),(lParam),(fn));

WM_QUIT = 18

当一个应用程序正要落实它的逻辑调色板时发此音讯通告所有的应用程序

发表评论

电子邮件地址不会被公开。 必填项已用*标注