如何关闭动态创建的CDockablePane窗口?
在我的 MFC(功能包)应用程序中,可以动态创建停靠窗格来显示图表/表格等。
但是,我不想让用户打开同一个东西两次。
我创建了一个像这样的窗格:
// Create CMyDockablePane pPane
pPane->Create(...);
pPane->EnableDocking(CBRS_ALIGN_ANY);
// Create CRect rcPane
pPane->FloatPane(rcPane);
这似乎工作正常。
这就是我尝试检查窗格是否已存在的方法。窗格由其类型(类)和参数来标识。
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;
}
问题在于,当我关闭窗格时,它无法被识别。 CDockingManager 对象仍然在 GetPanes() 调用中返回窗格。
如何告诉经理不要返回已关闭的窗格?
或
当窗格关闭时,如何从窗格列表中删除窗格?
更新
我深入研究后发现,当单击标题栏中的“x”按钮时,CWnd 对象实际上并未关闭,但是只有他们的容器。
所以真正的问题似乎是真正关闭窗格。
我还改变了问题以更好地反映问题。
In my MFC (Feature Pack) application one can dynamically create docking panes to display charts/tables etc.
However, I don't want to let the user open the same thing twice.
I create a pane like this:
// Create CMyDockablePane pPane
pPane->Create(...);
pPane->EnableDocking(CBRS_ALIGN_ANY);
// Create CRect rcPane
pPane->FloatPane(rcPane);
This seems to work fine.
This is how I tried to check if a pane already exists. A pane is identified by its type (class) and a parameter.
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;
}
The problem with this is that when I close a pane, this is not recognized. The CDockingManager object still returns the pane in the GetPanes() call.
How can I tell the manager to not return panes that are closed?
or
How can I remove the pane from a pane list, when it's closed?
Update
I dived a bit deeper and found, that the CWnd objects are not actually closed, when clicking the 'x' button in the caption bar, but only their containers.
So the real problem seems to be to really close the panes.
I also changed the question to better reflect the problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
正如我的更新中所述,对接管理器给我关闭的窗格的问题是窗格实际上并未关闭。只是他们的容器是封闭的;窗格本身只是被隐藏起来。
因此,为了真正关闭窗格,我在 CMDIFrameWndEx 派生的主框架类中重写了以下方法:
第二个:
As described in my update, the problem for the docking manager giving me closed panes, was that the panes were not actually closed. Only their containers were closed; the panes themselves were just hidden.
So to really close the panes I overrode the following methods in my
CMDIFrameWndEx
derived main frame class:And the second:
将如下所示的消息条目添加到您的 CMainFram 中:
OnClosePane 如下所示:
注意:
OnClosePane 在 CBasePane::OnLButtonDown 处理程序中间调用,销毁窗口
将使您的代码断言,因此您需要发布消息(WM_CLOSE)而不是发送它,这使 CBasePane::OnLButtonDown 处理程序有机会在窗格 hWnd 仍然有效时完成执行。
出于同样的原因,我返回 True 以防止关闭,因为我们已经通过关闭它
WM_CLOSE 这也会破坏窗口。
WM_RESETMEMBER 消息是注册窗口消息,用于将窗格成员重置为 null 。
它的实现看起来像这样:
你应该像这样的 msg 映射条目:
并且你应该像这样全局注册消息:
add to yor CMainFram a msg entry like the following :
OnClosePane look like this :
COUTION :
OnClosePane is called in middle of CBasePane::OnLButtonDown handler , destroying window
will make your code assert , so you need to post message(WM_CLOSE) instead of sending it , this give CBasePane::OnLButtonDown handler a chance to finish executing while the pane hWnd still valid .
and for the same resone i return True to prevent close because we already close it via
WM_CLOSE which will destroy window as well.
WM_RESETMEMBER message is registered window message to reset pane member to null .
it implementation look like this :
you should msg map entry like one :
and you should register message globally like this :
当您关闭窗格来完成这项工作。
I'd expect a call to CDockingManager::RemovePaneFromDockManager when you are closing your pane to do the job.
在mfc文档中,它说不要使用showwindow,所以使用showpane来显示窗格
in the mfc document,it said that don't use showwindow,so use showpane to show the pane