跟踪打开的 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'句柄
在 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'句柄