在VC中,如果只是简单的使用CButton之类的东西,是不需要使用CDialogBar类的,您只要简单使用CToolBar之类的就行了,但如果您要使用 CCombobox, CTreeview, 或者是ActiveX control之类的就需要该类了。
在http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B185672这篇文章中,述了如何使用CDialogBar的基本用法
在使用向导生成自己的类基于CDialog的类之后要进行以下6步
1、更改基类为CDialogBar,同时也要改BEGIN_MESSAGE_MAP 中的基类。
2、更改构造函数、DoDataExchange(),即
CMyDlgBar (CWnd* pParent = NULL); // standard constructor
CMyDlgBar:: CMyDlgBar (CWnd* pParent /*=NULL*/)
CDialog(CMyDlgBar::IDD, pParent)
{
...
void CMyDlgBar::DoDataExchange(CDataExchange* pDX)
{
Dialog::DoDataExchange(pDX);
CDialogBar::DoDataExchange(pDX); // <-加上这一行.
..
3、从类的头文件中删除
virtual BOOL OnInitDialog();
并添加
afx_msg LONG OnInitDialog ( UINT, LONG );
如下:
class CMyDlgBar : public CDialogBar
{
...
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CMyDlgBar)
virtual BOOL OnInitDialog();
//}}AFX_MSG
afx_msg LONG OnInitDialog ( UINT, LONG ); // <-加上这一行.
DECLARE_MESSAGE_MAP()
};
4、在CPP文件中加入WM_INITDIALOG消息映射
BEGIN_MESSAGE_MAP(CMyDlgBar, CDialogBar)
//{{AFX_MSG_MAP(CMyDlgBar)
...
//}}AFX_MSG_MAP
ON_MESSAGE(WM_INITDIALOG, OnInitDialog ) // <-- 加上这一行.
END_MESSAGE_MAP()
5、添加OnInitDialog函数并更改,如下:
LONG CMyDlgBar::OnInitDialog ( UINT wParam, LONG lParam)
{
CDialog::OnInitDialog();
// <-- 加上以下几行. -->
BOOL bRet = HandleInitDialog(wParam, lParam);
if (!UpdateData(FALSE))
{
TRACE0("Warning: UpdateData failed during dialog init./n");
}
...
return bRet;
6、在资源管理器中更改对话框的类型如下:
Style: Child
Boarder: None
Visible: Unchecked
经过以上六步你就可以按正常的方法使用CdialogBar了。什么叫正常的方法,CDialogBar派生自CContorBar。
而要让CdialogBar中控件变为“可见”,则还需做一件事,就是为控件提供Command Handler函数,而该函数必须是CdialogBar的父窗口以上的对象。
重新此时, 一切已被连接进行正常转换到 CDialogBar 类从 CDialog 类。 现在, 创建并使用它。
7. 将派生 CDialogBar 的实例添加到 CframeWnd - 派生类 (通常称为 CMainFrame)。 例如:
class CMainFrame : public CFrameWnd
{
...
CMyDlgBar m_myDlgBar;
...
};
8. 为 CFrameWnd::OnCreate() 方法中 m_myDlgBar 变量调用创建方法类似于以下内容:
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
}
...
}
9. 最后, 如果要支持动态停靠和调整是 CDialogBar, 将下行添加到末尾 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;
}
//-----------------------------------------------------------------------------------------+
如果你想实现有工具条的浮动和定位功能,而且可以方便的摆放任何控件上去,请继续看这篇文章吧!
那就使用CDialogBar就可以拥有和CDialog一样的方便和快捷。
步骤1:添加一个CDialogBar派生类
在资源中添加一个对话框,再采用类向导来添加类,找不到CDialogBar作为基类吧,可以先用CDialog作为基类产生一个,然后把所以的“CDialog”替换为“CDialogBar”,替换完成了。编译一下,^_^有错误吧!!请看步骤2。
步骤2:解决编译错误并完善该类
其实错误就是构着函数调用基类时有问题,: CDialogBar(/*CDlgBar::IDD, pParent*/)象这样注释掉就可以了,添加一个类似OnInitDialog的函数,在CDialogBar中是不存在OnInitDialog的消息的,至少我还不知道,因为初始化是在创建后调用的所以我们就重写virtual BOOL Create(CWnd* pParentWnd,UINT nIDTemplate,UINT nStyle,UINT nID);这个函数。注意哦用向导添加的Create函数的参数是不对的喔,看上面。下面是实现代码(很简单的)
BOOL CDlgXXX::Create(CWnd* pParentWnd,UINT nIDTemplate,UINT nStyle,UINT nID)
{
// TODO: Add your specialized code here and/or call the base class
BOOL bRes= CDialogBar::Create(pParentWnd,nIDTemplate,nStyle,nID );
InitDialogBar();//在类中添加一个成员函数就可以了
return bRes;
}
BOOL CDlgXXX::InitDialogBar()
{
UpdateData(FALSE);//这个一定要啊,这样就会有和CDialog一样的数据交换效果了
return TRUE;
}
步骤3:创建和使用
if (!m_barAttrib.Create(this,IDD_DLG_COM_ATTRIB, CBRS_RIGHT|CBRS_GRIPPER, XXX))
{
TRACE0("Failed to create dialogbar/n");
return -1;
}
m_barAttrib.SetWindowText("部件属性");
XXX是一个资源id手工直接在资源的.h文件中添加一条,不会,这里就不教了。
工具条的显示和隐藏代码如下,自己慢慢理解吧:
ShowControlBar(&m_barAttrib, (m_barAttrib.GetStyle() & WS_VISIBLE) == 0, FALSE);
上面代码实现后DoDataExchange也是可以用,给控件添加控件就和CDialog一样的方便咯
但是还有一个要注意的是就是控件类对象的添加,我试了一下好像不行,窗口句柄好像
总是0的,不能使用。还是使用GetDlgItem(IDC_DRIVER_LIST)来取得控件指针吧。
其他方面的心得
利用DoDataExchange来控制自定义的输入格式控制这里就举一个文本框的例子
给文本控件添加完变量后就在DoDataExchange会出现如下代码
DDX_Text(pDX, IDC_COM_VAR, m_strVar);//系统产生的
DDV_MaxChars(pDX, m_strVar,VAR_MAX_LEN);//加入长度控制后产生的
DDV_FileNameString(pDX, m_strVar);//自定义的手工添加的实现见下面
void CXXX::DDV_FileNameString(CDataExchange *pDX, CString m_strFileName)
{
CString strError=_T("///:*?/"<>|");
if(m_strFileName.SpanExcluding(strError) != m_strFileName)
{
::AfxMessageBox(_T("文件名中不能包含"+strError+"字符"));
pDX->Fail();//关键是这句执行这句后就会抛出异常下面的语句就不执行了
}
}
还有几个注意点是
1.只有执行了UpdateData()才会调用DoDataExchange函数若中途 执行了pDX->Fail(); UpdateData()就返回FALSE。
2. DDX_Text(pDX, IDC_COM_VAR, m_strVar);//系统产生的
DDV_MaxChars(pDX, m_strVar,VAR_MAX_LEN);//加入长度控制后产生的
DDV_FileNameString(pDX, m_strVar);//自定义的手工添加的实现见下面
如上面几句都是对一个控件的内容的控制,他们必须放在一块,且DDX_Text要放在第一句,这样在界面上就可以正确的指出那个控件的内容有问题,控件会被设置焦点并选中全部内容。
如果你想实现有工具条的浮动和定位功能,而且可以方便的摆放任何控件上去,那就使用CDialogBar就可以拥有和CDialog一样的方便和快捷。
添加一个CDialogBar派生类:在资源中添加一个对话框,再采用类向导来添加类,这里我们找不到CDialogBar作为基类,可以先用CDialog作为基类产生一个,然后把所以的“CDialog”替换为“CDialogBar”。
构造函数CXXXDlg::CXXXDlg(CWnd* pParent /*=NULL*/)
: CDialog(CXXXDlg::IDD, pParent)改成: CXXXDlg::CXXXDlg()就可以了,添加一个类似OnInitDialog的函数,在CDialogBar中是不存在OnInitDialog的消息的,因为初始化是在创建后调用的,所以我们就重写virtual BOOL Create(CWnd* pParentWnd,UINT nIDTemplate,UINT nStyle,UINT nID)这个函数。注意哦用向导添加的Create函数的参数是不对的,改成上面。下面是实现代码:
BOOL CXXXDlg::Create(CWnd* pParentWnd,UINT nIDTemplate,UINT nStyle,UINT nID)
{
BOOL bRes= CDialogBar::Create(pParentWnd,nIDTemplate,nStyle,nID );
InitDialogBar();//在类中添加一个成员函数就可以了
return bRes;
}
BOOL CXXXDlg::InitDialogBar()
{
UpdateData(FALSE);//这个一定要啊,这样就会有和CDialog一样的数据交换效果了
return TRUE;
}
创建和使用:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndColor.Create(this, IDD_COLOR,
CBRS_BOTTOM | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_HIDE_INPLACE,
ID_VIEW_COLOR))
{
TRACE0("Failed to create dialog bar m_wndContentMenu/n");
return -1; // fail to create
}
m_wndColor.EnableDocking(CBRS_ALIGN_BOTTOM );
DockControlBar(&m_wndColor);//没有这个,CDialogBar不可以移动,FloatControlBar的功能是浮动在窗口上。
EnableDocking(CBRS_ALIGN_ANY);
m_wndColor.SetWindowText(_T("颜色"));
return 0;
}
IDD_COLOR是CDialogBar的对话框ID,ID_VIEW_COLOR是一个菜单资源id,在
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_COMMAND_EX(ID_VIEW_COLOR, OnBarCheck)
ON_UPDATE_COMMAND_UI(ID_VIEW_COLOR, OnUpdateControlBarMenu)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
时,工具条可以显示和隐藏。
想在CDialogBar上添加按钮消息还需要修改如下:
BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
// TODO: Add your specialized code here and/or call the base class
if (m_wndColor.OnCmdMsg(nID,nCode,pExtra,pHandlerInfo))
return TRUE;
return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
m_wndColor为CDialogBar对象,这样,按钮的消息可以映射到自己的类中。
这里增加一条关于对话框上响应键盘按键消息,重载
BOOL CXXXDlg::PreTranslateMessage(MSG* pMsg)
{
if( pMsg->message>=WM_KEYDOWN && pMsg->message<=WM_KEYUP)
{
this->SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam);
return TRUE;
}
else
return CDialog::PreTranslateMessage(pMsg);
}
这样就可以在对话框上重载WM_KEYDOWN和WM_KEYUP来编写代码了。