跟踪打开的子对话



在C++程序(embarcadero XE2,vcl)中,我想将窗口消息从父窗口发送到所有子窗口。 为此,我注册了一个 windowMessage,在所有句柄的循环中发送带有PostMessage(handle,msg,wparam,lparam)的消息,并在每个带有WndProc(TMessage& Message)的对话框中接收它。

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

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

是否有更好的解决方案,例如Application.OpenForms(.NET) 中的自我更新列表?或者也许是从主对话通知子对话事件更好的方法?

窗口已经在内部跟踪其子窗口,因此您只需要利用它即可。如果要将消息发送到窗口的所有子窗口,则只需递归遍历该窗口的所有子窗口,并将消息发送到每个子窗口。

起点是GetTopWindow函数,该函数返回位于 Z 顺序顶部的子窗口。然后,通过调用GetNextWindow函数循环访问子窗口。

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

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,则子窗口的搜索将是递归的,以便将消息发布到父窗口的所有后代(其子窗口、子窗口的子窗口等)。如果FALSE,则消息将仅发布到其直接子级。

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

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

我的对话框是 vclTForms由 OwlTWindow打开的,这意味着我使用对话框的 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
}

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

对我有用的是将窗口消息发送到从主窗口打开的所有对话框:

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 遍历所有应用程序中的所有窗口。
  • 为了确保只获取我自己应用程序的窗口句柄,我使用了一个变量msgCheck来存储顶级句柄和我要发送的消息。
  • 现在我使用GetParent它检索所有者或父级,或者在都找不到时返回 NULL。
  • 在回调函数中,将存储的顶级句柄与找到的窗口的顶级句柄
  • 进行比较,如果它们匹配,则窗口消息将发送到找到的窗口的句柄

相关内容

  • 没有找到相关文章

最新更新