Duilib 源码分析之消息流程篇

来源:互联网 发布:人工智能眼部疾病治疗 编辑:程序博客网 时间:2024/06/06 17:55

Duilib 中的消息处理过程:

我们首先从窗口的创建开始,RegisterWindowClass 时注册了消息处理函数 CWindowWnd::__WndProc,在 CreateWindowEx 创建窗口之后,除了 WM_NCCREATEWM_NCDESTROY 之外的消息都由 LRESULT WindowImplBase::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) 进行处理,最关键的一步是 WM_CREATE 对应的 OnCreate 函数,在 OnCreate 中初始化 CPaintManagerUI ,读取 xml 初始化所有的 CControlUI, xml 这部分内容可以参考之前的 Blog : Duilib 源码分析之 xml 加载篇 和 Duilib 源码分析之 xml 解析篇

下一步,在 HandleMessage 中屏蔽了非客户区的绘制,Duilib 绘制的只有客户区,所谓的标题栏都是在客户区进行自绘的。

  • OnNcCalcSizeOnNcPaint 屏蔽了非客户区
  • OnNcHitTest 实现了普通窗口在非客户区边缘鼠标可拖拽改变窗口大小的功能和拖动标题栏移动窗口的功能,主要是通过控制返回值来实现的

下一步就是调用 static void CPaintManagerUI::MessageLoop() 首先进行消息的过滤,未处理的消息再发送给窗口。
static void CPaintManagerUI::MessageLoop(), 核心是调用 GetMessage 读取消息,读取到消息后,首先调用 bool CPaintManagerUI::TranslateMessage(const LPMSG pMsg) 进行处理,若没有进行处理,则调用默认的消息处理。

bool CPaintManagerUI::TranslateMessage(const LPMSG pMsg) 的处理过程中,分为窗口是否是有 WS_CHILD 样式,处理过程稍有不同,但都是要找到当前消息对应的窗口的 CPaintManagerUI,然后进行以下两项处理:

  1. bool CPaintManagerUI::TranslateAccelerator(LPMSG pMsg) 目前只有 CWebBrowserUI 需要进行这种处理(在控件创建后通过 GetManager()->AddTranslateAccelerator(this)添加到需要处理 TranslateAccelerator 的列表中),最终会调用到 HRESULT CComPtr<IOleInPlaceActiveObject>::TranslateAccelerator(MSG* pMsg), 作用是将 WM_KEYDOWNWM_SYSKEYDOWN 翻译为 WM_COMMANDWM_SYSCOMMAND 然后再发送给窗口
  2. bool PreMessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes) 处理键盘事件
    • 首先遍历 m_aPreMessageFilters 调用 MessageHandler 处理键盘事件,默认 m_aPreMessageFilters 会添加 WindowImplBase, 在当前版本的 duilib 中并没有在这个函数中屏蔽 VK_RETURNVK_ESCAPE
    • 继续处理 VK_TAB, 若当前焦点所在控件是 CRichEditUI 且在输入状态下不希望通过 tab 改变焦点 (IsWantTab() == true) 或当前焦点所在控件是 WkeWebkitUI ,也不进行焦点控件的切换。 否则则找下一个控件 SetFocus (Shift 按下时找上一个)
    • WM_SYSCHAR 处理快捷键,很多时候我们都会为按钮或者菜单项加快捷键 (ALT+自定义按键),找到对应的控件后执行对应的响应函数

上述过程未处理的情况下,消息会发送到各自的窗口进行处理,这部分的处理也分为三种情况:

  1. 用户自定义消息:需要重载 LRESULT WindowImplBase::HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled), 处理后把 bHandled 设置为 true 可以防止消息继续走默认的处理函数
  2. bool CPaintManagerUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes) 处理的消息,这部分内容是 Duilib 中最为核心的处理内容
  3. 通过 DefWindowProc 执行默认消息处理
原创粉丝点击