首页 > 解决方案 > 从父级的 wndproc 访问特定子窗口的最佳实践

问题描述

我经常遇到这样的情况,从父窗口的 wndproc 函数,我必须修改子窗口(例如:单击子按钮添加到同级组合框;向父级发送消息,然后将其转发给相应的子级)。据我所知,这意味着以某种方式获取孩子的 HWND 引用并使用该引用调用孩子的 wndproc。

在这种情况下,我有孩子的子窗口标识符,我有父窗口的 HWND 引用,但没有别的。

从各种教程中,看起来我唯一的选择是将子的 HWND 引用保存为全局,以便我可以从父的 wndproc 函数访问它,或者调用 EnumChildWindows() 并在开头有一个 switch 语句,如果当前孩子不是目标孩子:前者似乎不能很好地扩展,因为我正在为每个我需要说话的孩子保存一个全局;后者似乎旨在向所有儿童广播,而不是与单个特定儿童交谈。

觉得必须有一个函数接受父母的 HWND 和孩子的子窗口标识符并返回孩子的 HWND,但无论我如何谷歌,似乎都不存在这样的函数。

简而言之,我知道几种解决问题的方法,但我有一种直觉,我做错了什么。给定父窗口的 HWND 引用,在子窗口上执行操作的最佳实践方法是什么?

标签: c++winapivisual-studio-2017

解决方案


大多数基于WM_NOTIFYor的通知WM_COMMAND,包括BN_CLICKED,都带有HWND孩子的 ID 以及孩子的 ID,例如:

WM_NOTIFY

参数

发送消息的公共控件的标识符。不保证此标识符是唯一的。应用程序应使用结构的hwndFromoridFrom成员NMHDR(作为lParam参数传递)来标识控件。

参数

指向NMHDR包含通知代码和附加信息的结构的指针。对于某些通知消息,此参数指向一个较大的结构,该NMHDR结构作为其第一个成员。

WM_COMMAND

参数

LOWORD 包含按钮的控件标识符。HIWORD 指定通知代码。

参数

按钮的句柄。

因此,在父窗口的消息过程中,它确切地知道哪个子窗口正在向它发送通知,并且可以直接访问那个子窗口。

如果您希望父级的消息处理程序作用于另一个子级(即,从按钮的单击处理程序中将字符串添加到组合框),则应该HWND在您最初创建子级时已经具有该其他子级的 ID 或 ID。

在前一种情况下,您可以按原样使用保存HWND的内容,例如:

HWND hwndCB;
HWND hwndBtn;

...

case WM_CREATE:
    hwndCB = CreateWindow(WC_COMBOBOX, ..., hWnd, ...);
    hwndBtn = CreateWindow(WC_BUTTON, ..., hWnd, ...);
    break;

case WM_COMMAND:
    if (HIWORD(wParam) == BN_CLICKED) &&
        HWND(lParam) == hwndBtn)
    {
        SendMessage(hwndCB, CB_ADDSTRING, 0, ...);
    }
    break;

在后一种情况下,您可以使用在父窗口GetDlgItem()中获取孩子的ID,例如:HWND

case WM_CREATE:
    CreateWindow(WC_COMBOBOX, ..., hWnd, (MENU)ID_MY_COMBO, ...);
    CreateWindow(WC_BUTTON, ..., hWnd, (HMENU)ID_MY_BTN, ...);
    break;

case WM_COMMAND:
    if (HIWORD(wParam) == BN_CLICKED) &&
        LOWORD(wParam) == ID_MY_BTN)
    {
        HWND hwndCB = GetDlgItem(hWnd, ID_MY_COMBO);
        SendMessage(hwndCB, CB_ADDSTRING, 0, ...);
    }
    break;

推荐阅读