【问题标题】:Can WM_NEXTDLGCTL be used with non-dialog windows?WM_NEXTDLGCTL 可以与非对话框窗口一起使用吗?
【发布时间】:2015-07-29 16:16:30
【问题描述】:

WM_NEXTDLGCTL 的文档指出,此消息将与对话框一起使用:

发送到对话框过程以将键盘焦点设置到对话框中的不同控件。

如果此消息不能与非对话框控件父级一起使用,则以通用方式子类化控件将非常乏味(如this question 所示),因为窗口过程必须调用SetFocus 或发送WM_NEXTDLGCTL 消息,基于不太容易确定上下文。

由于其他特定于对话框的 API 可用于非对话框窗口(例如 IsDialogMessage),因此在此设置中也可以使用 WM_NEXTDLGCTL 感觉很自然。

问题:WM_NEXTDLGCTL 可以与非对话控制父母一起使用吗?

【问题讨论】:

    标签: c++ c user-interface winapi


    【解决方案1】:

    WM_NEXTDLGCTL 可以与非对话框控件父级一起使用吗?

    我不认为你可以在非对话框父窗口中使用它(至少对父窗口没有更改),原因是它在DefDlgProc 内部实现。因此,您的其他非对话框窗口必须调用它才能使此消息起作用。

    这是我在 The Old New Thing: Practical Development Through the Evolution of Windows 中找到的引述:DefDlgProc 内部发生了什么?

    正如 WM_NEXTDLGCTL 消息的注释所观察到的,DefDlgProc 函数通过更新所有内部对话管理器簿记来处理 WM_NEXTDLGCTL 消息,决定哪个按钮应该是默认按钮,所有这些都是好事。

    它是仅对话框消息的另一个原因是它(来自 msdn 的 WM_NEXTDLGCTL 引用):

    设置默认控件标识符

    为此它必须发送DM_SETDEFID,其定义为:

    #define DM_SETDEFID         (WM_USER+1)
    

    所以它是 WM_USER,因此它可能用于非对话窗口的其他目的(Raymond Chens 书中也提到了这一事实)。有趣的是,根据这本书IsDialogMessage 也将 DM_SETDEFID/DM_GETDEFID 发送到您的窗口。因此,如果你想在非对话窗口中使用类似 TAB 的导航(使用对话代码),你必须遵守一些规则,你可以在里面阅读它们:What happens inside IsDialogMessage? 上面的书。这意味着使用以下消息循环:

    while (GetMessage(&msg, NULL, 0, 0)) {
        if (IsDialogMessage(hwnd, &msg)) {
            /* Already handled by dialog manager */
        } else {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    

    因此,如果您不想对父 Windows 代码进行重大更改,那么恐怕您就不走运了。

    【讨论】:

    • 这听起来很有说服力,尤其是当涉及到窗口类私人消息 (WM_USER+x) 时。尽管如此,DM_SETDEFID 的文档仍然指出:“要设置默认按钮,该函数可以将 WM_GETDLGCODEBM_SETSTYLE 消息发送到指定的控件和当前默认按钮。” 所以理论上,DM_SETDEFID 不是严格要求的。虽然我认为您是正确的,但推理仍有一点差距。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2013-03-19
    • 1970-01-01
    • 2012-01-19
    • 2010-09-09
    • 2017-07-22
    相关资源
    最近更新 更多