最近要写一个MFC的对话框程序,发现要把MFC的对话框写的有色彩点并不容易,不像在C#里设置属性指就好,而是要自己去写一些代码完成对话框的绘画操作。比如一个简单的鼠标移入、移出操作,都要自己去写代码。由于我只用到了Button和Static两种控件,一切看上去还是比较顺利,所以谈谈自己的经验。

1、对话框的背景
MFC中没有属性能够设定对话框的背景颜色或是图片,需要我们在程序中进行操作。首先,需要实现WM_CTLCOLOR的消息操作,通过这个消息我们能够控制对话框以及Static控件(包括Group)的背景色、前景色。该消息的处理函数原型如下:
HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
其中,通过pDC能够文件的颜色、背景模式,通过pWnd可以获取正在绘制的控件ID,通过nCtlColor可以判断当前正在绘制的控件类型。这里我需要控制对话框的背景,所以要进行如下操作:
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    if (nCtlColor == CTLCOLOR_DLG)
{
return m_backgroundBrush;    //返回对话框背景的画刷
}
else if (nCtlColor == CTLCOLOR_STATIC)
{
pDC->SetBkMode(TRANSPARENT);    //所有Static控件的背景色为透明
        if (pWnd->GetDlgCtrlID() == IDC_NOTE)
        {

pDC->SetTextColor(RGB(255, 255, 255));    //针对特殊的static控件,设置单独的文字颜色

        }
}
return hbr; //不是要自绘的控件,返回默认值
2、按钮(Button)控件
一开始很奇怪,在WM_CTLCOLOR的消息处理函数进行如下操作竟然没有用:

            if (pWnd->GetDlgCtrlID() == IDB_TEST)  //按钮文字颜色
            {

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

            }
    原来按钮控件的颜色、背景等属性无法通过WM_CTLCOLOR消息实现,要改变这些属性,就必须要自己从CButton类继承一个类,然后改写其绘画函数——DrawItem。通过DrawItem函数的参数可以获取控件的大小、状态、类型、绘画DC等信息,有了它们,重绘Button就简单了。下面给出简单实例:
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (lpDrawItemStruct->CtlType != ODT_BUTTON)  //由于继承自CButton,这一句肯定成立
{
return;
}
CRect rect =  lpDrawItemStruct->rcItem;
CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
UINT state = lpDrawItemStruct->itemState;
TCHAR strText[MAX_PATH] = {0};
::GetWindowText(m_hWnd, strText, MAX_PATH);
//获取按钮的状态
if (state & ODS_FOCUS)
{
m_bSelected = TRUE;
}
else
{
m_bSelected = FALSE;
}
//根据按钮的状态填充按钮的底色
if (m_bOver)
{
pDC->FillRect(&rect, &m_overBrush); 
}
else if (m_bSelected)
{
pDC->FillRect(&rect, &m_selectedBrush); 
}
else
{
pDC->FillRect(&rect, &m_normalBrush); 
}
// 画按钮标题,水平和垂直都居中。把DC当作一个画布
// 如果要使DT_VCENTER(垂直居中)有效,必须同时设置DT_SINGLELINE(单行)风格
if (_tcslen(strText) > 0)
{
pDC->SelectObject(m_font);
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255, 255, 255));
pDC->DrawText(strText, &lpDrawItemStruct->rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER); 
}
}

但是写了以上代码,发现还是不管用,原来,还需要设置按钮的属性为自绘类型,即需要设置BS_OWNERDRAW属性。这个可以在对话框的OnInitDialog函数或Button类的PreSubClassWindow函数中,调用Button的SetButtonStyle方法设置,如下:
UINT uStyle = GetButtonStyle();       // 得到按钮的愿风格
    SetButtonStyle(uStyle | BS_OWNERDRAW);     // 加入自画风格
