Chapter I: ExcludeClipRect在一个剪切区域排除一个矩形,导致绘制该剪切区域时,不绘制该矩形.
  ExcludeClipRect函数详情请参考MSDN,这个函数用于排除一个区域的一部分,常用于绘制图画,例如,在一个窗口的客户区绘制一幅图片,如下面代码所示:
  1. case WM_PAINT:
  2. {
  3. hdc = BeginPaint(hWnd, &ps);
  4. RECT rc = {0};
  5. GetClientRect (hWnd, &rc) ;
  6. HDC hMemDC = CreateCompatibleDC(ps.hdc);
  7. SelectObject(hMemDC, g_hBmpAllWstDskWallpaper);//选择位图
  8. //ExcludeClipRect(ps.hdc,0,0,200,100);  //排除部分区域. A line
  9. BitBlt(ps.hdc,0,0,300,200,hMemDC,0,0,SRCCOPY);
  10. DeleteDC(hMemDC);
  11. EndPaint(hWnd,&ps);
  12. }
这段代码在窗口客户区绘制一个位图,这没问题.但是注意一下A行,它是注释掉的,然后去掉这个注释,再次运行程序,可以观察到,这个位图虽然还是绘制在了窗口的客户区,但是矩形区域{0, 0, 200, 100}显示的仍然是窗口的背景色,换句话说,位图缺了这一块.这是因为ExcludeClipRect将{0, 0, 200, 100}矩形从窗口剪切区域排除掉了,这样GDI是不会绘制这个矩形区域的.
Chaper II: ExcludeClipRect函数不释放排除的矩形区域
将Chapter I代码中的A行改为:
  1. BOOL g_bCall = TRUE;//全局变量.
  2. if (g_bCall)
  3. {
  4. g_bCall = FALSE;
  5. ExcludeClipRect(ps.hdc,0,0,200,100); //排除部分区域,仅调用一次. A line
  6. }
再次运行程序,并改变窗口大小,可以发现,客户区矩形区域{0, 0, 200, 100}始终不会被绘制.可见这个函数一旦被调用,那么这个函数排除的矩形区域将永远不会在该DC上绘制,那么有没有什么办法恢复该区域呢? 其实很简单,将那块被"Exclude"掉的矩形区域再"找回来"就行了.办法就是程序再创建一个剪切区域,使其大小和位置和之前"Exclude"掉的相同,然后调用ExtSelectClipRgn,注意最后一个参数要使用RGN_OR,这表示合并两个剪切区域.这样就相当于找回了这个"Exclude"掉的矩形区域.下面是代码:
  1. #define RECT_WIDTH(rt)      (rt.right-rt.left)
  2. #define RECT_HEIGHT(rt)     (rt.bottom-rt.top)
  3. RECT g_rcExclud = {0};
  4. BOOL g_bCancelExcludeRect = FALSE;
  5. case WM_PAINT:
  6. {
  7. hdc = BeginPaint(hWnd, &ps);
  8. RECT rc = {0};
  9. GetClientRect (hWnd, &rc) ;
  10. HDC hMemDC = CreateCompatibleDC(ps.hdc);
  11. SelectObject(hMemDC, g_hBmpAllWstDskWallpaper);//选择位图
  12. // "exclud"掉的区域在右下角.
  13. g_rcExclud.left = rc.right-200;
  14. g_rcExclud.top = rc.bottom-100;
  15. g_rcExclud.right = rc.right;
  16. g_rcExclud.bottom = rc.bottom;
  17. HRGN hrgn = NULL;   // 将上次"exclud"掉的区域填补回来.
  18. if (g_bCancelExcludeRect && RECT_WIDTH(g_rcExclud) && RECT_HEIGHT(g_rcExclud))
  19. {
  20. hrgn = CreateRectRgn(g_rcExclud.left, g_rcExclud.top, g_rcExclud.right, g_rcExclud.bottom);
  21. ExtSelectClipRgn(ps.hdc, hrgn, RGN_OR);
  22. FillRect(ps.hdc,&g_rcExclud,(HBRUSH)GetStockObject(COLOR_WINDOW));//擦除上次绘制的图片区域.
  23. }
  24. (!g_bCancelExcludeRect) //"exclud"掉窗口右下角区域.
  25. ExcludeClipRect(ps.hdc,g_rcExclud.left, g_rcExclud.top, RECT_WIDTH(g_rcExclud), RECT_HEIGHT(g_rcExclud));
  26. BitBlt(ps.hdc,0,0,400,300,hMemDC,0,0,SRCCOPY);//在右下角绘制一个位图.
  27. DeleteDC(hMemDC);
  28. if (hrgn != NULL) DeleteObject(hrgn);
  29. EndPaint(hWnd,&ps);
  30. }
