原帖地址:http://support.microsoft.com/kb/185672
When creating a simple CDialogBar, such as one with only CButtons similar to MFC's print preview, it is not necessary to derive from CDialogBar because the parent of CControlBar receives the notification messages from any child controls.
However, in the case of a more complex CDialogBar, which might have a drop- down combo box, a treeview, or ActiveX control, it might be useful to derive from CDialogBar to provide initialization for the child controls.
Because ClassWizard does not support deriving a class from CDialogBar, this article shows the steps necessary to create a class from CDialog and then "convert" the class to CDialogBar.
To start out, create a CDialog class with the child controls you want to use. You can transform the CDialog class into a CDialogBar class using the following nine steps:
- Change the base class from CDialog to CDialogBar in the class declaration. Don't forget to also change the base class in BEGIN_MESSAGE_MAP in the .cpp file.
- Change the constructor in both the .h and the .cpp files. Also make the change to the DoDataExchange(). Below are three items to change.
Change the following fromCMyDlgBar (CWnd* pParent = NULL); // standard constructor CMyDlgBar:: CMyDlgBar (CWnd* pParent /*=NULL*/) : CDialog(CMyDlgBar::IDD, pParent) { ... void CMyDlgBar::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); ...
CMyDlgBar (); // standard constructor CMyDlgBar:: CMyDlgBar () { ... void CMyDlgBar::DoDataExchange(CDataExchange* pDX) { CDialogBar::DoDataExchange(pDX); ...
- Remove "virtual BOOL OnInitDialog();" from the class header and add "afx_msg LONG OnInitDialog ( UINT, LONG );" in its place. For example:
class CMyDlgBar : public CDialogBar { ... // Implementation protected: // Generated message map functions //{{AFX_MSG(CMyDlgBar) virtual BOOL OnInitDialog(); // <-Remove this line. //}}AFX_MSG afx_msg LONG OnInitDialog ( UINT, LONG ); // <-Add this line. DECLARE_MESSAGE_MAP() };
- Add "ON_MESSAGE(WM_INITDIALOG, OnInitDialog );" to the message map in the .CPP implementation file. For example:
BEGIN_MESSAGE_MAP(CMyDlgBar, CDialogBar) //{{AFX_MSG_MAP(CMyDlgBar) ... //}}AFX_MSG_MAP ON_MESSAGE(WM_INITDIALOG, OnInitDialog ) // <-- Add this line. END_MESSAGE_MAP()
- Make the OnInitDialog() conversion as follows:
Change the following: BOOL CMyDlgBar::OnInitDialog() { CDialog::OnInitDialog(); // <-- Replace this line: ...
LONG CMyDlgBar::OnInitDialog ( UINT wParam, LONG lParam) { // <-- with these lines. --> BOOL bRet = HandleInitDialog(wParam, lParam); if (!UpdateData(FALSE)) { TRACE0("Warning: UpdateData failed during dialog init./n"); } ... return bRet;
- Make sure the dialog box resource styles to the following:
Style: ChildAt this point, everything has been reconnected to make the transformation from a CDialog class to a CDialogBar class work correctly. Now, create and use it.
Boarder: None
Visible: Unchecked - Add an instance of the derived CDialogBar to the CframeWnd-derived class (normally called CMainFrame). For example:
class CMainFrame : public CFrameWnd { ... CMyDlgBar m_myDlgBar; ... };
- Call the create method for the m_myDlgBar variable in the CFrameWnd::OnCreate() method similar to the following:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { ... if (!m_myDlgBar.Create(this, IDD_DLGBAR1, CBRS_LEFT, IDD_DLGBAR1)) { TRACE0("Failed to create dialog bar/n"); return -1; // fail to create } ... }
- Finally, if you want to support dynamic docking and resizing of the CDialogBar, add the following lines to the end of CMainFrame::OnCreate():
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { ... m_myDlgBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); m_myDlgBar.EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_myDlgBar); return 0; }