要求不用MDIGetActive()和MDINext()实现,因为 如果窗体中除活动子窗体以外其他非活动子窗体隐藏的话,MDINext()得到的将会是其本身,这个我做过试验了,这样就无法遍历其余的子窗体,有没有好的办法,就像视图遍历一样,从首遍历到尾?
如果用GetWindow代码怎么写?

解决方案 »

  1.   

    问】 如何在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;
    }
      

  2.   

    don't make assumptions about the ordering of children in the list after an API function is called.
    最后这句话的意思是什么?
    是说所有的子窗口和内部窗口没有固定的顺序在窗口管理列表里面吗?
      

  3.   

    尝试使用这个:
    BOOL EnumChildWindows(
      HWND hWndParent,         // handle to parent window
      WNDENUMPROC lpEnumFunc,  // callback function
      LPARAM lParam            // application-defined value
    );
      

  4.   

    HWND hwnd = MDIGetActive()->GetSafeHwnd(); // 得到活动子窗口
    hwnd = ::GetParent(hwnd); // 得到 MDIClient 窗口
    EnumChildWindows(hwnd, ...); // 可以得到 MDIClient 所有的子窗口,
                                 // 但你好像要求要得到的仅仅是直接的子窗口,
                                 // 所以在回调函数里需要检查一下遍历到的子窗
                                 // 口其父窗口是不是 MDIClient 窗口,或者简单
                                 // 判断一下是否具有 WS_EX_MDICHILD 风格即可。
    // 然后嘛...因为看你是用 MFC,...
    CMDIChildWnd* pChild = (CMDIChildWnd*)CWnd::FromHandle(...);
      

  5.   

    dandycheung(珠穆朗玛) :
    有一点不太明白,MDIClient子窗口和直接的子窗口有什么区别?还有第2句代码为何得到的不是主窗口的句柄?可能我对子窗口这边的概念还有些模糊,希望得到你的帮助,谢谢!
    HWND hwnd = MDIGetActive()->GetSafeHwnd(); // 得到活动子窗口
    hwnd = ::GetParent(hwnd); // 得到 MDIClient 窗口
      

  6.   

    MDI 是使用的两层结构我们可以最大化最小化的窗口称之为框架窗口,具体显示各个文档的可以最大化最小化的窗口称为 MDI 的子窗口,看起来好像是 MDI 子窗口是框架窗口的直接子窗口,其实不是的,在框架窗口的客户区里存在一个窗口类为 MDIClient 的窗口,他是框架窗口的直接子窗口,而所有的 MDI 子窗口都是这个窗口的直接子窗口;这样做是为了将 MDI 的管理功能分离到一个功能比较单一的窗口里去,以便于你对框架窗口进行别的工作而不影响 MDI 的管理。例如,VC 集成开发环境里,最大化的文档窗口也不能将 ClassView 覆盖,而框架窗口实现时只要能正确改变 MDIClient 窗口的大小即可,否则采用平面管理,框架窗口要去一一负责 MDI 子窗口的大小,而子窗口的数量在运行时又不确定,将会很麻烦。希望对你有帮助。
      

  7.   

    to laiyiling(陌生人 苦心钻研) :
    我的问题看到了吗?
    另外m_pWndCurrentChild->GetWindow(GW_OWNER)这句话得到的“所有者”是什么?父、本身又抑或是其他??
      

  8.   

    to dandycheung(珠穆朗玛) :
    你的提示对我很有帮助,谢谢,结贴后一定给分:)
      

  9.   

    m_pWndCurrentChild->GetWindow(GW_OWNER)就是返回前面m_pWndCurrentChild的所有者