首页 > 代码库 > MFC随笔记录——1

MFC随笔记录——1

  这段时间用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.处理重影现象

重影现象其实也不是很好解决的说,很惭愧,我在做项目期间,这个重影问题困扰了我的软件好几个版本,直到最后几个快要终结的版本才基本上处理掉了这个麻头的问题

MFC随笔记录——1