知识大全 创建有个性的对话框之MFC篇

Posted 消息

篇首语:有志者自有千计万计,无志者只感千难万难。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 创建有个性的对话框之MFC篇相关的知识,希望对你有一定的参考价值。

创建有个性的对话框之MFC篇  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

想使自己的软件与众不同就要给软件加点 色 一个颜色搭配协调的窗口要比windows千篇一律的灰底黑字更能吸引别人的眼球 设想如果浏览器显示的网页都是白底黑字 还会有那么多的mm喜欢上网吗?可能互联网的人气将下降一半 做个出色的界面对于老手来说可能不在话下 但是对于新手来说还是无从下手 使用BCGControlBar和Xtreme Toolkit是个很好的选择 不过对于一个小程序使用这么大的库未免有头重脚轻的感觉 其实不使用这些庞然大物一样可以做个很 色 的界面 本文就结合CSDN论坛上经常被问起的问题 介绍几个给对话框上色的方法 本文的方法都是针对MFC程序的 其他方法请参看 创建有个性的对话框之ATL/WTL篇

  第一步 改变对话框的背景颜色

  如何改变对话框的背景颜色这个问题常常出现在论坛上 可见大家对Windows默认的灰色对话框是多么不满 MFC程序修改对话框的背景和文字颜色最简单的方法就是调用SetDialogBkColor函数 SetDialogBkColor是CWinApp类的成员函数 以下是该函数的原型

void CWinApp::SetDialogBkColor(COLORREF clrCtlBk COLORREF clrCtlText);

  请注意 SetDialogBkColor函数并不是对Windows的某个API的封装 他是MFC框架的一部分 所以不使用MFC的程序也就不能享受这种方便 这个函数的使用很简单 在程序的CWinApp派生类的InitInstance函数中添加一行代码就行了

SetDialogBkColor(RGB( ) RGB( ));

  图 就是运行效果

  

  图 SetDialogBkColor效果图

  使用SetDialogBkColor也有局限的地方 那就是所有的控件文字颜色都一样 不能针对不同的控件设置不同的文字颜色 还有就是不能设置Edit控件的颜色 不使用SetDialogBkColor函数 直接编写代码控制对话框的背景颜色和控件文字颜色也不是很困难的事情 并且这种方法能够提供更灵活的颜色设置方案 比如对不同类型的控件使用不同的文字颜色 使用高亮度的背景颜色突出某个控件等等 最重要的是能够控制Edit控件的文字和背景颜色 下面就介绍这种方法

  首先是改变对话框的背景颜色 当Windows系统需要重画某个窗口客户区的背景的时候 就会向该窗口发送WM_ERASEBKGND 消息 窗口的处理过程响应这个消息重新画窗口的背景 这个过程称之为 自画 改变对话框的背景颜色的原理很简单 就是响应这个消息 用自定义的颜色填充对话框的客户区背景 代替对话框窗口默认的背景填充动作 许多新手经常问 为什么在class wizard中找不到对话框的WM_ERASEBKGND消息 是不是对话框没有这个消息 ?其实对话框也是窗口 它也有WM_ERASEBKGND消息 只是MFC的class wizard使用的dialog过滤器将其过滤掉了(只是在message窗口的显示中过滤了 并不是真的不响应这个消息) 为的是代码编写过程中突出对话框专有的消息和控件事件 如图 所示 只要在class wizard中的 class info table标签下将消息过滤器改成Windows就可以在对话框的消息列表中看到WM_ERASEBKGND了

  

  图 修改消息过滤器

  现在通过class wizard添加WM_ERASEBKGND的消息响应函数 并如下所示修改这个函数

