Fork me on GitHub

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.处理重影现象

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

posted @ 2014-08-23 22:47  闻波  阅读(413)  评论(2编辑  收藏  举报
友情链接: