如何关闭动态创建的CDockablePane窗口?

for*_*idt 2 c++ docking mfc-feature-pack pane

在我的MFC(Feature Pack)应用程序中,可以动态创建停靠窗格以显示图表/表格等.
但是,我不想让用户打开相同的东西两次.

我创建一个像这样的窗格:

// Create CMyDockablePane pPane
pPane->Create(...);
pPane->EnableDocking(CBRS_ALIGN_ANY);
// Create CRect rcPane
pPane->FloatPane(rcPane);
Run Code Online (Sandbox Code Playgroud)

这似乎工作正常.

这就是我尝试检查窗格是否已存在的方法.窗格由其类型(类)和参数标识.

BOOL CanOpenPane(const type_info & paneType, const CMyParameter & parameter) const
{
    CMainFrame* pFrm = GetMainFrame();
    CDockingManager* pDockMan = pFrm->GetDockingManager();


    // Check if there already is a pane of the same type which also has the same parameter.
    bool canOpen = true;
    CObList panes;
    pDockMan->GetPaneList(panes);
    POSITION pos = panes.GetHeadPosition();
    while (pos)
    {
        CMyDockablePane* pPane = dynamic_cast<CMyDockablePane*>(panes.GetNext(pos));
        if (NULL == pPane) { continue; }

        if (paneType == typeid(*pPane) &&
                pPane->GetParameter() == parameter)
        {
            canOpen = false;
            break;
        }
    }


    return canOpen;
}
Run Code Online (Sandbox Code Playgroud)

这样做的问题是,当我关闭窗格时,无法识别.CDockingManager对象仍返回GetPanes()调用中的窗格.

如何告诉经理不要退回关闭的窗格?
或者
如何在窗格列表关闭时从窗格列表中删除窗格?


更新

我更深入地发现,当单击标题栏中的"x"按钮时,CWnd对象实际上并未关闭,而只是它们的容器.
所以真正的问题似乎是真正关闭窗格.
我也改变了问题,以更好地反映问题.

for*_*idt 5

正如我的更新中所述,对接管理器给我关闭窗格的问题是,窗格实际上并未关闭.只有他们的容器被关闭; 窗格本身就是隐藏的.

因此,为了真正关闭窗格,我在我的CMDIFrameWndEx派生主框架类中覆盖了以下方法:

BOOL CMainFrame::OnCloseMiniFrame(CPaneFrameWnd* pWnd)
{
    if(0 == pWnd->GetPaneCount()) { return TRUE; } // No panes.. allow closing

    // Close all child panes of the miniframe that is about to be closed.
    //
    // Panes are placed inside a mini frame when they have the "floating" status.
    // Since I didn't find a way to iterate over the panes of a mini frame
    // (CMultiPaneFrameWnd can have several panes), we iterate over all panes
    // and close those whose parent frame is pWnd.

    CDockingManager* pDockMan = GetDockingManager();
    if(NULL != pDockMan)
    {
        CObList allPanes;
        pDockMan->GetPaneList(allPanes, TRUE, NULL, TRUE);

        for(POSITION pos = allPanes.GetHeadPosition(); pos != NULL;)
        {
            CDockablePane* pPane = dynamic_cast<CDockablePane*>(allPanes.GetNext(pos));
            if (NULL == pPane) { continue; }

            if(pWnd == pPane->GetParentMiniFrame())
            {
                pPane->PostMessage(WM_CLOSE); // Note: Post instead of Send
            }
        }

    }

    return TRUE; // Allow closing
}
Run Code Online (Sandbox Code Playgroud)

第二个:

BOOL CMainFrame::OnCloseDockingPane(CDockablePane* pWnd)
{
    CObList paneList;

    // We can get CDockablePanes and CTabbedPanes here.
    // The tabbed panes contain dockable panes.
    CTabbedPane* pTabbed = dynamic_cast<CTabbedPane*>(pWnd);
    CDockablePane* pDockable = dynamic_cast<CDockablePane*>(pWnd);
    if(NULL != pTabbed)
    {
        pTabbed->GetPaneList(paneList);
    }
    else if(NULL != pDockable)
    {
        paneList.InsertAfter(paneList.GetHeadPosition(), pDockable);
    }

    // Whatever it was, we now have a list of dockable panes, which we will close.
    for(POSITION pos = paneList.GetHeadPosition(); NULL != pos;)
    {
        CDockablePane* pPane = dynamic_cast<CDockablePane*>(paneList.GetNext(pos));
        ASSERT(NULL != pPane);


        // Let the window disappear and then recalculate the layout.
        // Not doing this causes problems with panes grouped together in a tabbed pane.
        pPane->ShowWindow(SW_HIDE);
        RecalcLayout();

        // Really close the window so the docking manager also doesn't know of it anymore.
        pPane->Reset();
        pPane->PostMessage(WM_CLOSE); // Note: Post instead of Send
    }


    return TRUE; // Allow closing
}
Run Code Online (Sandbox Code Playgroud)