快捷搜索:

WPF的消息机制(二)- WPF内部的5个窗口之隐藏消

WPF内部的5个窗口

对付Windows系统来说,它是一个消息系统,消息系统的核心便是窗口。对付WPF来说也是如斯。那么WPF内部为什么必要窗口,又存在哪些窗口呢?

在上一篇,我们频繁的说起“线程”,“Dispatcher”着实,运行WPF利用法度榜样所在的线程便是WPF所谓的UI线程,在Application.Run之后,调用Dispatcher.Run时会反省当火线程是否已经存在了一个Dispatcher工具,假如没有就构造一个,在这里,一个线程对应一个Dispatcher。是以,WPF的工具在获取this.Dispatcher属性时,不合工具取的都是同一个Dispatcher实例。别的,前面提到的“消息轮回”,“消息行列步队”等都是Win32利用法度榜样的观点,我们知道,提起这些观点,一定会跟Win32的“窗口”,“Handle”,“WndProc”之类的观点离不开,那么WPF里面究竟有没有“窗体”,“Handle”,“WndProc”呢?

我想说的是:有,还不止一个,只不过没有裸露出来,外貌不必要关心这些。

平日环境下,一个WPF利用法度榜样在运行起来的时刻,后台会创建5个Win32的窗口,赞助WPF系统来处置惩罚操作系统以及利用法度榜样内部的消息。在这5个窗口中,只有一个是可见的,可以处置惩罚输入事故与用户交互,其他4个窗口都是弗成见的,赞助WPF处置惩罚来自其他方面的消息。接下来我会来先容究竟这5个Win32的窗口若何赞助WPF处置惩罚消息,我会根据每个窗口创建的顺序来先容。

暗藏消息窗口

创建机会:在Application的构造函数调用基类DispatcherObject的构造函数的时刻,会创建一个Dispatcher工具,在Dispatcher的私有构造函数傍边。

用途:实现WPF线程模型的异步调用。

谈到异步调用,信托许多人都不陌生。WinForm下,我们平日为了使一些花费较多光阴的措施调用不影响UI的相应,会将这个操作分为很多步,然后应用BeginInvoke调用每一步,这样UI相应就不会被壅闭。BeginInvoke的本色是往消息行列步队傍边PostMessage,而不是直接调用,与此同时,UI行径(MouseMove)导致系统也往消息行列步队傍边PostMessage更新UI,但因为彼此花费的光阴很短,就感到两个消息是被同时处置惩罚似的,界面就不会感觉被壅闭了。WPF同样面临这样的问题,他是若何办理的呢?在这里Window 1#起着至关紧张的感化。经由过程下面一副图我们来看看Window 1#在做什么工作?

WPF也是经由过程BeginInvoke来办理的,而Wpf的BeginInvoke是在Dispatcher上面裸露了,由于全部消息系统都是Dispatcher在和谐。从上面图可以看出Dispatcher在调用BeginInvoke之后所经历的流程,终极是什么时刻Foo()被真正履行的。

第一步,便是将调用的Delegate和优先级包装成一个DispatcherOperation放入Dispatcher掩护的优先级行列步队傍边,这个Queue是按DispatcherPriority排序的,老是高优先级的DispatcherOperation先被处置惩罚。关于优先级相关常识可以参考MSDN对WPF线程模型的解释。

第二步,往当火线程的消息行列步队傍边Post一个名为MsgProcessQueue的Message。这个消息是WPF自己定义的,见Dispatcher的静态构造函数傍边的

_msgProcessQueue = UnsafeNativeMethods.RegisterWindowMessage("DispatcherProcessQueue");

这个消息被Post到消息行列步队之前,还要设置MSG.Handle,这个Handle便是Window 1#的Handle。指定Handle是为了在消息轮回Dispatch消息的时刻,指定哪个窗口的WndProc(窗口历程)处置惩罚这个消息。在这里所有BeginInvoke引起的消息都是Window1#的窗口历程来处置惩罚的。

第三步,消息轮回读取消息。

第四步,系统根据获取消息的Handle,发明跟Window1#的Handle相同,那么这个消息派发到Window1#的窗口历程,让其处置惩罚。

第五步,在窗口历程中,优先级行列步队傍边取一个DispatcherOperation。

第六步,履行DispatcherOperation.Invoke措施,Invoke措施的核心便是调用DispatcherOperation构造时传入的Delegate,也便是Dispatcher.BeginInvoke传入的Delegate。终极这个Foo()措施就被履行了。

经由过程上面的六步历程,一次Dispatcher.BeginInvoke就被处置惩罚完成。而这个历程必要消息赓续的流动,就必须加入消息行列步队,着末还要特定的窗口历程处置惩罚,而核心的器械便是这个暗藏的Window1#,他在WPF傍边只认真处置惩罚异步调用,其他的消息他不关心,残剩的4个窗口在处置惩罚。这个Window1#在WPF傍边被包了一层壳子,假如感兴趣,你可以去查看类型MessageOnlyHwndWrapper。

转自:http://www.cnblogs.com/powertoolsteam/archive/2010/12/31/1922794.html

您可能还会对下面的文章感兴趣: