ExcludeClipRect和无闪烁图像

简介:
  Chapter I: ExcludeClipRect在一个剪切区域排除一个矩形,导致绘制该剪切区域时,不绘制该矩形.
  ExcludeClipRect函数详情请参考MSDN,这个函数用于排除一个区域的一部分,常用于绘制图画,例如,在一个窗口的客户区绘制一幅图片,如下面代码所示:

 
  1. case WM_PAINT: 
  2.     hdc = BeginPaint(hWnd, &ps); 
  3.     RECT rc = {0}; 
  4.     GetClientRect (hWnd, &rc) ; 
  5.     HDC hMemDC = CreateCompatibleDC(ps.hdc); 
  6.     SelectObject(hMemDC, g_hBmpAllWstDskWallpaper);//选择位图 
  7.  
  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); 
客户区,但是矩形区域{0, 0, 200, 100}显示的仍然是窗口的背景色,换句话说,位图缺了这一块.这是因为ExcludeClipRect将{0, 0, 200, 100}矩形从窗口剪切区域
Chaper II: ExcludeClipRect函数不释放排除的矩形区域
 
将Chapter I代码中的A行改为:

 
 
  1. BOOL g_bCall = TRUE;//全局变量. 
  2. if (g_bCall) 
  3.     g_bCall = FALSE; 
  4.     ExcludeClipRect(ps.hdc,0,0,200,100); //排除部分区域,仅调用一次. A line 
该DC上绘制,那么有没有什么办法恢复该区域呢? 其实很简单,将那块被"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.     hdc = BeginPaint(hWnd, &ps); 
  7.     RECT rc = {0}; 
  8.     GetClientRect (hWnd, &rc) ; 
  9.     HDC hMemDC = CreateCompatibleDC(ps.hdc); 
  10.     SelectObject(hMemDC, g_hBmpAllWstDskWallpaper);//选择位图 
  11.  
  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.  
  18.     HRGN hrgn = NULL;   // 将上次"exclud"掉的区域填补回来. 
  19.     if (g_bCancelExcludeRect && RECT_WIDTH(g_rcExclud) && RECT_HEIGHT(g_rcExclud)) 
  20.     { 
  21.         hrgn = CreateRectRgn(g_rcExclud.left, g_rcExclud.top, g_rcExclud.right, g_rcExclud.bottom); 
  22.         ExtSelectClipRgn(ps.hdc, hrgn, RGN_OR); 
  23.         FillRect(ps.hdc,&g_rcExclud,(HBRUSH)GetStockObject(COLOR_WINDOW));//擦除上次绘制的图片区域. 
  24.     } 
  25.  
  26.     (!g_bCancelExcludeRect) //"exclud"掉窗口右下角区域. 
  27.         ExcludeClipRect(ps.hdc,g_rcExclud.left, g_rcExclud.top, RECT_WIDTH(g_rcExclud), RECT_HEIGHT(g_rcExclud)); 
  28.     BitBlt(ps.hdc,0,0,400,300,hMemDC,0,0,SRCCOPY);//在右下角绘制一个位图. 
  29.  
  30.     DeleteDC(hMemDC); 
  31.     if (hrgn != NULL) DeleteObject(hrgn); 
  32.     EndPaint(hWnd,&ps); 
