zoukankan      html  css  js  c++  java
  • Win32双缓冲绘图和位图的绘制

    前言:

    为什么需要使用双缓冲技术?可能很多朋友会问,不知道你们有没有发现,当屏幕刷新的时候会有闪烁,这样让人的体验感极差。原因是绘图与显示器刷新不同步,有时间差,为解决这一问题,这就需要用到双缓冲技术来绘图了。双缓冲技术是相对单缓冲而言的,单缓冲就是直接在设备DC上绘图;而双缓冲就是先在一个与设备DC相兼容的内存缓冲区里进行绘图,然后再一次性复制到设备DC上。一次性在屏幕上显示就不会出现闪烁的现象。

    这里需要注意的是:我们创建的兼容DC,不能直接在上面绘图,这里还需要一块画布,那我们创建的兼容DC就相当于画板,有了画板、画布,将画布选放在画板兼容DC上就可以进行绘图了。然后一次性贴在设备DC上就搞定了。如下:

    HDC mdc=CreateComatibleDC(hdc);   // 创建兼容DC 画板
    HBITMAP bmp=CreatrCompatibleBitnap(hdc,600,600);   // 创建画布
    SelectObject(mdc,bmp);   //  将画布选入画板
    

    一、双缓冲技术的使用

    双缓冲绘图步骤:

    1. 在内存中创建兼容DC缓冲区(依次包括创建兼容DCCreateComatibleDC、创建画布CreatrCompatibleBitnap、将画布选入SelectObject)。
    2. 在缓冲区进行画图操作(可以画图形、也可以贴位图)。
    3. 将兼容缓冲区一次性复制到设备DC上。(复制用Bitblt函数)
    4. 释放内存缓冲区。(DeleteDC函数)

    几个关键API函数:

    CreateCompatibleDC:
    该函数创建一个与指定设备兼容的内存设备上下文环境(DC)

     HDC CreateCompatibleDC(HDC hdc)

    CreateCompatibleBitmap:
    该函数创建与指定的设备环境相关的设备兼容的位图.

    HBITMAP CreateCompatibleBitmap(HDC hdc,  
                                   int nWidth,   // 定位图的宽度,单位为像素
                                   int nHeight)// 指定位图的高度,单位为像素
    

    BitBlt:
    BitBlt是一个计算机函数,该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境.

    BOOL BitBlt(  _In_  HDC hdcDest, 
                  _In_  int nXDest,  // 指定目标矩形区域左上角的X轴逻辑坐标
                  _In_  int nYDest,  // 指定目标矩形区域左上角的Y轴逻辑坐标
                  _In_  int nWidth,  // 指定源在目标矩形区域的逻辑宽度
                  _In_  int nHeight, // 指定源在目标矩形区域的逻辑高度
                  _In_  HDC hdcSrc,  // 指向源设备环境的句柄
                  _In_  int nXSrc,   // 指定源矩形区域左上角的X轴逻辑坐标
                  _In_  int nYSrc,   // 指定源矩形区域左上角的Y轴逻辑坐标
                  _In_  DWORD dwRop); //指定光栅操作代码。这些代码将定义源矩形区域的颜色数据,如何与目标矩形区域的颜色数据组合以完成最后的颜色。
    

    单双缓冲技术操作对比:

    单缓冲技术绘制两个矩形:

    // 直接在设备DC上绘制
    Rectangle(hdc, 100, 100, 200, 200);
    Rectangle(hdc, 300, 300, 200, 200);
    

    双缓冲技术绘制两个矩形:

    // 1.创建兼容缓冲区
    mdc = CreateCompatibleDC(hdc);   // 创建兼容DC
    bmp = CreateCompatibleBitmap(hdc, 600, 600);   // 创建兼容位图画布
    SelectObject(mdc, bmp);    // 选入
    
    // 2.在缓冲区绘制 
    Rectangle(mdc, 100, 100, 200, 200);
    Rectangle(mdc, 300, 300, 200, 200);
    
    // 3.一次性复制到设备DC
    BitBlt(hdc, 0, 0, 500, 500, mdc, 0, 0, SRCCOPY);
     
    // 4.释放缓冲区DC
    DeleteDC(mdc);
    

    二、绘制位图

    绘制位图步骤:

    1. 创建兼容DC(CreateCopatibleDC函数)
    2. 加载位图(LoadImage函数和LoadBitmap函数)
    3. 选取位图对象,使用BitBlt函数进行贴图(SelectObject函数)
    4. 释放兼容DC(DeleteDC函数)

    加载位图API函数:
    第一种 :LoadImage
    LoadImage是一种函数,功能是装载图标,光标,或位图。

    HANDLE LoadImage(HINSTANCE hinst,// 处理包含被装载图像模块的实例句柄。若要装载OEM图像,则设此参数值为0。
                      LPCTSTR lpszName,// 图像资源名称
                      UINT uType,   // 指定被装载图像类型,IMAGE_BITMAP:装载位图;IMAGE_CURSOR:装载光标;IMAGE_ICON:装载图标。
                      int cxDesired,// 指定图标或光标的宽度,以像素为单位
                      int cyDesired,// 指定图标或光标的高度,以像素为单位
                      UINT fuLoad);// 加载标识,含义见链接
    
    

    第二种 :LoadBitmap
    该函数从模块的可执行文件中加载指定的位图资源,该函数已经被函数LoadImage替代。

    HBITMAP LoadBitmap(HINSTANCE hInstance, LPCTSTR lpBitmapName)

    注意: 在内存DC上绘制位图时也需要创建一个与窗口DC兼容的内存DC(maphdc),还需要一个HBITMAP map来加载位图,然后选用位图对象( SelectObject(maphdc,map)与之前画笔画刷选取一样),最后用BitBlt函数将位图贴入内存DC上。
    上面所说的BitBlt函数是指在内存DC上贴位图,其中包括在设备DC和双缓冲技术的缓冲DC.在双缓冲技术绘制位图时,需要特别注意的是:兼容DC我们创建了两个(mdc和maphdc),mdc是真正的缓冲区(开始将所有图形位图都绘制在这个缓冲DC中),而maphdc是在选取位图时用的,会有很多人理解错,我开始学的时候也有点。HBITMAP 我们也声明了两个(bmp和map),bmp是mdc的画布(需要用CreateCompatibleBitmap来创建),而map只是用来加载位图的。以下做个对比说明:

    单缓冲绘制位图:
    // 1.创建兼容DC
    maphdc = CreateCompatibleDC(hdc);
    
    // 2.加载位图
    HBITMAP map = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 500, 500, LR_CREATEDIBSECTION);
    
    // 3.选取位图对象,使用BitBlt函数贴图
    SelectObject(maphdc, map);
    BitBlt(hdc, 0, 0, 1500, 1500, maphdc, 0, 0, SRCCOPY);
    
    // 4.释放兼容DC
    DeleteDC(maphdc);
    
    
    双缓冲绘制位图:
    // 1.创建兼容缓冲区
    mdc = CreateCompatibleDC(hdc);   // 创建兼容DC
    bmp = CreateCompatibleBitmap(hdc, 600, 600);   // 创建兼容位图画布
    SelectObject(mdc, bmp);    // 选入
    
    // 2.在缓冲区绘制 
    
    maphdc = CreateCompatibleDC(hdc); /*创建兼容DC*/
          
    /*贴第一张位图*/
    HBITMAP map = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 500, 500, LR_CREATEDIBSECTION);
    SelectObject(maphdc, map);
    BitBlt(mdc, 0, 0, 500, 500, maphdc, 0, 0, SRCCOPY);
          /*贴第二张位图*/
    HBITMAP map = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 500, 500, LR_CREATEDIBSECTION);
    SelectObject(maphdc, map);
    BitBlt(mdc, 0, 0, 500, 500, maphdc, 0, 0, SRCCOPY);
           
    DeleteDC(maphdc);  /*释放兼容DC*/
          
    // 3.一次性复制到设备DC
    BitBlt(hdc, 0, 0, 500, 500, mdc, 0, 0, SRCCOPY);
     
    // 4.释放缓冲区DC
    DeleteDC(mdc); 
    
  • 相关阅读:
    SWT DragSource 和 DropTarget 托拉拽
    Java的反射机制
    1. 算法导论
    SWT对于监听Tab键的理解
    SWT基础
    socket
    TCP/IP
    RPC(远程过程调用协议)
    Jython基本知识
    #与##
  • 原文地址:https://www.cnblogs.com/laohaozi/p/12537580.html
Copyright © 2011-2022 走看看