MFC MDI 在输出 window 中切换选项卡而无需重新启动(在我的例子中)
MFC MDI Toggling a tab in the output window without having to restart (in my case)
所以我正在使用 MFC 向导创建的输出窗格,一切都按我想要的方式运行。我想弄清楚的是如何 hide/show 用户从菜单中选择的特定选项卡。我有两个选项卡,一个是状态,一个是调试...我有一个用户菜单选项来打开调试 on/off 我通过使用注册表的开关来跟踪是否绘制它的状态在应用程序启动。我希望能够在不重新启动的情况下打开和关闭选项卡。
int COutputWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
CRect rectDummy;
rectDummy.SetRectEmpty();
// Create tabs window:
if (!m_wndTabs.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, 1))
{
TRACE0("Failed to create output tab window\n");
return -1; // fail to create
}
// Create output panes:
const DWORD dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;
if (!m_wndOutputBuild.Create(dwStyle, rectDummy, &m_wndTabs, 2) ||
!m_wndOutputDebug.Create(dwStyle, rectDummy, &m_wndTabs, 3))
{
TRACE0("Failed to create output windows\n");
return -1; // fail to create
}
UpdateFonts();
CString strTabName;
BOOL bNameValid;
// Attach list windows to tab:
bNameValid = strTabName.LoadString(IDS_STATUS_TAB);
ASSERT(bNameValid);
m_wndTabs.AddTab(&m_wndOutputBuild, strTabName, (UINT)0);
// Enable debug tab if user sets it in settings
int EnableDebugTab = AfxGetApp()->GetProfileInt(_T("Settings"), _T("EnableDebugTab"), 0); //Get value from registry
if (EnableDebugTab == TRUE)
{
bNameValid = strTabName.LoadString(IDS_DEBUG_TAB);
ASSERT(bNameValid);
m_wndTabs.AddTab(&m_wndOutputDebug, strTabName, (UINT)1);
}
return 0;
}
我试过:
m_wndOutputDebug.ShowWindow(FALSE);
但这没有用。
m_wndOutputDebug.EnableWindow(FALSE);
那也没用。
我知道选项卡可以打开和关闭,我只是不明白打开和隐藏调试选项卡的机制。
处理此任务的最佳方法是什么?
编辑
所以根据 IInspectable 的评论,我试图 show/hide 选项卡而不破坏选项卡数据,好的,不用担心....我对我想要实现的目标有错误的期望... . 我修改了调试选项卡以始终启动测试,如:
bNameValid = strTabName.LoadString(IDS_STATUS_TAB);
ASSERT(bNameValid);
m_wndTabs.AddTab(&m_wndOutputBuild, strTabName, (UINT)0);
bNameValid = strTabName.LoadString(IDS_DEBUG_TAB);
ASSERT(bNameValid);
m_wndTabs.AddTab(&m_wndOutputDebug, strTabName, (UINT)1);
添加:
m_wndTabs.RemoveTab(1);
这是有效的,因为它总是删除调试选项卡...太棒了!...但是...
知道有效...m_wndTabs.RemoveTab(1);
被注释掉并添加到下面的新函数中。
选项卡代码位于 COutputWnd
,我通过消息映射将此新功能称为 application.cpp 中的菜单项:
ON_COMMAND(ID_SETTINGS_DEBUG_TAB, &COutputWnd::OnDebugTabShow)
在OutputWnd.cpp
中添加了这个函数:
void COutputWnd::OnDebugTabShow()
{
m_wndTabs.RemoveTab(1); //exact code from on create that works there in test
}
我在 oncreate 中注释掉了 m_wndTabs.RemoveTab(1);
(因为我知道它在那里作为测试工作)...当我调试并调用 OnDebugTabShow()
时...我得到一个
Exception thrown: read access violation.
this->m_wndTabs
. was nullptr
.
我不清楚为什么指针是空的,因为它是构建和加载的。
只是需要帮助来解决这个问题。
您不必删除和添加标签。 Show/Hide 使用 ShowTab() 的 Tab 是合适的。
这里以 ShowTab 为例。因为Tab可以动态移动到任何地方,所以一定要搜索到想要的Tab。
void COutputWnd::OnOutputtabsDebug()
{
// Toggling OutputTab
CString strDebugLabelShould;
strDebugLabelShould.LoadString(IDS_DEBUG_TAB);
CString strLabelIs;
int nMax = m_wndTabs.GetTabsNum();
for (int nId = 0; nId < nMax; nId++)
{
m_wndTabs.GetTabLabel(nId, strLabelIs);
if (strLabelIs == strDebugLabelShould)
{
// found
CWnd* pWnd = m_wndTabs.GetTabWnd(nId);
BOOL bShow = !pWnd->IsWindowEnabled();
m_wndTabs.ShowTab(nId, bShow); // Toggle
pWnd->EnableWindow(bShow);
break;
}
}
}
命令转发路由到 COutputWnd
由于 MFC 命令路由不会为您执行此操作,因此必须在大型机(或视图)中添加处理程序并手动转发,例如这样
ON_COMMAND(ID_OUTPUTTABS_DEBUG, &CMainFrame::OnOutputtabsDebug)
void CMainFrame::OnOutputtabsDebug()
{
m_wndOutput.OnOutputtabsDebug();
}
回复:
The tab code lives in COutputWnd, I am calling this new function a menu item from my application.cpp via the message map:
ON_COMMAND(ID_SETTINGS_DEBUG_TAB, &COutputWnd::OnDebugTabShow)
你的 application.cpp
中有这个 ON_COMMAND
宏吗?那是错误的!
在那种情况下,您的应用程序的 this
指针将用于 COutputWnd::OnDebugTabShow()
(转换为 COutputWnd
),从而导致各种问题。
这应该在您视图的消息映射中。
所以我正在使用 MFC 向导创建的输出窗格,一切都按我想要的方式运行。我想弄清楚的是如何 hide/show 用户从菜单中选择的特定选项卡。我有两个选项卡,一个是状态,一个是调试...我有一个用户菜单选项来打开调试 on/off 我通过使用注册表的开关来跟踪是否绘制它的状态在应用程序启动。我希望能够在不重新启动的情况下打开和关闭选项卡。
int COutputWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
CRect rectDummy;
rectDummy.SetRectEmpty();
// Create tabs window:
if (!m_wndTabs.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, 1))
{
TRACE0("Failed to create output tab window\n");
return -1; // fail to create
}
// Create output panes:
const DWORD dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;
if (!m_wndOutputBuild.Create(dwStyle, rectDummy, &m_wndTabs, 2) ||
!m_wndOutputDebug.Create(dwStyle, rectDummy, &m_wndTabs, 3))
{
TRACE0("Failed to create output windows\n");
return -1; // fail to create
}
UpdateFonts();
CString strTabName;
BOOL bNameValid;
// Attach list windows to tab:
bNameValid = strTabName.LoadString(IDS_STATUS_TAB);
ASSERT(bNameValid);
m_wndTabs.AddTab(&m_wndOutputBuild, strTabName, (UINT)0);
// Enable debug tab if user sets it in settings
int EnableDebugTab = AfxGetApp()->GetProfileInt(_T("Settings"), _T("EnableDebugTab"), 0); //Get value from registry
if (EnableDebugTab == TRUE)
{
bNameValid = strTabName.LoadString(IDS_DEBUG_TAB);
ASSERT(bNameValid);
m_wndTabs.AddTab(&m_wndOutputDebug, strTabName, (UINT)1);
}
return 0;
}
我试过:
m_wndOutputDebug.ShowWindow(FALSE);
但这没有用。
m_wndOutputDebug.EnableWindow(FALSE);
那也没用。
我知道选项卡可以打开和关闭,我只是不明白打开和隐藏调试选项卡的机制。
处理此任务的最佳方法是什么?
编辑
所以根据 IInspectable 的评论,我试图 show/hide 选项卡而不破坏选项卡数据,好的,不用担心....我对我想要实现的目标有错误的期望... . 我修改了调试选项卡以始终启动测试,如:
bNameValid = strTabName.LoadString(IDS_STATUS_TAB);
ASSERT(bNameValid);
m_wndTabs.AddTab(&m_wndOutputBuild, strTabName, (UINT)0);
bNameValid = strTabName.LoadString(IDS_DEBUG_TAB);
ASSERT(bNameValid);
m_wndTabs.AddTab(&m_wndOutputDebug, strTabName, (UINT)1);
添加:
m_wndTabs.RemoveTab(1);
这是有效的,因为它总是删除调试选项卡...太棒了!...但是...
知道有效...m_wndTabs.RemoveTab(1);
被注释掉并添加到下面的新函数中。
选项卡代码位于 COutputWnd
,我通过消息映射将此新功能称为 application.cpp 中的菜单项:
ON_COMMAND(ID_SETTINGS_DEBUG_TAB, &COutputWnd::OnDebugTabShow)
在OutputWnd.cpp
中添加了这个函数:
void COutputWnd::OnDebugTabShow()
{
m_wndTabs.RemoveTab(1); //exact code from on create that works there in test
}
我在 oncreate 中注释掉了 m_wndTabs.RemoveTab(1);
(因为我知道它在那里作为测试工作)...当我调试并调用 OnDebugTabShow()
时...我得到一个
Exception thrown: read access violation.
this->m_wndTabs
. wasnullptr
.
我不清楚为什么指针是空的,因为它是构建和加载的。
只是需要帮助来解决这个问题。
您不必删除和添加标签。 Show/Hide 使用 ShowTab() 的 Tab 是合适的。 这里以 ShowTab 为例。因为Tab可以动态移动到任何地方,所以一定要搜索到想要的Tab。
void COutputWnd::OnOutputtabsDebug()
{
// Toggling OutputTab
CString strDebugLabelShould;
strDebugLabelShould.LoadString(IDS_DEBUG_TAB);
CString strLabelIs;
int nMax = m_wndTabs.GetTabsNum();
for (int nId = 0; nId < nMax; nId++)
{
m_wndTabs.GetTabLabel(nId, strLabelIs);
if (strLabelIs == strDebugLabelShould)
{
// found
CWnd* pWnd = m_wndTabs.GetTabWnd(nId);
BOOL bShow = !pWnd->IsWindowEnabled();
m_wndTabs.ShowTab(nId, bShow); // Toggle
pWnd->EnableWindow(bShow);
break;
}
}
}
命令转发路由到 COutputWnd
由于 MFC 命令路由不会为您执行此操作,因此必须在大型机(或视图)中添加处理程序并手动转发,例如这样
ON_COMMAND(ID_OUTPUTTABS_DEBUG, &CMainFrame::OnOutputtabsDebug)
void CMainFrame::OnOutputtabsDebug()
{
m_wndOutput.OnOutputtabsDebug();
}
回复:
The tab code lives in COutputWnd, I am calling this new function a menu item from my application.cpp via the message map:
ON_COMMAND(ID_SETTINGS_DEBUG_TAB, &COutputWnd::OnDebugTabShow)
你的 application.cpp
中有这个 ON_COMMAND
宏吗?那是错误的!
在那种情况下,您的应用程序的 this
指针将用于 COutputWnd::OnDebugTabShow()
(转换为 COutputWnd
),从而导致各种问题。
这应该在您视图的消息映射中。