C语言dialog函数用法,DialogBar的用法技巧

【文中一部分是转载】

在单文档中创建DialogBar

当创建一些简单的形如只包含了一些BUTTON的DialogBar的时候,是不需要从CDialogBar派生,因为CDialogBar本身就是从CControlBar派生而来,它可以接收任何的通告消息。

然而,在一些诸多较为复杂的情形下,我们就需要利用CDialogBar派生出自己的类了。

dialogbar包含了具有drop-down属性的COMBOBOX;

dialogbar包含了treeview或者tree控件,listview, list控件;

dialogbar包含了ActiveX控件;

诸如上面所说的任何较为复杂的情形下,我们都应该对Dialogbar进行派生,以便在派生的类中对其他的控件进行初始化。因为在ClassWizard并没有支持以CDialogBar为基类的派生。所以我们必须自己手动完成该派生过程。这篇文章就是要阐述如何将CDialog的派生类转换为CDialogBar的派生类。

在开始正题之前,有必要说明一点:CDialogBar类是从CControlBar类派生而来的,而CControlBar类则是从CWnd类派生而来,所以CDialogBar并非CDialog的派生类。

首先创建一个DialogBar类型的dialog资源(在创建对话框资源的时候,单击Dialog选项前面的"+"号进行选择)。并以CDialog类为基类生成派生类,然后按照下面的步骤对所产生的类进行修改。

在类的声明中,将基类CDialog改为CDialogBar,同时将.cpp文件中,BEGIN_MESSAGE_MAP中的基类也改为CDialogBar.

修改.h文件和.cpp文件中的构造函数,同时修改DoDataExchange()函数,具体修改后的效果如下图:

//修改前的代码:

1 CMyDlgBar (CWnd* pParent = NULL); // standard constructor2 IMPLEMENT_DYNAMIC(CDlg_Bar, CDialog)3 CMyDlgBar:: CMyDlgBar (CWnd* pParent )4 : CDialog(CMyDlgBar::IDD, pParent)5 {6 ...7 8 void CMyDlgBar::DoDataExchange(CDataExchange* pDX)9 {10 CDialog::DoDataExchange(pDX);11 ...12 BEGIN_MESSAGE_MAP(CDlg_Bar, CDialog)

//修改后的代码

1 CMyDlgBar (); // standard constructor2 IMPLEMENT_DYNAMIC(CDlg_Bar, CDialogBar)//这句不可忘记做修改3 CMyDlgBar:: CMyDlgBar ()4 {5 ...6 7 void CMyDlgBar::DoDataExchange(CDataExchange* pDX)8 {9 CDialogBar::DoDataExchange(pDX);10 ...

11 12 BEGIN_MESSAGE_MAP(CDlg_Bar, CDialogBar)

3.从文章开始所谈到的继承关系可以看出,在CDialogBar中并没有用来响应WM_INITDIALOG消息的虚函数。我们需要将.h文件中用来响应WM_INITDIALOG消息的虚函数OnInitDialog变化成为一个消息响应函数。首先将.h文件中的“virtual BOOL OnInitDialog();”从文件中删掉,然后在相同的位置上添加“afx_msg LONG OnInitDialog ( UINT, LONG );”函数。然后在.cpp文件中做相应的改动,并将.cpp文件中消息映射ON_WM_INITDIALOG()改为OM_MESSAGE(WM_INITDIALOG, OnInitDialog),例如:

//在头文件中