BOOL CCustDlgDlg::OnEraseBkgnd(CDC* pDC)   CRect rcClient;  GetClientRect(&rcClient);  pDC >FillRect(&rcClient &m_brBkgnd);  return TRUE;//  return CDialog::OnEraseBkgnd(pDC);

  m_brBkgnd是个CBrush 在此之前已经初始化过了 关键代码是最后返回TRUE 而不是默认的调用基类函数 返回TRUE意在告诉Windows 我已经画过背景了 你不要再画了 现在来看看运行的效果

  

  图 重画背景的效果

  使用位图作为对话框的背景也不难 就是在整个客户区画一个位图背景

   

  第二步 改变控件的颜色

  看起来不如刚才效果好 控件文字的颜色和背景色都没有改变 这是因为我们还没有处理WM_CTLCOLOR消息 WM_CTLCOLOR是Windows的控件向其父窗口发送最频繁的通知消息之一 例如 许多控件发送WM_CTLCOLOR消息给父窗口 让父窗口提供画刷来画自己的背景 MFC的窗口类对这个通知消息特殊对待 如果父窗口没有处理这个通知消息 MFC的窗口类就根据WM_CTLCOLOR通知消息的来源将这个WM_CTLCOLOR消息发送回控件 让控件自己处理 这就是所谓的 消息反射 不仅是WM_CTLCOLOR MFC对很多通知消息都做了反射 不过我们今天的例子没有使用 消息反射 我们在控件的父窗口 也就是对话框窗口处理这个通知消息 还有一点需要说明的是 WM_CTLCOLOR消息是 位的Windows平台的消息 在 位的Windows平台上取而代之的是一系列更明确的通知消息

  WM_CTLCOLORBTN   按钮控件 WM_CTLCOLORDLG   对话框 WM_CTLCOLOREDIT   编辑控件 WM_CTLCOLORLISTBOX   列表框控件 WM_CTLCOLORSCROLLBAR   滚动条控件WM_CTLCOLORSTATIC   静态文本控件

  MFC为了兼容性考虑 仍旧使用OnCtlColor响应这些消息 但是通过参数nCtlColor来具体的区分他们 在这个函数中 我们可以通过改变pDC参数的属性来改变控件的绘制 并返回相应的画刷句柄给控件 控件使用这个画刷画自己的背景 下面是我们修改后的OnCtlColor函数

HBRUSH CCustDlgDlg::OnCtlColor(CDC* pDC CWnd* pWnd UINT nCtlColor)   HBRUSH hbr = CDialog::OnCtlColor(pDC pWnd nCtlColor);    pDC >SetTextColor(m_clrText);  pDC >SetBkMode(TRANSPARENT);  return (HBRUSH)m_brBkgnd; //因为CBrush类实现了HBRUSH类型转换操作符  //  return hbr;

  图 就是这段代码的效果 在这里我们不分 青红皂白 向所有的控件返回我们自己的画刷 看起来不错 Edit控件的文字颜色也改了 但是好像多行Edit控件有了麻烦 看来需要对多行Edit控件特殊对待

  

  图 重载OnCtlColor之后的效果

  对于多行Edit控件特殊处理 如下所示 上面的问题解决了

HBRUSH CCustDlgDlg::OnCtlColor(CDC* pDC CWnd* pWnd UINT nCtlColor)   HBRUSH hbr = CDialog::OnCtlColor(pDC pWnd nCtlColor);    if(pWnd >GetDlgCtrlID() == IDC_EDIT_MULTI_LINE) //IDC_EDIT_MULTI_LINE是多行Edir控件的ID      pDC >SetTextColor(m_clrText);    return hbr;    else      pDC >SetTextColor(m_clrText);    pDC >SetBkMode(TRANSPARENT);    return (HBRUSH)m_brBkgnd;  

  上面的代码解决了IDC_EDIT_MULTI_LINE的问题 但是对每个多行Edit控件都要判断ID 下面的方法可以一劳永逸地解决多行编辑控件的问题

