|
适用于 这一个文章先前在 Q298126 之下被出版 征兆 当一个 MFC 工具栏垂直地被放置,工具栏的定制可能造成一个或更多个按纽不能显示。 定制可能使用CToolBarCtrl的Customize()函数 增加或除去按纽或相似的编程方法。 原因 首先, MFC 提供 对象的所有细节 , 像是工具栏 , 但是自从4.0版本,MFC 开始MFC开始用公用控件来代替工具柆,状态栏等等的实现。这个导置了MFC控件类的兼容性。 解决 无论工具栏是停靠或悬浮,在增加或删除按纽后,以下代码能够正确地调整大小,重画MFC垂直工具栏。 OnToolBarChange的句柄 响应 TBN_TOOLBARCHANGE 通知被执行。 代码分三个步骤执行。 首先, CalcDynamicLayout以适当的参数执行,工具栏的状态可能为停靠/ 悬浮/垂直/ 水平。 其次, DockControlBar( 或 FloatControlBar) 被执行, 主要地呼叫这些函数来执行 SetWindowPos 的呼叫。 最后, DrawBorders 被呼叫完成重画。 把下列的注册加入你 CMainFrame's 的信息映象中。 (AFX_IDW_TOOLBAR 是工具栏ID) ON_NOTIFY(TBN_TOOLBARCHANGE, AFX_IDW_TOOLBAR, OnToolBarChange) 把 OnToolBarChange 成员函数加入 CMainFrame 类并且增加下列的代码: void CMainFrame::OnToolBarChange(NMHDR *notify, LRESULT *result) { // Update the toolbar icons. CFrameWnd* pFrame; if (m_wndToolBar.IsFloating()) pFrame = m_wndToolBar.GetParentFrame(); else pFrame = m_wndToolBar.GetDockingFrame(); CRect rectActualSize; CRect rectActualFrameSize; CRect rect; CSize size; // Get the ToolBar's rectangle m_wndToolBar.GetWindowRect(&rect); // Are we horizontal? BOOL bHorz = (m_wndToolBar.m_dwStyle & CBRS_ORIENT_HORZ) != 0; if ((m_wndToolBar.m_dwStyle & CBRS_FLOATING) && (m_wndToolBar.m_dwStyle & CBRS_SIZE_DYNAMIC)) size = m_wndToolBar.CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH | LM_COMMIT); else if (bHorz) size = m_wndToolBar.CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK | LM_COMMIT); else size = m_wndToolBar.CalcDynamicLayout(0, LM_VERTDOCK | LM_COMMIT); // Use the result to calculate a new size rectActualSize = CRect(rect.TopLeft(), size); rectActualFrameSize = CRect(rect.TopLeft(), size); // Calculate frame rectangle CMiniFrameWnd::CalcBorders(rectActualFrameSize); // Leave room for the window's border. The values used here // for m_cxBorder and m_cyBorder are 2 and 2 as a result of // calling GetSystemMetrics for SM_CXBORDER and SM_CYBORDER // (these should return 1) and multiplying the result by 2 // to accommodate the modern shell's wider borders. rectActualFrameSize.InflateRect(-m_cxBorder, -m_cyBorder); if (m_wndToolBar.IsFloating()) { pFrame->FloatControlBar(&m_wndToolBar, rectActualFrameSize.TopLeft()); } else pFrame->DockControlBar(&m_wndToolBar); // force the frame window to recalculate the size m_wndToolBar.GetParentFrame()->RecalcLayout(); CDC* pDC = GetDC(); rectActualFrameSize.OffsetRect(-rectActualFrameSize.left, -rectActualFrameSize.top); m_wndToolBar.DrawBorders(pDC, rectActualFrameSize); ReleaseDC(pDC); } 把下列的数据成员加入 CMainFrame 类中并且在 CMainFrame's OnCreate成员函数设定他们初值: int m_cyBorder; int m_cxBorder; int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { m_cxBorder = GetSystemMetrics(SM_CXBORDER); m_cyBorder = GetSystemMetrics(SM_CYBORDER); ..... } 状态 这行为是藉着设计。 更多信息 为了要接受工具栏的定制特征 你一定将 CCS_ADJUSTABLE 风格设定为工具栏控制的特征,就象在这里显示: m_wndToolBar.GetToolBarCtrl.()ModifyStyle;(0,CCS_ADJUSTABLE) 改变后,当定制对话框出现,最少有一个工具栏通知被处理。这个通知是TBN_QUERYINSERT,它能够在CMainFrame 类被处理,就象下面那样: void CMainFrame::OnQueryInsert( NMHDR * pNotifyStruct, LRESULT * result ) { *result = TRUE; } NMHDR 结构实际上是 NMTOOLBAR 通知结构。 应该被处理的另外一个通知是 TBN_GETBUTTONINFO 。 因为通知被送去,所以这很重要为那些可得被增加到工具栏的按纽发送请求按纽数据。 为了要适当地处理这一个通知, NMTOOLBAR 结构的 iItem 成员应该被比较到原先的 TBBUTTON 结构队列的索引 , 和处理的人应该将结构装满按纽数据而且设定result为TRUE。 叁考 对于关于该如何保持那定制会话框看得见的信息, 按文章在下面数看微软知识库的文章: 241850 PRB: Call to CToolBarCtrl::Customize() Does Not Keep the Customize Dialog Box Visible MFC "Toolbar Topics" in the "Adding User Interface Features" section of the Visual C++ Programmer's Guide: http://msdn.microsoft.com/library/en-us/vccore98/html/_core_toolbar_topics.asp The Microsoft Platform SDK Documentation has extensive information on the ToolBar common control in its "User Interface Services" section under "Windows Common Controls": http://msdn.microsoft.com/library/en-us/shellcc/shellcc/CommCtls/ToolBar/ToolBar.asp
|