Chapter III: 使用ExcludeClipRect实现无闪烁图像
有网友写过相关文章:http://dev.10086.cn/cmdn/wiki/index.php?edition-view-6349-1.html
这篇文章些的不错,不过还是有一个问题,就是Chapter II所提到的ExcludeClipRect不会释放"exclude"掉的区域,这样如果因为窗口大小的改变导致位图位置的变化,而"exclude"掉的区域是不会被背景擦除的.
而且这篇文章还有一个地方没有说清楚,那就是解决图像闪烁的办法其实是不用擦除窗口背景,而绘制窗口前景色,图像区域用位图绘制,其它区域用窗口背景色绘制,这相当于把一幅挖了一个洞(这个部分就是图像,其它部分使用背景色绘制)的画布贴到窗口,这样不产生绘制重叠部分,下面是修改后的代码:
  1. case WM_PAINT:
  2. {
  3. hdc = BeginPaint(hWnd, &ps);
  4. RECT rc = {0};
  5. GetClientRect (hWnd, &rc) ;
  6. HDC hMemDC = CreateCompatibleDC(ps.hdc);
  7. SelectObject(hMemDC, g_hBmpAllWstDskWallpaper);
  8. HRGN hrgn = NULL;
  9. if (RECT_WIDTH(g_rcExclud) && RECT_HEIGHT(g_rcExclud))
  10. {
  11. hrgn = CreateRectRgn(g_rcExclud.left, g_rcExclud.top, g_rcExclud.right, g_rcExclud.bottom);
  12. ExtSelectClipRgn(ps.hdc, hrgn, RGN_OR);//恢复上次被"excude"掉的区域,必须的,否则这一部分不会被绘制.
  13. FillRect(ps.hdc,&g_rcExclud,(HBRUSH)GetStockObject(COLOR_WINDOW));//擦除上次绘制的图片区域.
  14. }
  15. g_rcExclud.left = rc.right-300;
  16. g_rcExclud.top = rc.bottom-200;
  17. g_rcExclud.right = rc.right;
  18. g_rcExclud.bottom = rc.bottom;
  19. BitBlt(ps.hdc,g_rcExclud.left,g_rcExclud.top,g_rcExclud.right-g_rcExclud.left,g_rcExclud.bottom-g_rcExclud.top,hMemDC,0,0,SRCCOPY);
  20. ExcludeClipRect(ps.hdc,g_rcExclud.left,g_rcExclud.top, g_rcExclud.right, g_rcExclud.bottom);//排除掉图像所占据的区域
  21. FillRect(ps.hdc,&rc,(HBRUSH)GetStockObject(COLOR_WINDOW));// 用窗口背景色绘制其余区域.
  22. DeleteObject(hrgn);
  23. DeleteDC (hMemDC) ;                      //释放内存设备环境
  24. EndPaint(hWnd, &ps);
  25. return 0;
  26. }
  27. break;
  28. case WM_SIZE:
  29. InvalidateRect(hWnd, NULL, FALSE);//最后一个参数为FALSE,表示不用擦除背景.
  30. break;

最后,改变窗口的大小,观察一下这幅图片,始终在窗口右下角,而且图片的确不再闪烁.

转载于:https://blog.51cto.com/jetyi/642401

