(最后一行有一个TL; DR)
我正在实现一个处理程序,以关闭在软件应用程序中打开的选定窗口。这是一个粗略的代码:
void CDlg_Dummy_Dialog::OnCloseWindows()
{
for (int i = 0; i < m_WindowsInfo.size(); i++) {
Window_Node *pWN = &m_WindowsInfo.at(i);
if (pWN->checked && IsWindow(pWN->pWnd->GetSafeHwnd())) {
pWN->pWnd->GetParentFrame()->SendMessage(WM_CLOSE);
}
}
}
这是上面显示的参数的一些声明:
struct Window_Node {
CString name;
CString path;
CWnd *pWnd;
BOOL checked;
HICON icon;
....
};
class CDlg_Dummy_Dialog : public CDialog {
...
protected:
std::vector<struct Window_Node> m_WindowsInfo;
...
}
另外,可能存在多个
Window_Node
实例,这些实例具有不同的pWnd
参数,这些实例源自单个CDocument
类(即,存在不同类型的窗口来显示文档的不同显示)。对于此软件,如果关闭了文档的第一个窗口(在图中始终为“绿色”窗口类型),则与此文档关联的所有其他窗口将自动关闭。这是发生问题的地方。
如果用户从同一文档中选择了多个窗口(其中有一个绿色窗口),则它将在完成第一次迭代时关闭所有窗口,并且所有
pWnd
指针现在都指向一个尚未分配的内存。因此,当它尝试在下一次迭代中调用GetSafeHwnd()
时,会提示一个存储器访问冲突错误:First-chance exception at 0x00000000521B4AD0 (mfc100d.dll) in Settle3D.exe: 0xC0000005: Access violation reading location 0x00000000136943E0.
Unhandled exception at 0x00000000521B4AD0 (mfc100d.dll) in Settle3D.exe: 0xC000041D: An unhandled exception was encountered during a user callback.
我知道,简单的解决方法是沿相反的方向迭代 vector 。但是,我也尝试将此方法集成到其他几个软件上,并且它们不一定以相同的方式组织窗口。
因此,经过上述漫长的问题,这是TL; DR:
是否可以检查CWnd *实例是否指向有效窗口?
最佳答案
一种可能性是从您的主窗口开始,如果发现有问题的HWND,则在子窗口中递归搜索。
使用CWnd::GetWindow(GW_CHILD)
获取第一个 child ,使用CWnd::GetWindow(GW_HWNDNEXT)
获取下一个窗口。