问】 如何在MDI环境下枚举所有打开的窗口? 答】 In MFC, each CMDIChildWnd created by the framework is managed as a child window of the MDIClient window. This MDIClient window is a child of the mainframe window and fills its client area. For MDI applications, the mainframe window is encapsulated by the CMDIFrameWnd class. This class has a public embedded HWND member (m_hWndMDIClient), which is the handle to the MDIClient window. For MDI applications, AppWizard derives the CMainFrame class from CMDIFrameWnd.The MDIClient maintains an internal list of child windows. In an MFC application, these child windows are either a CMDIChildWnd object or an internal window used to display the title of an iconized window. Note that this is an internal list controlled by Windows; don't make assumptions about the ordering of children in the list after an API function is called. //**mainfrm.h*************************************************** class CMainFrame : public CMDIFrameWnd { ... public: CWnd m_wndMDIClient; CWnd* m_pWndCurrentChild; CMDIChildWnd* GetNextMDIChildWnd(); int GetCountCMDIChildWnds(); ... }//**mainfrm.cpp************************************************** CMainFrame::CMainFrame():m_pWndCurrentChild(NULL) { //................. }CMainFrame::~CMainFrame() { m_wndMDIClient.Detach(); //................. }int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (m_wndMDIClient.Attach(m_hWndMDIClient) == 0) { TRACE0("Failed to attach MDIClient.\n"); return -1; // fail to create } //................. }//---------------------------------------------------------------- // This function finds the CMDIChildWnd in the list of windows // maintained by the application's MDIClient window following the // one pointed to by the member variable m_pWndCurrentChild. If no // further CMDIChildWnds are in the list, NULL is returned. //----------------------------------------------------------------CMDIChildWnd* CMainFrame::GetNextMDIChildWnd() { if (!m_pWndCurrentChild) { // Get the first child window. m_pWndCurrentChild = m_wndMDIClient.GetWindow(GW_CHILD); } else { // Get the next child window in the list. m_pWndCurrentChild= (CMDIChildWnd*)m_pWndCurrentChild->GetWindow(GW_HWNDNEXT); } if (!m_pWndCurrentChild) { // No child windows exist in the MDIClient, // or you are at the end of the list. This check // will terminate any recursion. return NULL; } // Check the kind of window if (!m_pWndCurrentChild->GetWindow(GW_OWNER)) { if (m_pWndCurrentChild-> IsKindOf(RUNTIME_CLASS(CMDIChildWnd))) { // CMDIChildWnd or a derived class. return (CMDIChildWnd*)m_pWndCurrentChild; } else { // Window is foreign to the MFC framework. // Check the next window in the list recursively. return GetNextMDIChildWnd(); } } else { // Title window associated with an iconized child window. // Recurse over the window manager's list of windows. return GetNextMDIChildWnd(); } }//----------------------------------------------------------------- // This function counts the number of CMDIChildWnd objects // currently maintained by the MDIClient. //-----------------------------------------------------------------int CMainFrame::GetCountCMDIChildWnds() { int count = 0; CMDIChildWnd* pChild = GetNextMDIChildWnd(); while (pChild) { count++; pChild = GetNextMDIChildWnd(); } return count; }
don't make assumptions about the ordering of children in the list after an API function is called. 最后这句话的意思是什么? 是说所有的子窗口和内部窗口没有固定的顺序在窗口管理列表里面吗?
尝试使用这个: BOOL EnumChildWindows( HWND hWndParent, // handle to parent window WNDENUMPROC lpEnumFunc, // callback function LPARAM lParam // application-defined value );
答】
In MFC, each CMDIChildWnd created by the framework is managed as a child window of the MDIClient window. This MDIClient window is a child of the mainframe window and fills its client area. For MDI applications, the mainframe window is encapsulated by the CMDIFrameWnd class. This class has a public embedded HWND member (m_hWndMDIClient), which is the handle to the MDIClient window. For MDI applications, AppWizard derives the CMainFrame class from CMDIFrameWnd.The MDIClient maintains an internal list of child windows. In an MFC application, these child windows are either a CMDIChildWnd object or an internal window used to display the title of an iconized window. Note that this is an internal list controlled by Windows; don't make assumptions about the ordering of children in the list after an API function is called. //**mainfrm.h***************************************************
class CMainFrame : public CMDIFrameWnd
{
...
public:
CWnd m_wndMDIClient;
CWnd* m_pWndCurrentChild;
CMDIChildWnd* GetNextMDIChildWnd();
int GetCountCMDIChildWnds();
...
}//**mainfrm.cpp**************************************************
CMainFrame::CMainFrame():m_pWndCurrentChild(NULL)
{
//.................
}CMainFrame::~CMainFrame()
{
m_wndMDIClient.Detach();
//.................
}int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1; if (m_wndMDIClient.Attach(m_hWndMDIClient) == 0)
{
TRACE0("Failed to attach MDIClient.\n");
return -1; // fail to create
}
//.................
}//----------------------------------------------------------------
// This function finds the CMDIChildWnd in the list of windows
// maintained by the application's MDIClient window following the
// one pointed to by the member variable m_pWndCurrentChild. If no
// further CMDIChildWnds are in the list, NULL is returned.
//----------------------------------------------------------------CMDIChildWnd* CMainFrame::GetNextMDIChildWnd()
{
if (!m_pWndCurrentChild)
{
// Get the first child window.
m_pWndCurrentChild = m_wndMDIClient.GetWindow(GW_CHILD);
}
else
{
// Get the next child window in the list.
m_pWndCurrentChild=
(CMDIChildWnd*)m_pWndCurrentChild->GetWindow(GW_HWNDNEXT);
} if (!m_pWndCurrentChild)
{
// No child windows exist in the MDIClient,
// or you are at the end of the list. This check
// will terminate any recursion.
return NULL;
} // Check the kind of window
if (!m_pWndCurrentChild->GetWindow(GW_OWNER))
{
if (m_pWndCurrentChild->
IsKindOf(RUNTIME_CLASS(CMDIChildWnd)))
{
// CMDIChildWnd or a derived class.
return (CMDIChildWnd*)m_pWndCurrentChild;
}
else
{
// Window is foreign to the MFC framework.
// Check the next window in the list recursively.
return GetNextMDIChildWnd();
}
}
else
{
// Title window associated with an iconized child window.
// Recurse over the window manager's list of windows.
return GetNextMDIChildWnd();
}
}//-----------------------------------------------------------------
// This function counts the number of CMDIChildWnd objects
// currently maintained by the MDIClient.
//-----------------------------------------------------------------int CMainFrame::GetCountCMDIChildWnds()
{
int count = 0; CMDIChildWnd* pChild = GetNextMDIChildWnd();
while (pChild)
{
count++;
pChild = GetNextMDIChildWnd();
}
return count;
}
最后这句话的意思是什么?
是说所有的子窗口和内部窗口没有固定的顺序在窗口管理列表里面吗?
BOOL EnumChildWindows(
HWND hWndParent, // handle to parent window
WNDENUMPROC lpEnumFunc, // callback function
LPARAM lParam // application-defined value
);
hwnd = ::GetParent(hwnd); // 得到 MDIClient 窗口
EnumChildWindows(hwnd, ...); // 可以得到 MDIClient 所有的子窗口,
// 但你好像要求要得到的仅仅是直接的子窗口,
// 所以在回调函数里需要检查一下遍历到的子窗
// 口其父窗口是不是 MDIClient 窗口,或者简单
// 判断一下是否具有 WS_EX_MDICHILD 风格即可。
// 然后嘛...因为看你是用 MFC,...
CMDIChildWnd* pChild = (CMDIChildWnd*)CWnd::FromHandle(...);
有一点不太明白,MDIClient子窗口和直接的子窗口有什么区别?还有第2句代码为何得到的不是主窗口的句柄?可能我对子窗口这边的概念还有些模糊,希望得到你的帮助,谢谢!
HWND hwnd = MDIGetActive()->GetSafeHwnd(); // 得到活动子窗口
hwnd = ::GetParent(hwnd); // 得到 MDIClient 窗口
我的问题看到了吗?
另外m_pWndCurrentChild->GetWindow(GW_OWNER)这句话得到的“所有者”是什么?父、本身又抑或是其他??
你的提示对我很有帮助,谢谢,结贴后一定给分:)