HBRUSH CCustDlgDlg::OnCtlColor(CDC* pDC CWnd* pWnd UINT nCtlColor)  HBRUSH hbr = CDialog::OnCtlColor(pDC pWnd nCtlColor);  TCHAR szClassName[ ];  ::GetClassName(pWnd >GetSafeHwnd() szClassName );  if(lstrcmpi(szClassName _T( Edit )) == ) //是Edit 控件      DWORD dwStyle = pWnd >GetStyle();    if((dwStyle & ES_MULTILINE)  == ES_MULTILINE) //多行edit控件          pDC >SetTextColor(m_clrText);      return hbr;        else          pDC >SetTextColor(m_clrText);      pDC >SetBkMode(TRANSPARENT);      return (HBRUSH)m_brBkgnd;        else //不是编辑控件      pDC >SetTextColor(m_clrText);    pDC >SetBkMode(TRANSPARENT);    return (HBRUSH)m_brBkgnd;  

  下面我们针对每个控件设置特殊的颜色 区分控件可以通过控件的ID 修改控件背景也很简单 直接返回相应的画刷就可以了 下面就是颜色设置的完整代码

HBRUSH CCustDlgDlg::OnCtlColor(CDC* pDC CWnd* pWnd UINT nCtlColor)  HBRUSH hbr = CDialog::OnCtlColor(pDC pWnd nCtlColor); TCHAR szClassName[ ]; ::GetClassName(pWnd >GetSafeHwnd() szClassName ); if(lstrcmpi(szClassName _T( Edit )) == ) //是Edit 控件   DWORD dwStyle = pWnd >GetStyle();  if((dwStyle & ES_MULTILINE)  == ES_MULTILINE) //多行edit控件     pDC >SetTextColor(m_clrText);   return hbr;    else     pDC >SetTextColor(m_clrText);   pDC >SetBkMode(TRANSPARENT);   return (HBRUSH)m_brBkgnd;    else //不是编辑控件   if(pWnd >GetDlgCtrlID() == IDC_STC_REDTEXT)     pDC >SetTextColor(RGB( ));   pDC >SetBkMode(TRANSPARENT);   return (HBRUSH)m_brBkgnd;    else if(pWnd >GetDlgCtrlID() == IDC_STC_BLUETEXT)     pDC >SetTextColor(RGB( ));   pDC >SetBkMode(TRANSPARENT);   return (HBRUSH)m_brBkgnd;    else if(pWnd >GetDlgCtrlID() == IDC_STC_BLUETEXHITEBACK)     pDC >SetTextColor(RGB( ));   pDC >SetBkMode(TRANSPARENT);   return (HBRUSH)m_brControlBkgnd ;    else if(pWnd >GetDlgCtrlID() == IDC_CHK_GREEN)     pDC >SetTextColor(RGB( ));   pDC >SetBkMode(TRANSPARENT);   return (HBRUSH)m_brBkgnd;    else if(pWnd >GetDlgCtrlID() == IDC_RAD_BLUE)     pDC >SetTextColor(RGB( ));   pDC >SetBkMode(TRANSPARENT);   return (HBRUSH)m_brBkgnd;    else if(pWnd >GetDlgCtrlID() == IDC_CHK_GREEN )     pDC >SetTextColor(RGB( ));   pDC >SetBkMode(TRANSPARENT);   return (HBRUSH)m_brControlBkgnd ;    else if(pWnd >GetDlgCtrlID() == IDC_RADIO )     pDC >SetTextColor(RGB( ));   pDC >SetBkMode(TRANSPARENT);   return (HBRUSH)m_brControlBkgnd ;    else     pDC >SetTextColor(m_clrText);   pDC >SetBkMode(TRANSPARENT);   return (HBRUSH)m_brBkgnd;   

  现在看看效果

  

  图 修改OnCtlColor之后的效果

  上面的代码是根据控件ID来设置颜色 还可以根据控件的类型统一设置某种控件的颜色 这就要用到nCtlColor参数 nCtlColor参数用来指明发送这个通知消息的控件的类型 nCtlColor可以是以下取值

  CTLCOLOR_BTN CTLCOLOR_DLG CTLCOLOR_EDIT CTLCOLOR_LISTBOX CTLCOLOR_MSGBOXCTLCOLOR_SCROLLBAR CTLCOLOR_STATIC

  第三步 使用位图作对话框的背景

  使用位图作为对话框的背景也很简单 就是在OnEraseBkgnd中用位图填充客户区 只是在OnCtlColor中需要注意返回空画刷代替原来的画刷 返回空画刷是为了阻止控件绘制自己的背景 从而破坏位图背景的完整性 但是有时候返回空画刷会对其他控件产生不良影响 所以我们只处理了CTLCOLOR_BTN和CTLCOLOR_STATIC两种类型的消息