Chapter III: 使用ExcludeClipRect实现无闪烁图像
有网友写过相关文章:http://dev.10086.cn/cmdn/wiki/index.php?edition-view-6349-1.html
而"exclude"掉的区域是不会被背景擦除的.
而且这篇文章还有一个地方没有说清楚,那就是解决图像闪烁的办法其实是不用擦除窗口背景,而绘制窗口前景色,图像区域用位图绘制,其它区域用窗口背景色绘制,
 
 
   
  1. case WM_PAINT: 
  2.     { 
  3.         hdc = BeginPaint(hWnd, &ps); 
  4.         RECT rc = {0}; 
  5.         GetClientRect (hWnd, &rc) ; 
  6.  
  7.         HDC hMemDC = CreateCompatibleDC(ps.hdc); 
  8.         SelectObject(hMemDC, g_hBmpAllWstDskWallpaper); 
  9.  
  10.         HRGN hrgn = NULL; 
  11.         if (RECT_WIDTH(g_rcExclud) && RECT_HEIGHT(g_rcExclud)) 
  12.         { 
  13.             hrgn = CreateRectRgn(g_rcExclud.left, g_rcExclud.top, g_rcExclud.right, g_rcExclud.bottom); 
  14.             ExtSelectClipRgn(ps.hdc, hrgn, RGN_OR);//恢复上次被"excude"掉的区域,必须的,否则这一部分不会被绘制. 
  15.             FillRect(ps.hdc,&g_rcExclud,(HBRUSH)GetStockObject(COLOR_WINDOW));//擦除上次绘制的图片区域. 
  16.         } 
  17.  
  18.         g_rcExclud.left = rc.right-300; 
  19.         g_rcExclud.top = rc.bottom-200; 
  20.         g_rcExclud.right = rc.right; 
  21.         g_rcExclud.bottom = rc.bottom; 
  22.  
  23.         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); 
  24.         ExcludeClipRect(ps.hdc,g_rcExclud.left,g_rcExclud.top, g_rcExclud.right, g_rcExclud.bottom);//排除掉图像所占据的区域 
  25.         FillRect(ps.hdc,&rc,(HBRUSH)GetStockObject(COLOR_WINDOW));// 用窗口背景色绘制其余区域. 
  26.  
  27.         DeleteObject(hrgn); 
  28.         DeleteDC (hMemDC) ;                      //释放内存设备环境 
  29.         EndPaint(hWnd, &ps); 
  30.         return 0; 
  31.     } 
  32.     break
  33. case WM_SIZE: 
  34.     InvalidateRect(hWnd, NULL, FALSE);//最后一个参数为FALSE,表示不用擦除背景. 
  35.     break
最后,改变窗口的大小,观察一下这幅图片,始终在窗口右下角,而且图片的确不再闪烁.
 










本文转自jetyi51CTO博客,原文链接:http://blog.51cto.com/jetyi/642401  ,如需转载请自行联系原作者


相关文章
|
12月前
|
存储 编译器 C语言
详解C/C++中的static和extern
本文详解了C/C++中`static`和`extern`关键字的用法和区别,通过具体代码示例说明了在不同情境下如何正确使用这两个关键字,以及`extern "C"`在C++中用于兼容C语言库的特殊作用。
411 4
详解C/C++中的static和extern
|
开发工具 git 编译器
Git 提交的正确姿势:Commit message 编写指南
Git 每次提交代码,都要写 Commit message(提交说明),否则就不允许提交。 $ git commit -m "hello world" 上面代码的-m参数,就是用来指定 commit mesage 的。
7471 0
|
存储 编译器 C++
【C++练级之路】【Lv.13】多态(你真的了解虚函数和虚函数表吗?)
【C++练级之路】【Lv.13】多态(你真的了解虚函数和虚函数表吗?)
220 0
|
缓存
石英晶体是如何产生振荡的?以及cpu倍频的由来
本文是关于石英晶体振荡器的学习笔记,适合计算机科学与技术背景的读者。内容涵盖了石英晶体振荡器的基本原理,包括压电效应、等效电路、谐振频率,以及不同类型振荡器的特性和参数。此外,还讨论了石英晶体振荡器的小型化、高精度、低噪声、低功耗发展趋势,并列举了它们在石英钟、彩电和通信系统中的应用。最后提到了处理器倍频的概念,解释了其原理和实际应用中的限制。
石英晶体是如何产生振荡的?以及cpu倍频的由来
|
12月前
|
人工智能 Cloud Native 数据管理
重磅升级,阿里云发布首个“Data+AI”驱动的一站式多模数据平台
阿里云发布首个AI多模数据管理平台DMS,助力业务决策提效10倍
1369 17
在Linux中,什么是initrd镜像?
在Linux中,什么是initrd镜像?
|
开发工具 对象存储 git
|
安全 Java 数据库连接
Java中的异常处理:深入理解try-with-resources语句
在Java的异常处理领域,try-with-resources语句是一个重要的特性,它简化了资源管理并提高了代码的可读性。本文将详细探讨try-with-resources的工作原理、使用场景以及如何正确运用这一结构来优化资源管理,同时指出常见的误用情况和最佳实践。
394 0
|
Windows
【Qt 学习笔记】Qt常用控件 | 显示类控件 | Label的使用及说明
【Qt 学习笔记】Qt常用控件 | 显示类控件 | Label的使用及说明
747 0
代码重构:优化之道
代码重构:优化之道