DialogBar相比Dialog有很多优势。因CDialogBar继承于CControlBar,因此其可以Docking在窗口一边,而把CView挤压开,但是CDialogBar 的使用并不是很容易,因为 MFC 里面并没有提供直接可以使用的CDialogBar,我们需要自己动手,打造自己的完美的DialogBar。
首先,你需要建立一个CDialog的子类(比CMyDlgBar)。然后,我们来把他一步步转换成CDialogBar的子类。
1、改变基类和消息映射
我们头文件中把CMyDlgBar的基类改成CDialogBar (原来CDialog),并且在cpp文件中的BEGIN_MESSAGE_MAP也做同样的修改。
修改头文件和cpp文件里的构造函数,并且修改DoDataExchange()等三处地方:
CMyDlgBar:: CMyDlgBar (CWnd* pParent /*=NULL*/)
: CDialog(CMyDlgBar::IDD, pParent)
{
...
void CMyDlgBar::DoDataExchange(CDataExchange* pDX)
CDialog::DoDataExchange(pDX);
...
修改为:
CMyDlgBar (); //标准构造函数
CMyDlgBar:: CMyDlgBar ()
{
...
void CMyDlgBar::DoDataExchange(CDataExchange* pDX)
CDialogBar::DoDataExchange(pDX);
...
2、改写OnInitDialog
在头文件的消息函数声明中插入:
afx_msg LONG OnInitDialog(UINT, LONG);
在cpp文件的消息映射中插入:
ON_MESSAGE(WM_INITDIALOG, OnInitDialog);
并且在cpp文件中实现这个函数:
LONG CPfctDlgBar::OnInitDialog(UINT wParam, LONG lParam){
BOOL bRet = HandleInitDialog(wParam, lParam);
if(!UpdateData(FALSE)){
TRACE0("Warning, Unalbe to init update. ");
}
// Add Code here
return bRet;
}
不错,现在你可以在DialogBar里面初始化控件了。
3、使用CMyDlgBar
首先确定CMyDlgBar的属性,如果不是以下设置,就修改过来:
Style: Child
Boarder: None
Visible: Unchecked
好了,现在让我们来使用这个CMyDlgBar,比如在CMainFrame里面声明一个:
class CMainFrame : public CFrameWnd
{
...
CMyDlgBar m_myDlgBar;
...
}
然后在CMainFrame::OnCreate()函数里面这样写:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...
if (!m_myDlgBar.Create(this, IDD_DLGBAR1, CBRS_LEFT, IDD_DLGBAR1))
{
TRACE0("Failed to create dialog bar ");
return -1; // fail to create
}
...
}
或者如果你想让其动态的停靠在面板的任何一个地方,那就加上CBRS_FLYBY和CBRS_SIZE_DYNAMIC,这两个都是CControlBar的属性,具体可查询MSDN:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
....
if (!m_myDlgBar.Create(this, IDD_DLGBAR1, CBRS_LEFT| CBRS_FLYBY | CBRS_SIZE_DYNAMIC, IDD_DLGBAR1))
{
TRACE0("Failed to create dialog bar ");
return -1; // fail to create
}
m_myDlgBar.EnableDocking(CBRS_ALIGN_LEFT | CBRS_ALIGN_RIGHT);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_myDlgBar);
...
}
到此,你基本上可以像使用其它控件一样使用CDialogBar了,当然,还有一些小技巧。
4、实用技巧
(1)、如果有很多个CDialogBar同时出现在你的面板上,那可能会出现显示错误的问题,你可以在ShowWindow()之后,调用MainFrame的RecalcLayout()来将屏幕位置合理调整。
(2)、CButton不能使用,如何解决?
同样是添加函数,头文件中插入:
afx_msg void OnUpdateButton(CCmdUI * pCmdUI);
在cpp文件中插入:
ON_UPDATE_COMMAND_UI(IDC_BUTTON, OnUpdateButton)
并且在cpp文件中实现之:
void CMyDlgBar::OnUpdateButton(CCmdUI * pCmdUI){
pCmdUI -> Enable(TRUE);
}
(3)、如何在Button上添加bitmap?
还是消息函数,在OnInitDialog中添加:
OnInitDialog(){
…;
HBITMAP hBitmap = LoadBitmap(AfxGetApp() ->m_hInstance,
MAKEINTRESOURCE(IDB_BITMAP);
HWND hwnd = ::GetDlgItem(this -> GetSafeHwnd(), IDOK);
::SendMessage(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (long)hBitmap);
…;
}
(4)、改变CMyDlgBar的大小,比如永远为主窗口的左1/3:
在头文件的重载函数声明中插入:
virtual CSize CalcDynamicLayout(int nLength, DWORD nMode);
在cpp文件中实现:
CSize CMyDlgBar::CalcDynamicLayout(int nLength, DWORD nMode){
CRect rcFrame;
GetDockingFrame() ->GetClientRect(&rcFrame);
return CSize(rcFrame.Width() / 3, rcFrame.Height());
}
#if !defined(AFX_MYDLGBAR_H__2AFF8EA8_A746_4608_AA10_04CEC54260A7__INCLUDED_) #define AFX_MYDLGBAR_H__2AFF8EA8_A746_4608_AA10_04CEC54260A7__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // MyDlgBar.h : header file // ///////////////////////////////////////////////////////////////////////////// // CMyDlgBar dialog class CMyDlgBar : public CDialogBar { // Construction public: CMyDlgBar(); // standard constructor // Dialog Data //{{AFX_DATA(CMyDlgBar) enum { IDD = CG_IDD_MYDIALOGBAR }; // NOTE: the ClassWizard will add data members here //}}AFX_DATA // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CMyDlgBar) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(CMyDlgBar) afx_msg LONG OnInitDialog(UINT, LONG); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_MYDLGBAR_H__2AFF8EA8_A746_4608_AA10_04CEC54260A7__INCLUDED_)
// MyDlgBar.cpp : implementation file // #include "stdafx.h" #include "2011082603.h" #include "MyDlgBar.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMyDlgBar dialog CMyDlgBar::CMyDlgBar() { //{{AFX_DATA_INIT(CMyDlgBar) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT } void CMyDlgBar::DoDataExchange(CDataExchange* pDX) { CDialogBar::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMyDlgBar) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CMyDlgBar, CDialogBar) //{{AFX_MSG_MAP(CMyDlgBar) ON_MESSAGE(WM_INITDIALOG, OnInitDialog) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMyDlgBar message handlers LONG CMyDlgBar::OnInitDialog(UINT wParam, LONG lParam) { BOOL bRet = HandleInitDialog(wParam, lParam); if(!UpdateData(FALSE)) { TRACE0("Warning, Unalbe to init update. "); } // Add Code here return bRet; }