HBRUSH CBmpBkgndDlg::OnCtlColor(CDC* pDC CWnd* pWnd UINT nCtlColor)  HBRUSH hbr = CDialog::OnCtlColor(pDC pWnd nCtlColor);  if(nCtlColor == CTLCOLOR_BTN || nCtlColor == CTLCOLOR_STATIC)   pDC >SetTextColor(RGB( ));  pDC >SetBkMode(TRANSPARENT);  return (HBRUSH)m_HollowBrush;   pDC >SetTextColor(RGB( )); pDC >SetBkMode(TRANSPARENT); return hbr;

  下面是使用位图背景和空画刷的效果

  

  图 使用位图背景的效果

   

  第四步 单独处理按钮控件

  现在看来按钮控件还是影响整体效果 WM_CTLCOLORBTN好像对于push button类型的按钮控件没有效果 不过push button也是支持自画的 在使用自画按钮之前 我们先来看看控件自画的原理 Windows的控件都有默认的外观 但是许多控件有支持 自画 也就是让用户定制控件的外观 当给一个控件指定自画的样式之后 控件在重画自己的时候向父窗口发送WM_MEASUREITEM和WM_DRAWITEM消息 父窗口响应这两个消息 定位控件的大小并绘制控件 从而使控件有定制的外观 但是每个控件的自画都由父窗口完成加重了父窗口的负担 也不利于代码重用 所以 MFC对这些消息进行了反射处理 就是将消息发还位控件 由控件响应消息 自己绘制 这样将自画代码封装在控件类中 提高了代码的重用性 很多MFC的控件类都自己处理这两个消息 派生类可以重载MeasureItem和DrawItem自己画控件的外观 CButton就是这样的控件类

  现在就来做一个自画的按钮类 首先从CButton派生一个类 我们命名为CSMButton 然后重载DrawItem和PreSubclassWindow 重载PreSubclassWindow的原因是在CSMButton子类化按钮控件之前先给按钮添加BS_OWNERDRAW样式 否则按钮就不会向父窗口发送WM_DRAWITEM消息 MFC的消息反射就不会发生 我们的DrawItem就不会被调用 嗯 后果很严重 当然也可以让CSMButton的使用者自己给按钮添加BS_OWNERDRAW样式 但是会让人觉得没水平 嗯 后果也很严重 接下来添加对WM_CAPTURECHANGED WM_MOUSEMOVE WM_SETCURSOR和WM_KILLFOCUS四个消息的响应函数 对这四个消息的响应是为了给按钮增加更多的功能 比如使按钮看起来象工具栏的按钮 改变鼠标的形状等等

  关于CSMButton类的使用就像CButton一样 为按钮添加变量就行了 演示代码中包含了这个类的源代码以及用法 这里不在赘述 CSMButton类的功能很简单 但是完成了一个自画按钮的框架 大家可以修改代码实现自己的风格 网上也有很多这样的类 功能更强大 比如STButton等 现在看看CSMButton的效果

  

  图 使用自画按钮后的效果

  第五步 使用Picture Box控件

  想要在对话框上显示位图 可以使用很复杂的控件或CxImage之类的库 也可以很简单地使用Picture Box Picture Box默认的样式使Frame 需要手工改成Bitmap 如下图所示

  

  图 使用位图

  VC 的集成环境不支持 位位图的浏览和编辑 但是并不影响使用 本例使用的位图都是 位的 为的是省去调色板的处理 本人比较懒 使用如下代码就可以更改Picture Box中的位图

