这段时间用MFC做完了项目里的一个对图像处理(字迹匹配)的软件,通过项目的具体要求的一步一步的实现,我也学习到了很多以前困惑很久的问题,算是对自己的一个提高吧,把一些有技巧性的操作记在这里,给以后的自己留一份存档也是不错的。
一、关于窗口绘制
1.添加窗口背景图片
MFC创建的窗口的确有点丑,如果不做美化的话做出来的软件也会看着都没有想用的欲望。闲话不多说,直接开始添加背景图片的步骤吧
(1)找到自己想作为背景的图片,并转换为bmp格式,复制到当前项目的资源文件夹res下
(2)对于对话框:
在XXXDlg.cpp的OnPaint()中把else中的语句改为:
else{ //CDialogEx::OnPaint(); CBitmap bmpBackground; bmpBackground.LoadBitmap(IDB_BITMAP1);//IDB_BITMAP是自己的图对应的ID CRect rc;//表示对话框的大小尺寸 GetClientRect(&rc); CPaintDC dc(this); BITMAP bm; bmpBackground.GetBitmap(&bm); int width = bm.bmWidth, height = bm.bmHeight; for(int y=0;y < rc.Height();y += height) { for(int x=0;x < rc.Width();x += width) { CDC memDC; CBitmap *oldMemBitmap; memDC.CreateCompatibleDC(&dc); oldMemBitmap=memDC.SelectObject(&bmpBackground); dc.StretchBlt( x, y, width, height, &memDC, 0, 0, width, height, SRCCOPY ); memDC.SelectObject(oldMemBitmap); } } }
对于单文档:
<1>在XXXView.h中添加定义:
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
DECLARE_MESSAGE_MAP()
<2>在XXXView.cpp中的BEGIN_MESSAGE_MAP(...)与END_MESSAGE_MAP()之间添加ON_WM_ERASEBKGND(),即:
BEGIN_MESSAGE_MAP(...) ON_WM_ERASEBKGND() END_MESSAGE_MAP()
<3>在XXXView类的构造函数中载入位图资源:LoadBitmap(IDB_BITMAP);
<4>实现函数BOOL XXXView::OnEraseBkgnd(CDC* pDC);
{ CBitmap bmpBackground; bmpBackground.LoadBitmap(IDB_BITMAP1);//IDB_BITMAP是自己的图对应的ID //载入位图如果放在这里也可以,不过会重复载入,影响效率 CRect rc;//表示对话框的大小尺寸 GetClientRect(&rc); CPaintDC dc(this); BITMAP bm; bmpBackground.GetBitmap(&bm); int width = bm.bmWidth, height = bm.bmHeight; for(int y=0;y < rc.Height();y += height) { for(int x=0;x < rc.Width();x += width) { CDC memDC; CBitmap *oldMemBitmap; memDC.CreateCompatibleDC(&dc); oldMemBitmap=memDC.SelectObject(&bmpBackground); dc.StretchBlt( x, y, width, height, &memDC, 0, 0, width, height, SRCCOPY ); memDC.SelectObject(oldMemBitmap); } } }
背景图片现在就可以正常显示了,但是可能会出现按钮被图片覆盖的情况,如果发生了也不要急,只要进行一点小小的操作就可以解决:
在对话框点击右键->属性,将WS_CLIPCHILDREN(裁剪子窗口)设为True,这样子窗口区域(按钮部分)就不会被背景的绘制而覆盖
回头来看时发现这个有点复杂了,多说一句,其实这个OnEraseBkgnd(...)消息响应函数也可以根据下面的类向导那样直接添加响应函数,而不需要手工添加。
2.更改静态文本框背景
从上个图片中也可以看到,中间那一行静态文本很扎眼,因为在绘制时字本身有背景颜色(单一颜色)把图片的那一块给挡住了。我们为了能让字只显示它本身的部分,而不绘制字的背景色则需要进行下面的一些操作:
<1>在主窗口点击右键->类向导,在“消息”下面找到“WM_CTLCOLOR”,然后选择“添加处理程序”->“编辑代码”:
HBRUSH C常用操作Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { // 对特定的控件做修改 if (nCtlColor == CTLCOLOR_STATIC) //修改静态文本框 { pDC->SetTextColor(RGB(0,0,255)); //设置字体颜色 pDC->SetBkMode(TRANSPARENT);//设置背景为透明 static HBRUSH B = (HBRUSH)GetStockObject(NULL_BRUSH);//获取画笔颜色混合后的画笔,完成透明 return B; //返回画刷句柄 } return CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor); }
<2>到对话框中,点击对应的静态文本框,在属性中把“透明”调为True,好了,大功告成!
3.重绘窗口(防止重影)——此节将在下面细细道来...
二、编辑框部分
1.让编辑框自动滚动显示
当一个编辑框中需要显示的数据较多时,我们需要设置多行属性:把对应编辑框的Multiline和Verticle scroll属性均设置为True,如果不允许被修改,可以把Read only属性也设置为True。
在处理完编辑框IDC_value1对应的变量value1之后再使用以下代码即可实现自动向下滚动显示:
SetDlgItemText(IDC_value1,value1);//分别为编辑框的ID和对应的变量 CEdit* pEdit = ((CEdit*)GetDlgItem(IDC_value1)); pEdit->LineScroll(pEdit->GetLineCount());//设置完成后不需要调用UpdateData(0)
很明显,滚动条可以自动向下滚动了,但是仔细的朋友会看到,编辑框内却出现了重影现象(这就是上一节提到的却还没解决的问题)
2.处理重影现象
重影现象其实也不是很好解决的说,很惭愧,我在做项目期间,这个重影问题困扰了我的软件好几个版本,直到最后几个快要终结的版本才基本上处理掉了这个麻头的问题