您的位置 首页 > 数码极客

如何给父窗口的父窗口发送消息

问题

今天我们来聊一聊Windows里比较少用到的两个消息:

WM_UPDATEUISTATE和WM_CHANGEUISTATE。

写这篇文章的原因,也是因为在开发中碰到一个界面绘制的问题,后来发现这个问题和这两个消息有关,当然了,这个问题在这里就不详细展开了,我可能会在另一篇文章里再写。

在讲述这两个消息之前,我先介绍一个概念:keyboard cues。我就先将它翻译成”键盘指示器”吧。

我们打开电脑的计算器程序,然后按下键盘的Alt按键,可以观察到计算器程序的菜单栏出现了两个变化:

1) 当前活动的菜单项被一个矩形框所包围

2) 所有菜单项文字中括号里的字母出现了下划线标识。

如下图所示:

那么,这里出现的矩形框和下划线,就是所谓的keyboard cues了,也叫做:keyboard indicator。

MSDN的解释

我们先来看看这两个消息的WPARAM参数在MSDN中的解释:

这个32位的WPARAM被分为两部分:Low-order word 和 High-order word。

这里你会感觉有一种双重否定的味道:

如果希望显示矩形框,则需要设置WPARAM为:UIS_CLEAR + UISF_HIDE­FOCUS。

如果希望隐藏下划线,则需要设置WPARAM为:UIS_SET + UISF_HIDEACCEL。

WM_QUERY­UI­STATE

这里再提一下WM_QUERY­UI­STATE这个消息,因为每个窗口结构会有一个内部成员记录着keyboard indicator的显示状态,所以我们可以使用这个消息来获取指定窗口的keyboard indicator的显示状态。

WM_CHANGEUISTATE消息

当一个窗口希望能改变和它在同一个窗口级别的所有子窗口的keyboard indicator的显示状态时(这句话有点长,需要好好理解),这个窗口可以向它自身或者它的父窗口发出此消息。WM_CHANGEUISTATE消息将由子窗口向父窗口层层向上传递,父窗口会查看消息里的WPARAM,如果窗口当前的状态和WAPRAM参数要求的是一致的时候,消息传递中止。如果发现不一致,则父窗口会继续向上传递,直至消息到达top-level窗口。

当top-level窗口收到此消息时,表明当前窗口的状态确实需要更新,所以top-level窗口会首先向它自身发出WM_UPDATEUISTATE消息,系统会完成要求的界面状态变更,然后将WM_UPDATEUISTATE消息层层向下传播至所有的子窗口。

WM_UPDATEUISTATE消息

当一个窗口收到WM_UPDATEUISTATE消息时,表明此时窗口需要进行界面更新了,系统会根据WPARAM的要求完成keyboard indicator的显示或者隐藏,值得注意的是,此消息在本窗口完成处理后,还会被广播到此窗口的所有子窗口。这样,就可以保持各层级窗口的界面显示一致性。

实例讲解

我们使用一个简单的例子来讲解以上的内容。设想有三个窗口,一个父窗口P,它有两个子窗口C1和C2。在初始状态下,所有窗口的keyboard indicator都是隐藏状态,也即UISF_HIDEACCEL和UISF_HIDEFOCUS都为SET状态(想想双重否定),如下图所示:

当用户按下Alt按键,用户预期窗口F的菜单项显示矩形框,如果此时窗口C1拥有输入焦点,则它会向它自身发出WM_CHANGE­UI­STATE消息,消息的WPARAM参数会设置为:UIS_CLEAR + UISF_HIDE­FOCUS。

窗口C1收到WM_CHANGE­UI­STATE消息后,发现当前窗口状态和WPARAM要求的不一致,它会继续向它的父窗口(F)发送WM_CHANGE­UI­STATE消息。

当父窗口F收到WM_CHANGE­UI­STATE消息时,因为它已经是top-level窗口了,所以它不再向上传递此消息。它会将收到WM_CHANGE­UI­STATE消息转化为WM_UPDATE­UI­STATE消息,并首先发送给自身。当收到WM_UPDATE­UI­STATE消息后,父窗口F完成界面更新(显示矩形框)并继续将WM_UPDATE­UI­STATE消息向下传递至它的两个子窗口(C1和C2)。C1和C2收到WM_UPDATE­UI­STATE消息后,也会分别完成各自的界面更新,因为它们都没有子窗口了,至此WM_UPDATE­UI­STATE消息处理完毕。状态变化如下图所示:

通过以上一系列的消息路由过程,我们可以通过发送WM_CHANGE­UI­STATE消息的方式来向整个窗口树广播我们的意图(显示或隐藏keyboard indicator),进行实现统一的界面展示效果。

总结

1) 目前,随着Windows 10的推出,我们已经越来越少用到keyboard indicator这个特性了,因为大部分时候,鼠标操作比键盘操作更方便。但也存在一些比较特殊的情况(你的鼠标被人拿了),那么使用键盘的Alt按键激活keyboard indicator,就可以实现菜单的选择以及输入焦点的切换了。

2) 探究WM_UPDATEUISTATE和WM_CHANGEUISTATE这两个消息,有助于我们理解Windows图形界面的绘制原理和底层设计意图。虽然有点绕弯,但是还是挺值得了解一下的。

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“如何给父窗口的父窗口发送消息”边界阅读