• 位图复制操作


    这一篇是针对推箱子小游戏写的,有很多细节在其它文章已记录,但还是再写一篇,我一直觉得知识需要反反复复的锤炼才能理解,尤其对于windows程序设计,它不难,但是非常琐碎!每一句代码都有其意思,为什么这样为什么那样,一句代码不明白,就是一个知识点不明白,能允许不能解释的代码存在吗?我们总要给其一个解释,至少能自圆其说!

    首先考虑的是位图怎么显示在屏幕上。

    当获取或创建一个设备对象时,该设备对象中包含有一个位图,该位图所使用的内存是输出设备在输出图形时所使用的内存(例如,显示器的显示缓冲区),这样,GDI函数在该内存中所绘制的图形同时可以在显示器上可见。

    这段话的意思大概是,如果不进行任何的操作,只是得到一个hdc显示位图,位图就处在显示器的显示缓冲区中。

    接下来就是内存设备对象,也就是在内存中创建一个设备对象,在这个设备对象上画图,然后再把这个位图送到其它显示设备上显示。唯一需要的是,创建的这个内存设备对象得兼容其它的显示设备对象,比如hdc等等。

    这里需要注意的一个问题,创建内存设备对象初始时,其位图尺寸只有1x1(即一个像素),需要扩大显示表面才能容纳位图,采用的方法是创建一个兼容位图去填充内存设备对象。如图所示:

    针对推箱子游戏的代码:

    hdc=GetDC(hWnd);
    mdc=CreateCompatibleDC(hdc);//创建兼容的内存设备对象
    bg=CreateCompatibleBitmap(hdc,Border*COL,Border*ROW);//兼容位图,即是推箱子客户区的大小
    SelectObject(mdc,bg);//选入位图进入内存设备对象,同时也就扩大了内存设备对象的显示表面

    上图说明了如何复制的流程,观察这三个dc,尺寸是不一样的,hdc=mdc=客户区的大小,而bufdc=images的大小。
    这里出现一个问题,为什么不直接把图块放在mdc中,然后再复制mdc到hdc,还要创建一个bufdc呢? 可以这样理解,实在的位图和内存块之间如何复制?至少现在知道是不行的,比如说BitBlt函数,是在内存块之间复制,不是位图和内存之间复制,所以还是建立一个bufdc,将位图放在其中,这样位图就相当于“内存块”了,于是就可以利用BitBlt位块操作,将bufdc的某个区域复制到mdc,最后将完整的mdc复制到hdc。

    需要注意的几个问题

    创建内存设备对象初始时只有1个像素,可以先扩大其显示表面。

    第二个,观察SelectObject这个函数,假如直接将一幅存在的位图选入到某个DC中,那这个DC直接就具有了这个图像。比如:

            mdc=CreateCompatibleDC(hdc);
                    hBitmap=(HBITMAP)LoadImage(NULL,"fg.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);    
                    SelectObject(mdc,hBitmap);

    第三个,是BitBlt函数

    这个函数是位块复制函数,位块就是在内存块之间转移。从源到目的复制多大,取决于前面设置的宽和高,也就是说,源只提供坐标,从哪开始,而目的提供宽度和高度。

    SelectObject和BitBlt的一点微妙关系

    前面提到的,创建一个内存设备对象,初始时,是1像素,既然这么小,为什么SelectObject将一幅位图选进后,它就自动变的位图一样大呢?这个通过程序可以验证的。
    按照这种思路,在创建mdc的时候,我不扩大其显示表面,被动的等待其它位块来填充,这样可行吗?验证是不行的。

    这两者的对比就说明一个问题,进行SelectObject操作时,可以不指定内存设备对象的大小,直接复制。而BitBlt是位块复制,目标尺寸必须大于源的尺寸,这一点还是奇怪的。用图表示:

    正是因为这个区别,在创建mdc的时候,还要多出一步,扩大其显示表面,以用于后面的复制操作!
    代码表示:

        hdc=GetDC(hWnd);
        mdc=CreateCompatibleDC(hdc);
        bufdc=CreateCompatibleDC(hdc);//bufdc不需要扩大,因为其用于SelectObject...
        bg=CreateCompatibleBitmap(hdc,Border*COL,Border*ROW);
        images= (HBITMAP)LoadImage(NULL,"box.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);//直接从硬盘读取位图
        SelectObject(mdc,bg);//扩大mdc的显示表面,mdc是用于复制的...

    ——————————————————————————————————————————————————————————————————

  • 相关阅读:
    集合
    字典
    Visual Studio 2017 发布
    表现设身处地的方法:杜彬(Ben Duffy)方法
    Can RemObjects SDK parameters be passed via the URI?
    转:RemObjects SDK 简介
    转:RemObject 服务器端自调用的方法
    转: Delphi多层开发方案比较
    Embed
    log4d 的使用(转)
  • 原文地址:https://www.cnblogs.com/tinaluo/p/5439965.html
Copyright © 2020-2023  润新知