龙马谷

 找回密码
 立即注册

QQ登录

只需一步,快速开始

龙马谷VIP会员办理客服QQ:82926983(如果临时会话没有收到回复,请先加QQ好友再发。)
1 [已完结] GG修改器新手入门与实战教程 31课 2 [已完结] GG修改器美化修改教程 6课 3 [已完结] GG修改器Lua脚本新手入门教程 12课
4 [已完结] 触动精灵脚本新手入门必学教程 22课 5 [已完结] 手游自动化脚本入门实战教程 9课 6 [已完结] C++射击游戏方框骨骼透视与自瞄教程 27课
7 [已完结] C++零基础UE4逆向开发FPS透视自瞄教程 29课 8 [已完结] C++零基础大漠模拟器手游自动化辅助教程 22课 9 [已完结] C++零基础开发DXF内存脚本辅助教程 32课
以下是天马阁VIP教程,本站与天马阁合作,赞助VIP可以获得天马阁对应VIP会员,名额有限! 点击进入天马阁论坛
1 [已完结] x64CE与x64dbg入门基础教程 7课 2 [已完结] x64汇编语言基础教程 16课 3 [已完结] x64辅助入门基础教程 9课
4 [已完结] C++x64内存辅助实战技术教程 149课 5 [已完结] C++x64内存检测与过检测技术教程 10课 6 [已完结] C+x64二叉树分析遍历与LUA自动登陆教程 19课
7 [已完结] C++BT功能原理与x64实战教程 29课 8 [已完结] C+FPS框透视与自瞄x64实现原理及防护思路
查看: 6973|回复: 0

C++ GDI自绘之 双缓冲绘制技术 解决GDI绘图效率问题

[复制链接]

14

主题

1

回帖

20

积分

编程入门

Rank: 1

龙马币
48

Windows绘图原理
我们在Windows环境下看到各种元素,如菜单、按钮、窗口、图像,都是“画”出来的。这时的屏幕,就相当于一块黑板,而Windows下的各种GDI要素,如画笔、画刷等,就相当于彩色粉笔了我们在黑板上手工画图时,是一笔一划的,电脑亦然。只不过电脑的速度比手工快的太多,所以我们看起来好像所有的图形文字都是同时出现的。

当要绘制太复杂图形(比如位图)时,电脑便力不从心了。这时的画面会显示的很慢,对于运动的画面,会给用户“卡住、闪烁”的感觉。

双缓冲绘制技术原理
双缓冲的原理可以这样形象的理解:把电脑屏幕看作一块黑板。
首先我们在内存环境中建立一个“虚拟“的黑板
然后在这块黑板上绘制复杂的图形,等图形全部绘制完毕的时候
再一次性的把内存中绘制好的图形“拷贝”到另一块黑板(屏幕)上。
采取这种方法可以提高绘图速度,极大的改善绘图效果。


双缓冲绘制技术实现步骤
第一步:
使用CreateCompatibleDC创建一个内存兼容DC,,但这个DC尺寸很小,通常是1*1像素,不能直接绘制

第二步:
使用CreateCompatibleBitmap创建位图,默认是全黑的,使用SelectObject将位图选入到兼容DC,
这时位图尺寸大小就相当于了内存设备环境尺寸大小,此时才可绘制。

第三步:
使用绘图API函数(Rectangle、MoveToEx等)在内存兼容DC上绘制各种图形

第四步:
使用BitBlt(不拉伸)或StretchBlt(拉伸)将兼容DC一次性复制到窗口DC上

示例代码:(以下是 窗口过程中消息的分支)
C++
  1. case WM_PAINT:
  2. {
  3.         PAINTSTRUCT ps;//绘图结构体
  4.         HDC hdc=BeginPaint(hwnd, &ps);
  5.        

  6.         //第一步:=创建一个内存兼容DC,此时它的大小是1*1,很小,不能绘制
  7.         HDC hMenDC = CreateCompatibleDC(hdc);


  8.         //第二步:创建兼容位图,提供绘画区域
  9.         HBITMAP hMenBmp = CreateCompatibleBitmap(hdc, 100, 100);
  10.         //并且把兼容位图选到兼容内存DC中,此时DC的大小与位图一致,可以绘制
  11.         SelectObject(hMenDC, hMenBmp);


  12.         //第三步:在内存兼容DC上绘制各种图形
  13.         SetTextColor(hMenDC,RGB(255, 0, 0));
  14.         TextOut(hMenDC, 0, 0, TEXT("这是一个简单的绘图例子"), lstrlen(TEXT("这是一个简单的绘图例子")));
  15.         Rectangle(hMenDC, 30, 30, 80, 80);


  16.         //第四步 把内存中的图像一次性画到窗口DC上

  17.         //不拉伸
  18.         BitBlt(hdc, 0, 0, 100, 100, hMenDC, 0, 0,SRCCOPY);
  19.         //拉伸
  20.         StretchBlt(hdc,0, 100, 200, 200, hMenDC, 0, 0, 100, 100, SRCCOPY);
  21.         //缩放
  22.         StretchBlt(hdc, 300, 0, 50, 50, hMenDC, 0, 0, 100, 100, SRCCOPY);


  23.         //最后不要忘记释放资源
  24.         DeleteDC(hMenDC);
  25.         DeleteObject(hMenBmp);


  26.         EndPaint(hwnd,&ps);
  27.         break;
  28. }