1 class CMyDlgBar : public CDialogBar2 {3 ...4 // Implementation5 protected:6 7 // Generated message map functions8 //{{AFX_MSG(CMyDlgBar)9 virtual BOOL OnInitDialog(); //

1 //在源文件中2 BEGIN_MESSAGE_MAP(CMyDlgBar, CDialogBar)3 ...4 ON_MESSAGE(WM_INITDIALOG, OnInitDialog ) //

//将函数实现从:BOOL CMyDlgBar::OnInitDialog()

{

CDialog::OnInitDialog(); //

{// BOOL bRet = HandleInitDialog(wParam, lParam);if (!UpdateData(FALSE))

{

TRACE0("Warning: UpdateData failed during dialog init.\n");

}

...return bRet;

到此为止所有需要修改的地方都已经完成,剩下的就是使用了。在CMainFrame中定义变量,并在CMainFrame::OnCreate()函数中添加代码:

1 if (!m_wndDlgBar.Create(this, IDD_DIALOGBAR, WS_CHILD | WS_VISIBLE | CBRS_BOTTOM2 | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC, IDD_DIALOGBAR))3 {4 TRACE0("Failed to create Dialog bar\n");5 return -1; // fail to create6 }7 8 //如果需要实现可停靠的功能,则添加如下代码:9 m_wndDlgBar.EnableDocking(CBRS_ALIGN_ANY );10 EnableDocking(CBRS_ALIGN_ANY); //申明窗口边界可被停靠,如果上文已出现过,可不必写这句了11 DockControlBar(&m_wndDlgBar, AFX_IDW_DOCKBAR_BOTTOM);

改变DialogBar的背景及其控件的颜色

在CMyDlgBar类中响应WM_CTLCOLOR消息:

HBRUSH CMyDlgBar::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)

{

HBRUSH hbr = CDialogBar::OnCtlColor(pDC, pWnd, nCtlColor);

int nID=pWnd->GetDlgCtrlID();

if (nID==IDC_EDIT1) //编辑控件

{

pDC->SetBkMode(TRANSPARENT); //文字背景模式

pDC->SetTextColor(RGB(255,0,0));

return CreateSolidBrush(RGB(255,255,200));

}

if (nID==IDD_DIALOGBAR) //自身DialogBar

{

return CreateSolidBrush(RGB(122,122,122));

}

return hbr;

}

上面的List Control是用位图画刷装饰的,下面将为List Control贴图:

为List Control添加一个类CMyList,基类CListBox,在类中响应WM_ERASEBKGND消息:

BOOL CMyList::OnEraseBkgnd(CDC* pDC)

{

pDC->SetBkMode(TRANSPARENT);

if (!m_compatibleDC.m_hDC) //CDC m_compatibleDC;在MyList头文件中加此句 {

m_compatibleDC.CreateCompatibleDC(pDC);

}

CBitmap bitmap;

bitmap.LoadBitmap(IDB_BITMAP1);

BITMAP bit;

bitmap.GetBitmap(&bit);

m_compatibleDC.SelectObject(&bitmap);

CRect rect;

GetClientRect(&rect);

pDC->StretchBlt(0,0,rect.Width(),rect.Height(),&m_compatibleDC,0,0,bit.bmWidth,bit.bmHeight,SRCCOPY);

return FALSE;

//return CDialog::OnEraseBkgnd(pDC);

}

接下来,将列表框资源和类CMyList关联起来,在CMyDlgBar类的头文件中加入CMyList m_list;源文件的DoDataExchange函数中加入

DDX_Control(pDX, IDC_LIST1, m_list);这样就可以了。

实用技巧(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());

}

(5)去掉CMyDlgBar浮动时的标题栏

响应WM_WINDOWPOSCHANGED消息:

void CDlg_Bar::OnWindowPosChanged(WINDOWPOS* lpwndpos)

{

CDialogBar::OnWindowPosChanged(lpwndpos);

static BOOL m_bMenuRemoved=TRUE;

if( IsFloating() )

{

if( m_pDockBar && !m_bMenuRemoved )

{

CWnd* pParent = ((CWnd*)m_pDockBar)->GetParent();

if( pParent->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)))

{

pParent->ModifyStyle( WS_CAPTION, 0, 0 );

m_bMenuRemoved = TRUE;

}

}

}

else if( m_bMenuRemoved ) {

m_bMenuRemoved = FALSE;

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值