• 兼容位图和兼容DC的理解


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

    通常情况下,如果是同一类设备,创建的DC的初始化环境是相同的,问题在于设备DC在变化,运行过程中一定会调整属性,如果再创建一个同类设备的DC,初始属性肯定不一样,不兼容的可能性是很大的,所以以某个运行时刻的DC为基准创建一个兼容DC,将复制当前时刻的DC属性,它的属性可以保证是相同的,这才是兼容DC的目的,而不是直接使用CreateDC。

    因为兼容DC默认不包含位图,而DC本身的任何操作都是针对位图来操作的,所以创建兼容DC之后,必须也对应地创建一个兼容位图,否则任何绘制操作都是无效的,没有位图的兼容DC被BitBlt到目标DC之后,你会发现全是黑色的。

    如果像你的这种特殊需求,在创建兼容DC的时候还没有目标DC,那么通常都是以屏幕DC作为参考来创建兼容DC,因为最终所有的窗口都要显示在屏幕上。

    理解二:

    我对兼容位图的理解是:它是为解决绘图统一性而建立的一种机制,和位深无关,你在32位的程序里BITBLT()8位的图不也能行吗?

    所谓的绘图统一性是这样的。假设在一个界面有多个贴图,如果你不用兼容位图的话,那么你就要贴多次,比如有3幅图,你要贴3次,有5幅图你就要贴5次。

    如果你仅仅只想画一幅话的话,这也没什么,但在游戏领域就会造成大麻烦,因为游戏是要不断刷新图象的,而且是一秒钟要刷新几十次之多,这就是所谓的帧频,也就是说,在一秒钟内将屏幕上所有的图象绘几十次,如果屏幕上有5幅图,帧频是30次,那么你要在一秒钟内绘5*30=150次图,如果有10幅图,那就得绘300次,这会给显示系统造成很大负担,最显著的表现就是屏幕闪烁。

    而兼容位图能解决这一问题,它先把各个位图绘制到内存里,然后再一次性绘制到屏幕上,绘图次数就大大减少了,打个比喻,不用兼容位图绘图就好比是手动运货,你一次只搬一件货物过去,而兼容位图就是用集装箱运货,你先把所有的货物放到集装箱里,再一次运过去,这样你的劳动量就大大减少了

    所谓的“兼容位图”其实就是“内存位图”。绘图过程中你要用到内存,而普通绘图不要用到内存。

    假设你要在窗口中绘制A,B,C三幅图,

    普通绘图过程是这样的:
    把A绘制到窗口中;
    把B绘制到窗口中;
    把C绘制到窗口中;

    而兼容位图是这样的:
    先在内存中开辟一块区域存放图片,
    把A绘制到内存中;
    把B绘制到内存中;
    把C绘制到内存中;
    然后把内存中绘好的图片绘制到窗口中。

    普通绘图要绘3次,而兼容位图只要绘一次。


    CPaintDC dc(this); 
    // 定义一个兼容DC 
    CDC CompaDC; 
    // 初始化绘图DC指针 
    CDC* pDrawDC = &dc; 
    CBitmap bitmap; 
    CBitmap* pOldBitmap = 0; 
    CRect rtClient; 
    GetClientRect(&rtClient); 
    // 将对话框的客户区上面的/4区域设为绘图区域 
    CRect rtDraw(rtClient.top,rtClient.left,rtClient.Width(),3*(rtClient.Height()/4)); 
    // 假如不是打印机DC 
    if (!dc.IsPrinting()) 
    { 
        // 创建兼容DC,创建兼容位图,将兼容位图选进兼容DC 
        if (CompaDC.CreateCompatibleDC(&dc)) 
        { 
            if (bitmap.CreateCompatibleBitmap(&dc,rtDraw.Width(),rtDraw.Height())) 
            { 
                pDrawDC = &CompaDC; 
                pOldBitmap = CompaDC.SelectObject(&bitmap); 
            } 
        } 
    } 
    // 定义一个白色画刷,将背景色设为白色 
    CBrush brush; 
    if (!brush.CreateSolidBrush(RGB())) 
        return; 
    brush.UnrealizeObject(); 
    
    pDrawDC->FillRect(rtDraw,&brush); 
    // 绘制直线 
    for (size_t i = 0;***;i ++)
    { 
        pDrawDC->MoveTo(m_Lines.m_Begin); 
        pDrawDC->LineTo(m_Lines.m_End); 
    }
    if (pDrawDC != &dc)
    {
        // 将绘图DC贴到真正的设备DC上 
        dc.BitBlt(rtDraw.left,rtDraw.top,rtDraw.Width(),rtDraw.Height(),&CompaDC, 0, 0, SRCCOPY); 
        CompaDC.SelectObject(pOldBitmap);
    }


    具体应用步骤:

    应用是这样的,有两个DC,dc1和dc2,dc1是目标表面,dc2是内存中的,并且绑定位图bmp,通常做法:

    1. 创建与dc1兼容的dc2
    2. 创建与dc1兼容的bmp
    3. 绑定bmp到dc2
    4. 在dc2上绘制,然后bitblt到dc1上。

    总之,所谓的双缓冲处理图像的过程,其实就是在一个兼容DC,以及一个兼容BITMAP上进行相关处理的过程。这样做的好处,我想应该是可以改善闪烁。闪烁问题的出现,是因为频繁的绘画,而兼容DC,兼容BITMAP的好处,就是一次绘画,多次使用,可以降低绘画的频率。

  • 相关阅读:
    Semaphore类
    我的java学习之路五:java的循环和条件语句
    我的java学习之路四:java的基础类型和变量
    第一节 线性表
    我的java学习之路三:java的类与对象
    我的Java学习之路二:Java基础语法
    算法分析一:基本定义
    我的java学习之路一:java的安装以及环境配置
    【2019 CCPC 江西省赛】Cotree 树重心
    【2018 icpc 南京站】G
  • 原文地址:https://www.cnblogs.com/jinxiang1224/p/8468344.html
Copyright © 2020-2023  润新知