从 parent 的 wndproc 访问特定 child window 的最佳实践

Best practice for accessing a specific child window from the parent's wndproc

我将 运行 保留在这样的场景中,从 parent window 的 wndproc 函数,我必须修改 child window(例如:单击 child 按钮添加到同级组合框;向 parent 发送消息,然后将其转发到适当的 child)。据我所知,这意味着以某种方式获取 child 的 HWND 引用并使用该引用调用 child 的 wndproc。

在这种情况下,我有 child 的 child-window-identifier,我有 parent window 的 HWND 参考,但没有别的。

从各种教程来看,我唯一的选择似乎是将 child 的 HWND 引用保存为全局引用,以便我可以从 parent 的 wndproc 函数访问它,或者调用 EnumChildWindows() 并在开头有一个 switch 语句,如果当前 child 不是目标 child,则立即 returns:前者似乎无法很好地扩展,因为我为每个 child 保存一个全局,我也需要发言;后者似乎旨在向所有 children 广播,而不是针对单个特定的 child.

感觉 好像有一个函数需要 parent 的 HWND 和 child 的 child-windows-identifier 和 returnschild的HWND,但无论我怎么google,好像都没有这个功能。

简而言之,我知道有几种方法可以解决我的问题,但我有一种直觉,我做错了什么。给定 parent 的 HWND 引用,best-practice 对 child window 执行操作的方法是什么?

大多数基于 WM_NOTIFY or WM_COMMAND, which includes BN_CLICKED 的通知带有 child 的 HWND 以及 child 的 ID,例如:

WM_NOTIFY

wParam

The identifier of the common control sending the message. This identifier is not guaranteed to be unique. An application should use the hwndFrom or idFrom member of the NMHDR structure (passed as the lParam parameter) to identify the control.

lParam

A pointer to an NMHDR structure that contains the notification code and additional information. For some notification messages, this parameter points to a larger structure that has the NMHDR structure as its first member.

WM_COMMAND

wParam

The LOWORD contains the button's control identifier. The HIWORD specifies the notification code.

lParam

A handle to the button.

所以,在parent window的消息过程中,它确切地知道哪个child正在向它发送通知,并且可以直接访问那个child .

在您希望 parent 的消息处理程序作用于 另一个 child 的情况下(即,将字符串添加到 ComboBox来自 Button 的点击处理程序),应该已经有其他 child 的 HWND 或您最初创建 child.

时的 ID

前一种情况,可以使用保存的HWNDas-is,eg:

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() 获取 child 的 HWND,给定它在 parent window 中的 ID,例如:

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;