ExcludeClipRect和无闪烁图像相关推荐

  1. VC++大数据量绘图时无闪烁刷屏技术实现

    引言 当我们需要在用户区显示一些图形时,先把图形在客户区画上,虽然已经画好但此时我们还无法看到,还要通过 程序主动地刷新用户区,强制Windows发送一条WM_PAINT消息,这将引发视类OnDraw ...

  2. Qt组件中的双缓冲无闪烁绘图

    双缓冲绘图 在Qt4中,所有的窗口部件默认都使用双缓冲进行绘图.使用双缓冲,可以减轻绘制的闪烁感.在有些情况下,用户要关闭双缓冲,自己管理绘图.下面的语句设置了窗口部件的Qt::WA_PaintOnS ...

  3. Hook源码+插件化实现无闪烁换肤

    现在的移动端应用,在实现功能需求的同时,还会在用户体验上进行突破,以增加用户黏性.例如,很多场景都加入了日/夜间主题切换,或者类似于网易云音乐的换肤.那么,当我们碰到类似的需求时,应该怎么来实现呢?更 ...

  4. 四大指标超现有模型!少样本的无监督图像翻译效果逆天| 技术头条

    作者 | Ming-yu Liu, Xun Huang, Arun Mallya, Tero Karras, Timo Aila, Jaakko Lehtinen 译者 | linstancy 编辑 ...

  5. Github大热论文 | U-GAT-IT:基于GAN的新型无监督图像转换

    作者丨武广 学校丨合肥工业大学硕士生 研究方向丨图像生成 生成对抗网络(GAN)在这几年的发展下已经渐渐沉淀下来,在网络的架构.训练的稳定性控制.模型参数设计上都有了指导性的研究成果.我们可以看出 1 ...

  6. 用ajax技术实现无闪烁定时刷新页面

    在Web开发中我们经常需要实现定时刷新某个页面:1.来保持session的值或者检查session的值是否为空(比如说防止同一用户重复登录):2.实现实时站内短信:3.定时更新页面数据等等.但是我们在 ...

  7. 无闪烁刷新页面 php,AJAX_Ajax实现无闪烁定时刷新页面实例代码,在Web开发中我们经常需要实现 - phpStudy...

    Ajax实现无闪烁定时刷新页面实例代码 在Web开发中我们经常需要实现定时刷新某个页面: 1.来保持session的值或者检查session的值是否为空(比如说防止同一用户重复登录): 2.实现实时站 ...

  8. “用于无监督图像生成解耦的正交雅可比正则化”论文解读

    Tikhonov regularization terms https://blog.csdn.net/jiejinquanil/article/details/50411617 本文是对博客http ...

  9. Delphi用ini文档实现界面无闪烁多语言转换

    越来越多的程序使用了多国语言切换,虽然DELPHI自带多语言包的添加和配置,   但是那种方法在切换语言时界面会出现闪烁,而且实现起来很麻烦,这里我介绍给大家的是利用INI文件来读取界面的语种文字,  ...

最新文章

  1. 华中科技大学 教学大纲 计算机,教学大纲-华中科技大学计算机学院
  2. cdh 安装_使用Cloudera的CDH部署Hadoop:第三步,安装管理平台和数据库
  3. android 紧急号码没记录,android – 当呼叫被隐瞒/未知时,来电号码是...
  4. 关于两个php.ini的说明
  5. 攻城狮危险:波士顿动力机器狗去福特当工程师了!
  6. 前端学习(3024):vue+element今日头条管理-关于默认子路由的问题
  7. python mysql实例_Python使用MySQL数据库的方法以及一个实例
  8. 自定义AlertDialog控件的使用(AndroidStudio)
  9. 全网最全的IDEA热部署方案,看完弄懂,再也不用加班了~
  10. 正则表达式:基础知识学习
  11. 舒尔特注意力训练表格_用微信小程序里训练提升你的专注力
  12. visio2019 专业版,两种方法
  13. snipaste如何滚动截图_3款工具满足你对截图软件的所有想象
  14. 关注C-RAN 的五大理由
  15. VUE框架应用包---------微信二维码应用
  16. excel提取数字的方法
  17. vb.net(C#)调用CAD并画图
  18. 电压源电流源电路符号及2B法
  19. Flex布局——flex-basis、flex-grow、flex-shrink
  20. 7-36 复数四则运算 (15 分)【简化版】

热门文章

  1. java用axis方式调用webservice接口
  2. 从0到1搭建大数据平台之数据计算
  3. 如何在C++里面加快运行速度
  4. 计算机管理 合并分区,如何分区,删除和合并计算机02
  5. 我们为什么需要数字化转型?
  6. Win10自带SSH免密连接Virtulbox虚拟机
  7. 【用户画像和用户标签】
  8. 差速小车的Cartographer建图
  9. 是的你没看错,js生成word文档
  10. 子查询及其分类(标量子查询+列子查询+行子查询+表子查询)