m_hCat = (HBITMAP)::LoadImage(AfxGetResourceHandle() MAKEINTRESOURCE(IDB_BITMAP ) IMAGE_BITMAP LR_CREATEDIBSECTION);GetDlgItem(IDC_STC_PICTURE) >SendMessage(STM_SETIMAGE IMAGE_BITMAP (LPARAM)m_hCat );

  装载位图还可以这样

m_hCat = (HBITMAP)::LoadImage(AfxGetResourceHandle() (LPCTSTR)IDB_BITMAP IMAGE_BITMAP LR_CREATEDIBSECTION);

  这是最终的效果

  

cha138/Article/program/net/201311/11335

相关参考

知识大全 求一篇英语预定客房的情景对话,最好带中文翻译,大概20句,谢谢各位大神了

求一篇英语预定客房的情景对话,最好带中文翻译,大概20句,谢谢各位大神了!Guest:Hello,isthatJinjiangHotel?你好,是锦江大酒店吗?Operator:Hello,thisi

——篇《“最有个性的官方网站”:成都新都区网上信访平台不设防》的新闻迅速红遍全国。该政府网站坚持不删帖、有问必答,甚至不

——篇《“最有个性的官方网站”:成都新都区网上信访平台不设防》的新闻迅速红遍全国。该政府网站坚持不删帖、有问必答,甚至不删骂人帖。对此现象的正确认识是_____。A、网络是民众实现表达权和监督权的最佳

知识大全 《金刚经》中须菩提与之对话的佛是什么佛,是释迦牟尼佛吗

《金刚经》中须菩提与之对话的佛是什么佛,是释迦牟尼佛吗?是释迦摩尼佛,如果读经,要入于心,见于行。《金刚经》读一遍自然有读一遍的好处,而这好处,亦无从得。个人觉得,学佛还是从三皈依开始。另外,《金刚经

知识大全 创建文明城市作文800字求几篇

创建文明城市作文800字求几篇创建文明城市从我做起绿化是城市的外衣,建筑是城市的骨架,环境是城市的容貌,市民是城市的灵魂。文明城市不仅是要看她的楼有多高,街道有多宽,种了多少树,栽了多少花,搞了多少景

月亮变你也变之满月篇

人们常说,“月有阴睛圆缺,人有悲欢离合”。此语也形象地说明。我们的命运与月亮一样变化不定,人月同理。现在。科学家已经有了充分的依据证明。我们的身体与情绪确实随着月亮的阴睛圆缺发生着微妙的变化。满月,即

月亮变你也变之残月篇

人们常说“月有阴晴圆缺,人有悲欢离合”,此语也形象地说明,我们的命运与月亮一样变化不定,人月同理。现在,科学家已经有了充分的依据证明,我们的身体与情绪确实随着月亮的阴晴圆缺发生着微妙的变化。残月就是月

月亮变你也变之新月篇

人们常说“月有阴晴圆缺,人有悲欢离合”,此语也形象地说明,我们的命运与月亮一样变化不定,人月同理。现在,科学家已经有了充分的依据证明,我们的身体与情绪确实随着月亮的阴晴圆缺发生着微妙的变化。有一种人,

知识大全 常见面试攻略之问答篇

面试过程是面对面斗智斗勇的过程,如果遇到以下问题,要学会积极应对。1.你对自己的未来有什么规划?如果说"我也没想过"或者"成为管理层",都显得你有些苍白,可以说"我希望自己的精力与专业知识能够融入所从

知识大全 Framework创建文件方式不同之处

Framework创建文件方式不同之处  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &

知识大全 Biztalk 开发之 如何快速创建架构

Biztalk开发之如何快速创建架构  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  使用Bizt