分享

用MFC做漂亮界面之美化对话框

 行走在理想边缘 2018-05-23

在windows开发当中做界面的主要技术之一就是使用MFC,通常我们看到的QQ,360,暴风影音这些漂亮的界面都可以用MFC来实现。今天我们来说一下如何用MFC美化对话框,默认情况下,对话框的背景如下:

那么,我们如何将它的背景变成如下界面呢,而且还要保留对话框的移动功能,漂亮背景如下:

为了实现美化对话框背景的效果,我们需要让我们的对话框响应WM_CTLCOLOR消息,每当我们的对话框或者它的子控件需要重绘时,我们的对话框都会收到这个消息,

因此,我们需要为对话框添加WM_CTLCOLOR的消息响应函数,完成对消息的处理,WM_CTLCOLOR的响应函数定义如下:

  1. HBRUSH CMFCDialogUIDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  
  2. {  
  3.     HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);  
  4.   
  5.     if (pWnd == this)  
  6.     {  
  7.         return m_bkBrush;  
  8.     }  
  9.   
  10.     return hbr;  
  11. }  
当我们的对话框需要重绘的时候,我们的对话框就会收到WM_CTLCOLOR消息,然后我们的对话框处理函数会调用OnCtlColor函数来处理该消息,在这个函数中,pDC代表我们要绘制的上下文环境,pWnd代表我们要绘制的窗口指针,nCtlColor代表我们要绘制的窗口类型,在函数的内部我们首先调用父类的OnCtlColor,目的是为了对该消息做默认处理,这是MFC消息响应函数的惯用写法,但是在我们这里,我们不能使用默认处理返回的画刷,所以我们需要做一个特殊的判断,如果pWnd指向的窗口地址是当前对话框,那么我们就返回m_bkBrush,这个画刷是一个图像画刷,它会在我们的对话框客户区绘制我们想让它显示的图片。下面我们看一下m_bkBrush是如何创建的,首先在我们的对话框的头文件中增加一个CBrush变量,变量名是m_bkBrush,然后在对话框的OnInitDialog中初始化它,OnInitDialog的定义如下:
  1. BOOL CMFCDialogUIDlg::OnInitDialog()  
  2. {  
  3.     CDialogEx::OnInitDialog();  
  4.   
  5.     // 将“关于...”菜单项添加到系统菜单中。  
  6.   
  7.     // IDM_ABOUTBOX 必须在系统命令范围内。  
  8.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  9.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  10.   
  11.     CMenu* pSysMenu = GetSystemMenu(FALSE);  
  12.     if (pSysMenu != NULL)  
  13.     {  
  14.         BOOL bNameValid;  
  15.         CString strAboutMenu;  
  16.         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);  
  17.         ASSERT(bNameValid);  
  18.         if (!strAboutMenu.IsEmpty())  
  19.         {  
  20.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  21.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  22.         }  
  23.     }  
  24.   
  25.     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动  
  26.     //  执行此操作  
  27.     SetIcon(m_hIcon, TRUE);         // 设置大图标  
  28.     SetIcon(m_hIcon, FALSE);        // 设置小图标  
  29.   
  30.     // TODO:  在此添加额外的初始化代码  
  31.   
  32.     CString strBmpPath = _T(".\\res\\Background.png");  
  33.   
  34.     CImage img;  
  35.   
  36.     img.Load(strBmpPath);  
  37.   
  38.     MoveWindow(0, 0, img.GetWidth(), img.GetHeight());  
  39.   
  40.     CBitmap bmpTmp;  
  41.   
  42.     bmpTmp.Attach(img.Detach());  
  43.   
  44.     m_bkBrush.CreatePatternBrush(&bmpTmp);  
  45.   
  46.     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE  
  47. }  
现在我们看一下,在OnInitDialog中,我们都做了什么,首先,我们创建了一个CString变量strBmpPath,用它指向我们的图片文件,然后我们创建了一个CImage变量img,这个变量可以方便的加载各种格式的图像文件,所以我们使用它的目的是为了方便加载png格式的文件,MoveWindow的目的是为了调整我们的对话框客户区的大小,使客户区的大小与图片的大小一致,然后我们创建了一个CBitmap类型变量bmpTmp,使用它是因为CBrush的成员函数CreatePatternBrush的参数要求输入这种类型的参数,所以必须将img转换成CBitmap,转换的方法是bmpTmp.Attach(img.Detach()),img.Detach会释放图像的句柄,并且返回这个句柄,bmpTmp使用Attach绑定img返回的图像句柄,从而完成了对象类型的转换,最后调用CreatePatternBrush,这个函数的功能是使用传递给它的图像创建一个图像画刷,然后在OnCtlColor中,使用它填充对话框的背景,程序运行效果如下:

现在虽然程序的客户区已经变成了对话框的背景,但是对话框原来的标题栏和背景图片的标题栏重复,看起来很别扭,通过设置对话框的Border属性可以消除原来的标题栏,设置如下:

Border:None

再次编译,运行程序,效果如下:

现在的对话框背景已经和我们设想的基本一致,还有一点小瑕疵,大家仔细观察对话框的底边,左下角和右下角有多于的像素,下面我们通过代码消除它。

在OnInitDialog尾部追加如下代码:

  1. CRgn rgnTmp;  
  2. RECT rc;  
  3. GetClientRect(&rc);  
  4. rgnTmp.CreateRoundRectRgn(rc.left + 3, rc.top + 3, rc.right - rc.left - 3, rc.bottom-rc.top -3, 6, 6);  
  5. SetWindowRgn(rgnTmp, TRUE);  
通过以上的代码可以让对话框变成一个圆角矩形,这样就可以去掉边角的点,程序最终运行效果如下:

现在这个对话框的背景已经完全符合我们的要求,但是它现在不能拖动,因为它的标题栏是假的,所以,我们最后一个目标就是让这个窗口可以拖动,如何才能让它移动呢?

Windows只允许我们拖动对话框的标题栏,当我们的鼠标在对话框上拖动的时候,对话框会收到一个WM_NCHITTEST消息,默认的消息处理函数会判断当前的鼠标是否在对话框的标题栏,如果在就返回HTCAPTION标志,否则就返回其它标志,当返回HTCAPTION标志的情况下,系统就会允许对话框拖动,所以我们可以欺骗windows系统,让WM_NCHITTEST的响应函数永远返回HTCAPTION标志就可以了,为对话框添加WM_NCHITTEST响应函数,代码如下:

  1. LRESULT CMFCDialogUIDlg::OnNcHitTest(CPoint point)  
  2. {  
  3.     // TODO:  在此添加消息处理程序代码和/或调用默认值  
  4.     LRESULT ret = CDialogEx::OnNcHitTest(point);  
  5.     return (ret == HTCLIENT) ? HTCAPTION : ret;  
  6. }  
重新编译代码,现在的对话框背景已经美化完成,并且这个对话框可以拖动。

下篇文章,我们会为这个对话框添加美化的按钮。




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多