关闭

纯SDK实现双缓冲绘图与普通绘图差别演示

1406人阅读 评论(0) 收藏 举报

先大致介绍一下WINDOWS下的绘图原理:

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

普通绘图方式的局限
上述绘图方式我们暂且称之为普通绘图方式吧。虽然这种方式能满足相当一部分的绘图需要,但是当要绘制的对象太复杂,尤其是含有位图时,电脑便力不从心了。这时的画面会显示的很慢,对于运动的画面,会给人“卡”住了的感觉,总之一个字:不爽。
解决之道:双缓冲

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

                                                        双缓冲原理示意图

下面贴出代码吧

[cpp:showcolumns] view plaincopyprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. #include <windows.h>   
  2. #include "resource.h"   
  3. LRESULT CALLBACK WndProc (HWNDUINTWPARAMLPARAM) ;  
  4. void PThanshu(HWND);//普通画图函数   
  5. void DHChanshu(HWND);//双缓冲画图函数   
  6.   
  7. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,  
  8.                     PSTR szCmdLine, int iCmdShow)  
  9. {  
  10.      static TCHAR szAppName [] = TEXT ("GDI") ;  
  11.      HWND         hwnd ;  
  12.      MSG          msg ;  
  13.      WNDCLASS     wndclass ;  
  14.   
  15.      wndclass.style         = CS_HREDRAW | CS_VREDRAW ;  
  16.      wndclass.lpfnWndProc   = WndProc ;  
  17.      wndclass.cbClsExtra    = 0 ;  
  18.      wndclass.cbWndExtra    = 0 ;  
  19.      wndclass.hInstance     = hInstance ;  
  20.      wndclass.hIcon         = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON1)) ;  
  21.      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;  
  22.      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;  
  23.      wndclass.lpszMenuName  = szAppName;  
  24.      wndclass.lpszClassName = szAppName ;  
  25.        
  26.      if (!RegisterClass (&wndclass))  
  27.      {  
  28.           MessageBox (NULL, TEXT ("This program requires Windows NT!"),  
  29.                       szAppName, MB_ICONERROR) ;  
  30.           return 0 ;  
  31.      }  
  32.        
  33.      hwnd = CreateWindow (szAppName, TEXT ("GDI TEST"),   
  34.                           WS_OVERLAPPEDWINDOW,   
  35.                           CW_USEDEFAULT, CW_USEDEFAULT,  
  36.                           CW_USEDEFAULT, CW_USEDEFAULT,  
  37.                           NULL, NULL, hInstance, NULL) ;  
  38.   
  39.      ShowWindow (hwnd, iCmdShow) ;  
  40.      UpdateWindow (hwnd) ;  
  41.   
  42.      while (GetMessage (&msg, NULL, 0, 0))  
  43.      {  
  44.           TranslateMessage (&msg) ;  
  45.           DispatchMessage (&msg) ;  
  46.      }  
  47.      return msg.wParam ;  
  48. }  
  49.      static int     cxClient, cyClient;  
  50.          static int radius=1;  
  51. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
  52. {  
  53.   
  54.      HDC            hdc;  
  55.      HINSTANCE      hInstance ;  
  56.      static int     pt,gdi;//PT--普通画图,GDI--双缓冲画图   
  57.      PAINTSTRUCT    ps ;  
  58.      RECT     rect;  
  59.   
  60.      TCHAR szAppName[]="GDI";  
  61.        
  62.      switch (message)  
  63.      {  
  64.      case WM_CREATE:  
  65.          SetTimer(hwnd,1,1000,NULL);  
  66.           hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;  
  67.   
  68.           return 0 ;  
  69.      case WM_TIMER:  
  70.          //GetClientRect(hwnd,&rect);//本打算在这里触发WM_PAINT消息的   
  71.         // InvalidateRect(hwnd,&rect,TRUE);   
  72.          if(radius<16)  
  73.          {radius++;}  
  74.          else  
  75.          {radius=0;}  
  76.   
  77.          if(pt)  
  78.          {  
  79.              PThanshu(hwnd);//普通画图   
  80.          }  
  81.          else if(gdi)  
  82.          {  
  83.             DHChanshu(hwnd);//双缓冲画图     
  84.          }  
  85.          else  
  86.              return 0;  
  87.   
  88.   
  89.      case WM_SIZE:  
  90.           //cxClient = LOWORD (lParam) ;   
  91.           //cyClient = HIWORD (lParam) ;   
  92.           return 0 ;  
  93.   
  94.      case WM_PAINT:  
  95.          /*if(pt==1) 
  96.          { 
  97.              hdc = BeginPaint (hwnd, &ps) ; 
  98.              for(int x=0;x<cxClient;x+=16) 
  99.                for(int y=0;y<cyClient;y=+16) 
  100.              { 
  101.                  Ellipse(hdc,x,y,x+radius,y+radius); 
  102.  
  103.              } 
  104.                EndPaint (hwnd, &ps) ; 
  105.          } 
  106.     else 
  107. { 
  108.     hdc=BeginPaint (hwnd, &ps) ; 
  109.     DrawText(hdc,szAppName,-1,&rect,DT_CENTER); 
  110.     EndPaint(hwnd,&ps); 
  111.  
  112. }*/  
  113.          hdc=BeginPaint(hwnd,&ps);  
  114.          GetClientRect(hwnd,&rect);  
  115.          DrawText(hdc,szAppName,-1,&rect,DT_CENTER);  
  116.          EndPaint(hwnd,&ps);  
  117.   
  118.           return 0 ;  
  119.      case WM_COMMAND:  
  120.          if(lParam==0)  
  121.          {  
  122.              switch(wParam)  
  123.              {  
  124.                    
  125.              case IDM_PT://普通画图菜单项ID   
  126.                  pt=1;  
  127.                  gdi=0;  
  128.                  return 0;  
  129.              case IDM_DHC://双缓冲画图菜单项ID   
  130.                  gdi=1;  
  131.                  pt=0;  
  132.                  return 0;  
  133.              default:  
  134.                  return 0;  
  135.                    
  136.              }  
  137.          }  
  138.            
  139.   
  140.      case WM_DESTROY:  
  141.           PostQuitMessage (0) ;  
  142.           return 0 ;  
  143.      }  
  144.      return DefWindowProc (hwnd, message, wParam, lParam) ;  
  145. }  
  146. void PThanshu(HWND hwnd)  
  147. {  
  148.   
  149.     HDC hdc=GetDC(hwnd);  
  150.     RECT  rect;  
  151.     GetClientRect(hwnd,&rect);  
  152.     cxClient=rect.right;  
  153.     cyClient=rect.bottom;  
  154.     FillRect(hdc,&rect,NULL);  
  155.   
  156.     for(int x=0;x<cxClient;x+=16)  
  157.                for(int y=0;y<cyClient;y+=16)  
  158.              {  
  159.                  Ellipse(hdc,x,y,x+radius,y+radius);  
  160.   
  161.              }  
  162.                ReleaseDC(hwnd,hdc);  
  163. }  
  164. void DHChanshu(HWND hwnd)//暂且没实现   
  165. {  
  166.     //MessageBox(hwnd,TEXT("zhaoxujing"),TEXT("yiruirui"),MB_OK);   
  167.     HDC hdc=GetDC(hwnd);  
  168.     RECT rect;  
  169.     GetClientRect(hwnd,&rect);  
  170.     cxClient=rect.right;  
  171.     cyClient=rect.bottom;  
  172.       
  173.     HDC hdcmem=CreateCompatibleDC(hdc);  
  174.     HBITMAP hbitmap=CreateCompatibleBitmap(hdc,cxClient,cyClient);  
  175.     SelectObject(hdcmem,hbitmap);  
  176.   FillRect(hdcmem,&rect,NULL);  
  177.     for(int x=0;x<cxClient;x+=16)  
  178.                for(int y=0;y<cyClient;y+=16)  
  179.              {  
  180.                  Ellipse(hdcmem,x,y,x+radius,y+radius);  
  181.   
  182.              }  
  183.                BitBlt(hdc,0,0,cxClient,cyClient,hdcmem,0,0,SRCCOPY);  
  184.                DeleteObject(hdcmem);  
  185.                ReleaseDC(hwnd,hdc);  
  186.   
  187. }  

 

完整的工程放在了CSDN上,地址:http://download.csdn.net/source/2992685

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1706434次
    • 积分:19618
    • 等级:
    • 排名:第439名
    • 原创:27篇
    • 转载:1525篇
    • 译文:2篇
    • 评论:128条
    最新评论