为了判断按钮当前的状态,如是否有鼠标停留、焦点等,就需要跟踪鼠标的移动,这个可以通过WM_MOUSEMOVE消息实现。但是鼠标移入、移出的操作无法通过Vc的Wizard实现,在Vs2010里可以通过Wizard添加,但是函数不会被调用。为了能够知道鼠标移入、移出操作,需要在WM_MOUSEMOVE消息中增加如下代码,已跟踪鼠标事件:
if (!m_bTrack)    //记录是否已经设置跟踪事件
{
TRACKMOUSEEVENT ent = {0};
ent.dwFlags = TME_HOVER | TME_LEAVE;
ent.cbSize = sizeof(TRACKMOUSEEVENT);
ent.dwHoverTime = 10;
ent.hwndTrack = this->m_hWnd;
m_bTrack = TrackMouseEvent(&ent);
}
通过以上代码,我们就可以收到WM_MOUSEHOVER、WM_MOUSELEAVE事件,通过将鼠标停留时间ent.dwHoverTime(触发WM_MOUSEHOVER的时间)设置为足够短,我们就可以模拟出鼠标移入事件。为了能够处理这两个消息,需要通过MFCWizard增加WM_MOUSEHOVER、WM_MOUSELEAVE的事件处理函数。
    void CMyButton::OnMouseHover(UINT nFlags, CPoint point)
{
m_bOver = TRUE;
InvalidateRect(NULL, TRUE);
CButton::OnMouseHover(nFlags, point);
}
    void CMyButton::OnMouseLeave()
{
m_bTrack = FALSE;
m_bOver = FALSE;
InvalidateRect(NULL, FALSE);
CButton::OnMouseLeave();
}
3、Static控件
虽然可以通过对话框的WM_CTLCOLOR消息设置Static控件的字体颜色和背景模式,但是如果要更好地控制其字体、背景等属性,以及添加鼠标事件,就要自己写代码了。方法很简单,和Button类似,需要自己写一个继承自CStatic的类,然后改写DrawItem方法,实现自己的绘画方法。
    只是有一点需要注意,默认情况下Static是不发送消息的,即鼠标点击、移动等事件是没有效果的,需要设置SS_NOTIFY属性,这可以在继承Static类的PreSubClassWindow中进行入操作设置:
ModifyStyle(SS_TYPEMASK, SS_OWNERDRAW|SS_NOTIFY);
以上代码同时设置自绘和消息通知属性。
4、无标题对话框的移动
在Windows的应用程序中,都可以通过点击标题栏拖拽窗口进行移动,但是如果窗口没有标题栏怎么办呢,即将对话框的Border属性设置为None,如何实现窗口移动呢?在我的对话框应用中,在窗口顶部放了一个Static控件,想把它作为窗口的标题栏,通过拖拽Static空间拖动窗口。有两种方法可以实习这个目的。
一个很容易想到的方法是写一个继承自CStatic类的自绘控件,然后关联该类的对象到充当标题栏的Static控件。通过处理Static控件的WM_MOUSEMOVE、WM_LBUTTONDOWN、WM_LBUTTONUP消息,就可以得知鼠标是否按下、移动、松开,然后在WM_MOUSEMOVE的处理函数计算鼠标移动的距离,然后获得父窗口的指针,通过MoveWindow函数移动父窗口。显然,这种方法比较复杂,需要进行的操作也比较繁琐。
    既然点击标题栏能够移动窗口,而点击其他地方却效果不同,那么windows肯定通过什么标志来判断要采取什么操作,我们应该能够不需要自己去实现移动窗口,而是告诉Windows,点击Static这个“标题”时就是点击真正的标题栏。控件在响应点击操作之前,都会发送WM_NCHITTEST消息,用于判断鼠标点击的位置,而消息处理函数的返回值就指出了位置。WM_NCHITTEST的处理函数如下:
    LRESULT CWinAppDlg::OnNcHitTest(CPoint point)
{
CRect rect;
GetDlgItem(IDC_TITLE)->GetClientRect(rect);
ClientToScreen(rect);
return rect.PtInRect(point) ? HTCAPTION : CDialogEx::OnNcHitTest(point);
}
在上面的代码中,首先获得Static控件IDC_TITLE的位置,然后判断鼠标点击位置是否位于控件内,如果是,则返回HTCAPTION,告诉Windows点击的是标题栏,否则返回默认值。显然这种移动窗口的做法要简单的多,而且它利用MFC的原理进行操作,更稳定也更具兼容性。这几句代码也有一个限制,即标题栏只能是Static控件,因为Static默认是不接收事件、消息,所以WM_NCHITTEST由对话框进行处理,如果是Button等其他控件,WM_NCHITTEST就会发送到控件而不是对话框上。

转载于:https://blog.51cto.com/jslmes/1161756

MFC的Button和Static控件相关推荐

  1. 使用CvvImage类在MFC的static控件显示图片

    使用OpenCV的库,可以非常便捷地实现对图像的各种操作.在CTestDlg对话框中放置一个picture static控件,ID为IDC_STATIC,如下函数即可实现显示图片的功能.根据此方法,可 ...

  2. 用回车键实现MFC对话框中TAB键控件输入焦点在控件中跳转的效果(转)

    用回车键实现MFC对话框中TAB键控件输入焦点在控件中跳转的效果(转) 版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明 http://hcq11.blogbus.com/logs/5 ...

  3. 关于Static控件背景透明时文本覆盖重影的问题

    2019独角兽企业重金招聘Python工程师标准>>> 关于Static控件背景透明时文本覆盖重影的问题 通过映射OnCtlColor消息,而后在该函数中使用pDC->SetB ...

  4. MFC 对话框Picture Control(图片控件)中静态和动态显示Bmp图片

    最近有同学问我如何实现MFC基于对话框在图片控件中加载图片?其实使用MFC显示图片的方法各种各样,但是还是有些同学不知道怎样显示.以前在<数字图像处理>课程中完成的软件都是基于单文档的程序 ...

  5. sdk编程改变static控件字体和颜色

    //关于对话框中要处理的控件的ID是IDC_MYSTATIC //"关于"框的消息处理程序. LRESULT CALLBACK About(HWND hDlg, UINT mess ...

  6. 【转】修改static控件背景颜色和文字颜色

    当 static 控件或具有 ES_READONLY 风格的 edit 控件被绘制时,会向父窗口发送 WM_CTLCOLORSTATIC 消息.如果我们在窗口过程中处理该消息,就必须返回一个画刷句柄, ...

  7. MFC设置对话框背景色及控件颜色

    MFC设置对话框背景色及控件颜色 一.使用背景图片更改对话框背景色 在对话框源文件void CxxDlg::OnPaint()函数中 if (IsIconic()) { (这里省略) } else { ...

  8. MFC中使用TAB Control控件

    2019独角兽企业重金招聘Python工程师标准>>> MFC中使用TAB Control控件 MFC中使用TAB Control控件(转) 假如我现在有个SDI程序,View是Fo ...

  9. 使用button触发FileUpload控件的click事件

    点击button触发FileUpload控件的click事件 通过点击button按钮触发FileUpload控件,避免因浏览器不同而导致FileUpload控件样式发生变化,影响页面效果. 注意:需 ...

最新文章

  1. the mysql is running_Mysql报错:TheMySQLserverisrunningwiththe--skip-grant-
  2. eclipse html自动编译,eclipse不自动编译解决方法 不编译要怎么办
  3. android进出动画有白屏,Android启动白屏原因及解决方案
  4. 查看电脑重启日志_系统日志看硬盘故障图文教程,电脑日志查看磁盘硬盘坏道问题方法...
  5. 阿里P8成长路线!我的头条面试经历分享,吊打面试官系列!
  6. 软件架构(7)---软件架构设计-五视图方法论
  7. 计算机基础线性代数还有,大学计算机基础 word作业.doc
  8. CCNA培训课总结笔记--RIP的基本配置(五)
  9. java ftp取远程服务器时间_在 Java 中如何获取 FTP 服务器上的文件修改时间
  10. 不知名程序员金山云大米云主机体验日志
  11. 银河麒麟操作系统常用问题及解决方法
  12. 小学计算机无生试讲教案,小学数学无生试讲教案(9页)-原创力文档
  13. python stacktrace_pystack--python stack trace--让python打印线程栈信息
  14. Arcgis 空间分析—学校选址
  15. Vulkan_Ray Tracing 09_反射
  16. PMP-我是如何两周拿下5A的
  17. [几何] BZOJ 4246 两个人的星座
  18. 关键字驱动自动化测试
  19. async 函数的含义和用法
  20. 2004年6月30日

热门文章

  1. Word 2010 制作文档结构之图标自动编号设置
  2. MVC Html.AntiForgeryToken() 防止CSRF***
  3. DDD为何叫好不叫座?兼论DCI与业务分析的方法论
  4. openfire 插件开发例子
  5. tcptracerte参数_TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute【转】
  6. java根据模板生成PDF
  7. canvas特效代码详解(2)
  8. centos安装禅道的步骤
  9. 孤掌难鸣-------堵水眼
  10. System.Xml名称空间下的支持DOM的类型