用MFC对话框做无闪烁图片重绘

本文介绍如何使用双缓冲技术优化Windows对话框应用的绘图性能,解决闪烁问题,并提供了一个详细的实现步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用应用程序向导生成一个基于对话框的应用程序

把对话框Styles里的Border设置为Resizing,并把Minimize box跟Maximize box复选按钮都勾上

现在我们为资源导入一张位图然后我们为程序添加四个私有变量private:

int height;
int width;
CBitmap myBitmap;
BITMAP bm;

然后用类向导添加WM SIZE消息输入下列代码: width = cx;
height = cy;
Invalidate();

然后在添加WM_PAINT消息在函数里添加以下代码: CDC *pDC=new CDC;


CPaintDC dc(this);
//CClientDC dc(NULL);
pDC->CreateCompatibleDC(&dc);
pDC->SelectObject(myBitmap);
//将图片伸缩成我们设定的大小。

dc.StretchBlt(0,0,width,height,pDC,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);

//如果不准备进行缩放可以用BITBLT。
//dc.BitBlt(0,0,bm.bmWidth,bm.bmHeight,pDC,0,0,SRCCOPY);

delete pDC;

然后做最后一步在程序初始化时候导入我们的图片并让对话大小跟图片一样

在 OnInitDialog函数最里添加如下代码:
// TODO: Add extra initialization here
myBitmap.LoadBitmap(IDB_BITMAP1);
myBitmap.GetObject(sizeof(BITMAP),&bm);

好了我们现在就做了一个可以显示图片的对话框并且对话改变大小的时候图片大小也会改变,不过这个程序有一个缺点,就是重绘的时候有闪烁,性能不怎么好,

现在我们按上面的步骤在做一个对话框,导入位图,

添加以下变量:public:
CSize m_sizeBuffer;
CBitmap m_bmpBackBuffer;
CBitmap* m_pbmpPattern;

在OnInitDialog函数里添加以下代码
m_pbmpPattern=CBitmap::FromHandle((HBITMAP)::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDB_BACKGROUND), IMAGE_BITMAP, 0,0, LR_SHARED));

重写OnPaint函数

if (IsIconic())
{
       CPaintDC dc(this); // device context for painting
       SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

       // Center icon in client rectangle
      int cxIcon = GetSystemMetrics(SM_CXICON);
      int cyIcon = GetSystemMetrics(SM_CYICON);
      CRect rect;
      GetClientRect(&rect);
      int x = (rect.Width() - cxIcon + 1) / 2;
      int y = (rect.Height() - cyIcon + 1) / 2;
      // Draw the icon
      dc.DrawIcon(x, y, m_hIcon);
}
else {
     CPaintDC dc(this);
     CDC dcBackBuffer;
     dcBackBuffer.CreateCompatibleDC(&dc);
     //重新计算区域面积
     CRect rectClient;
     GetClientRect(rectClient);
     if ( m_sizeBuffer != rectClient.Size() ) {
          m_sizeBuffer = rectClient.Size();
         if ( m_bmpBackBuffer.GetSafeHandle() != NULL )
             m_bmpBackBuffer.DeleteObject();
         m_bmpBackBuffer.CreateCompatibleBitmap(&dc, m_sizeBuffer.cx, m_sizeBuffer.cy);
    }

    CBitmap* pOldBmp = dcBackBuffer.SelectObject(&m_bmpBackBuffer);
    //画背景
    if ( NULL == m_pbmpPattern ) {
         dcBackBuffer.FillSolidRect(rectClient, RGB(255,0,255));
     }
   else {
       CDC dcPat;
       dcPat.CreateCompatibleDC(&dcBackBuffer);
       CBitmap* pbmpOld = dcPat.SelectObject(m_pbmpPattern);
       BITMAP bitmap;
       if ( m_pbmpPattern->GetBitmap(&bitmap) && bitmap.bmWidth > 0 && bitmap.bmHeight > 0 ) {
                 BOOL m_bTilePattern ;
                 m_bTilePattern =TRUE;
                 if ( m_bTilePattern ) {
                        for (int y=0; y<rectClient.bottom+bitmap.bmHeight; y += bitmap.bmHeight) {
                             for (int x=0; x<rectClient.right+bitmap.bmWidth; x += bitmap.bmWidth) {
                                   dcBackBuffer.BitBlt(x,y, bitmap.bmWidth, bitmap.bmHeight, &dcPat, 0,0, SRCCOPY);          }
                        }
                 }
                else {
                     dcBackBuffer.FillSolidRect(rectClient, RGB(255,0,255));
                     dcBackBuffer.BitBlt((m_sizeBuffer.cx-bitmap.bmWidth)/2,(m_sizeBuffer.cy- bitmap.bmHeight)/2, bitmap.bmWidth, bitmap.bmHeight, &dcPat, 0,0, SRCCOPY);
                }
         }
         dcPat.SelectObject(pbmpOld);
     }
     dc.BitBlt(0,0,m_sizeBuffer.cx,m_sizeBuffer.cy,&dcBackBuffer,0,0,SRCCOPY);
     dcBackBuffer.SelectObject(pOldBmp);
     CDialog::OnPaint();
}


现在我们的对话框就是真正利用了双缓冲来绘图性能比起第一个要好,而且还解决了闪烁问题
/****************************************************** SolveFlashingAndRedraw框架说明 ******************************************************/ /** 项目名称: SolveFlashingAndRedraw框架 包含文件: 1. ReadMe.txt 2. SolveFlashingAndRedraw MFC工程 版本号: v1.0.1 第一作者: Jef 地址: 中国/江苏 日期: 20091126 电子邮箱: dungeonsnd@126.com QQ: 420554565 (加好友时注明下载的文件名) 版权: 1.您可以修改及免费使用本程序。 2.修改之后附上您的个人信息发送到上面的作者邮箱,作者负责在全面测试后发布您修改后的新版本。 3.您使用本程序而导致任何伤害以及经济损失,由过错方依法承担所有责任,一概与第一作者及合作单位无关。 4.如果您使用本程序则表示您已经同意此版本协议!否则请勿使用! 项目功能: SolveFlashingAndRedraw 样例工程是MFC解决窗口保存及闪烁问题的一种比较好的方案(Win32解决方法类似)。 运行步骤: 直接运行里面的程序,在窗口上任意拖拉鼠标画线,然后点击菜单栏的几个示范菜单项,然后移动窗口、 改变窗口大小、最大最小化窗口、用其它窗口覆盖此窗口、鼠标放到任务栏。。。 以上种种操作观察窗口内的图像变化。可以发现窗口内图像几乎看不到闪烁,而且窗口的元素已经保存下来时任然可以看到图像。 如何使用: 进行项目开发时,可以先建立项目,然后把本解决方案框架拷贝到新建项目中即可。 也可以自己根据需要修改。 其它: 友情提示,小心 View类头文件及View类的实现文件中有说明,使用时别把它弄到你实际项目里哦! 进行大量复杂的图形的输出,而且对效率要求特别高时要考虑适当修改此框架(如增加裁剪区)后再使用哦。 如何有任何问题欢迎与作者分享!!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值