我们在写桌面程序时为了让界面好看,经常会用到窗体的自绘制功能,下面我来简单地介绍一下具体的做法,只要通过重载几个消息函数,里面添加几行代码即可实现漂亮的自绘制窗口,首先创建一个MFC对话框应用程序,然后在类视图中选择对话框类点击右键,选择“类向导”,VS2017里的这个类向导我个人觉得不友好,没有VC6.0和VS2003友好,不过没关系用多了就习惯了。
在类向导(ClassWizard)中选择WM_ERASEBKGND消息,并添加其处理函数OnEraseBkgnd(CDC* pDC),这个函数中添加重绘代码,当然也有人会问,对话框窗体重绘怎么不在WM_PAINT消息的处理函数OnPaint()中写呢?这是有windows窗口的重绘机制有关,每次重绘之前先会调用OnEraseBkgnd(CDC* pDC)消除先前内容,然后重绘,这样一来消除内容会导致窗口闪烁,所以我们直接在OnEraseBkgnd(CDC* pDC)中绘制内容,防止用白刷消除内容,这样就可以避免移动窗口时的闪烁问题,当然也可用双缓冲绘图来解决,关于双缓冲后续再介绍,双缓冲对于绘图应用很重要。窗体自绘制的代码如下:
BOOL CMFCAppTestDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CRect rect;
GetClientRect(rect); //取得窗体窗户区区域
CRgn myrgn1, myrgn2;
myrgn1.CreateRoundRectRgn(0, 0, rect.Width(), rect.Height(), 15, 15);//圆角的窗体区域
myrgn2.CreateRectRgn(0, 0, rect.Width(), 40);//标准栏区域
CBrush frameBrush, titlebrush, bgbrush;
bgbrush.CreateSolidBrush(RGB(150, 150, 150));//主窗体背景色画刷
frameBrush.CreateSolidBrush(RGB(178, 178, 200));
titlebrush.CreateSolidBrush(RGB(80, 80, 80));//标题栏的画刷
pDC->FillRgn(&myrgn1, &bgbrush);
pDC->FillRgn(&myrgn2, &titlebrush);
pDC->FrameRgn(&myrgn1, &frameBrush, 1, 1);
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(0x00ffffff);
pDC->TextOut(20, 15, "自绘制的对话框");
return true;
return CDialogEx::OnEraseBkgnd(pDC);
}
为了达到好的效果,还有两个工作要做:
1)在资源视图中选择对话框,在属性中将border属性修改为None;
2)同样用类向导给对话框添加WM_NCHITTEST消息处理函数OnNcHitTest(CPoint point),用来响应鼠标按下后的拖动问题。WM_NCHITTEST 消息返回后, 消息的 Result 参数表示了鼠标所在窗口的部位,加这段代码主要是让程序知道鼠标在客户区移动时都当作在标题栏,其代码如下:
LRESULT CMFCAppTestDlg::OnNcHitTest(CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
UINT nHitTest = CDialog::OnNcHitTest(point);
return (nHitTest == HTCLIENT) ? HTCAPTION : nHitTest;//
return CDialogEx::OnNcHitTest(point);
}
这样一个简单漂亮的自绘制窗体完成了,是一个圆角的黑色窗体,整体是还是比较好看的,感兴趣的朋友可以试试,也可以继续完善,以便得到更好的效果,下面我们看一下最后的运行效果。