复制代码


扩展阅读:

BitBlt(不拉伸)  函数介绍:  执行对应于从指定的源设备上下文像素矩形到目标设备上下文的颜色数据的位块传输。

BOOL BitBlt(
HDC    hdcDest,//目标设备上下文的句柄。
int    nXDest,//目标矩形左上角的x坐标。
int    nYDest,//目标矩形左上角的y坐标。
int    nWidth,//目标矩形、源矩形的宽度
int    nHeight,//目标矩形、源矩形的高度
HDC    hdcSrc,//源设备上下文的句柄。
int    nXSrc,//源矩形左上角的x坐标
int    nYSrc,//源矩形左上角的y坐标
DWORD dwRop//光栅操作代码。这些代码定义如何将源矩形的颜色数据与目标矩形的颜色数据组合以实现最终颜色。
) ;

光栅操作代码可选值:
BLACKNESS    使用物理调色板中与索引0关联的颜色填充目标矩形(对于默认物理调色板为黑色)
CAPTUREBLT    包括在结果图像中窗口顶部的任何窗口。默认情况下,图像只包含你的窗口。
DSTINVERT    颠倒目标矩形。
MERGECOPY    通过使用布尔AND运算符,将源矩形的颜色与当前在hdcDest中选择的画笔合并。
MERGEPAINT    通过使用布尔或运算符将反转源矩形的颜色与目标矩形的颜色合并。
NOMIRRORBITMAP    防止镜像被镜像。
NOTSRCCOPY    将倒置的源矩形复制到目标。
NOTSRCERASE    通过使用布尔OR运算符组合源矩形和目标矩形的颜色,然后反转结果颜色。
PATCOPY    将当前在hdcDest中选择的画笔复制到目标位图中。
PATINVERT    通过使用布尔XOR运算符,将当前在hdcDest中选择的画笔的颜色与目标矩形的颜色组合在一起。
PATPAINT    此操作的结果通过使用布尔或运算符与目标矩形的颜色相结合。
                  通过使用布尔OR运算符,将当前在hdcDest中选择的画笔的颜色与反转的源矩形的颜色组合。
SRCAND    通过使用布尔AND运算符组合源和目标矩形的颜色。
SRCCOPY    将源矩形直接复制到目标矩形。(通常选用这个)
SRCERASE    通过使用布尔AND运算符将目标矩形的反转颜色与源矩形的颜色组合在一起。
SRCINVERT    通过使用布尔XOR运算符组合源和目标矩形的颜色。
SRCPAINT    通过使用布尔或运算符组合源和目标矩形的颜色。
WHITENESS    便用物理调色板中与索引1关联的颜色填充目标矩形。(对于默认物理调色板为白色)

如果函数或功,返回值为非零。

如果函数失败,返回值为零,调用GetLastError获得扩展的错误信息.


StretchBlt(拉伸) 函数介绍
BOOL StretchBlt (
HDC    hdcDest,    //目标设备上下文的句柄。
int    nXDest,    //目标矩形左上角的x坐标。
int    nYDest,    //目标矩形左上角的y坐标。
int    nWidth,    //目标矩形的宽度
int    nHeight,    //目标矩形的高度
HDC    hdcSrc,    //源设备上下文的句柄。
int    nXSrc,    //原矩形左上角的x坐标
int    nYSrc,    //源矩形左上角的y坐标
int    nWidthSrc,    //源矩形的宽度    比BitBlt 多了这两个参数
int    nHeightSrc,    //源矩形的高度    比BitBlt 多了这两个参数
DWORD dwRop    //光栅操作代码。这些代码定义如何将源矩形的颜色数据与目标矩形的颜色数据组合以实现最终颜色。
) ;

如果函数或功,返回值为非零。

如果函数失败,返回值为零,调用GetLastError获得扩展的错误信息.


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

龙马谷| C/C++辅助教程| 安卓逆向安全| 论坛导航| 免责申明|Archiver|
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表龙马谷立场!
任何人不得以任何方式翻录、盗版或出售本站视频,一经发现我们将追究其相关责任!
我们一直在努力成为最好的编程论坛!
Copyright© 2018-2021 All Right Reserved.
在线客服
快速回复 返回顶部 返回列表