跟踪打开的 child 个对话框

Keeping track of open child dialogs

在 C++ 程序 (embarcadero XE2, vcl) 中,我想将 window-messages 从 parent 发送到所有 child windows。 为此,我注册了一个 window 消息,在所有句柄的循环中使用 PostMessage(handle,msg,wparam,lparam) 发送消息,并在每个对话框中使用 WndProc(TMessage& Message).

接收它

我的问题是跟踪打开的 window 句柄。由于大多数对话框都是通过 Show() 打开的,因此多个对话框可以同时 运行。

到目前为止,我使用 std::vector<HWND> 来存储 Window-Handles。但是,这将需要我跟踪哪个句柄一次仍然有效。 我可以通过向对话框添加一个 onClose 处理程序来解决这个问题,并使用对话框的句柄作为参数在主线程中调用一个过程,这样它就可以从向量中删除...

是否有更好的解决方案,如 Application.OpenForms (.NET) 中的 self-updating 列表?或者也许是从主对话框通知 child-dialog 事件的更好方法?

A window 已经在内部跟踪其 children,因此您只需要利用它。如果你想向所有window的childwindows发送消息,那么你只需要递归遍历所有window的[=33] =]ren,发信息给大家

起点是GetTopWindow function, which returns the child window at the top of the Z order. Then, you iterate through the child windows by calling the GetNextWindow function

MFC 实际上包含一个执行此操作的方法,称为 SendMessageToDescendants。如果您更喜欢这些语义,您可以自己编写等价物,并将 SendMessage 替换为 PostMessage

void PostMessageToDescendants(HWND   hwndParent,
                              UINT   uMsg,
                              WPARAM wParam,
                              LPARAM lParam,
                              BOOL   bRecursive)
{
   // Walk through all child windows of the specified parent.
   for (HWND hwndChild = GetTopWindow(hwndParent);
        hwndChild     != NULL;
        hwndChild      = GetNextWindow(hwndChild, GW_HWNDNEXT))
   {
      // Post the message to this window.
      PostMessage(hwndChild, uMsg, wParam, lParam);

      // Then, if necessary, call this function recursively to post the message
      // to all levels of descendant windows.
      if (bRecursive && (GetTopWindow(hwndChild) != NULL))
      {
         PostMessageToDescendants(hwndChild, uMsg, wParam, lParam, bRecursive);
      }
   }
}

参数与 PostMessage 函数相同,除了最后一个:bRecursive。此参数的含义正如其名称所暗示的那样。如果 TRUE,child windows 的搜索将是 递归 ,这样消息将被发布到 parent 的所有后代] window(其children,其children的children等)。如果 FALSE,该消息将只发布到其直接 children.

Cody Gray 对我提出的问题给出了正确的解决方案。

但是,如评论所示,我问错了问题。

我的对话框是 vcl TForms,由 Owl TWindow 打开,这意味着我使用对话框的 ParentWindow 属性 来获取模态外观:

__fastcall TMyDialog::MyDialog(owl::TWindow* Owner) :TForm(HWND(NULL)){
    tf = new TForm(Owner->Handle); //TForm*, Mainwindow calls this dialog
    tf->ParentWindow = Owner->Handle; // workaround: owl calls vcl
    this->PopupParent = tf; // workaround: owl calls vcl
}

因此,结果很可能是子对话和自有对话的混合体。

我将 Window 消息发送到从主 window 打开的所有对话框的原因是:

struct checkMSG{
    HWND handle; UINT msg; WPARAM wparam; LPARAM lparam;
};
checkMSG msgCheck;

BOOL CALLBACK enumWindowsProc(__in  HWND hWnd,__in  LPARAM lParam) {
     HWND owner= ::GetParent(hWnd);
     if(owner==msgCheck.handle)
        ::PostMessage(hWnd, msgCheck.msg, msgCheck.wparam, msgCheck.lparam);
     return TRUE;
}

void SendToAllWindows(HWND handle, UINT msg, WPARAM wparam, LPARAM lparam){
    msgCheck.handle=::GetParent(handle);
    msgCheck.msg=msg;
    msgCheck.wparam= wparam;
    msgCheck.lparam= lparam;
    BOOL enumeratingWindowsSucceeded = ::EnumWindows( enumWindowsProc, NULL );
}
  • EnumWindows 迭代所有应用程序中的所有 windows。
  • 为了确保只获取我自己的应用程序 window 的句柄,我使用了一个变量 msgCheck 来存储顶层句柄和我要发送的消息。
  • 现在我使用 GetParent 检索 Owner 或 Parent 或 returns NULL(如果两者都未找到)。
  • 在回调函数中,将存储的顶层句柄与找到的 window 的顶层句柄进行比较,如果它们匹配,window 消息将发送到找到的 window'句柄