转VC绘制位图--BeginPaint()与GetDC()的区别

    技术2022-05-11  54

    //======================================================================== //TITLE: //    EVC绘制位图--BeginPaint()与GetDC()的区别 //AUTHOR: //    norains //DATE: //    Tuesday  29-August-2006 //======================================================================== 1.BeginPaint()和GetDC()         在EVC中绘制位图比较方便,有不少现成的函数可供调用,我们所要注意的只是BeginPaint()或GetDC()的使用即可.         因为代码比较简单,所以不做更多解释.         这是消息循环函数:         LRESULT CALLBACK MainWndProc(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam)         {             ......                          switch(wMsg)             {                 case WM_PAINT:                         OnPaintMainWnd(hWnd,wMsg,wParam,lParam);                         break;                                  ......                                          }             return DefWindowProc(hWnd,wMsg,wParam,lParam);                          ......                      }                  响应WM_PAINT消息的函数,在这里进行位图的绘制:         LRESULT OnPaintMainWnd(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam)         {             PAINTSTRUCT ps;             HDC hdc = BeginPaint(hWnd,&ps);             //Create a DC that matches the device             HDC hdcMem = CreateCompatibleDC(hdc);             //Load the bitmap             HANDLE hBmp= LoadImage(g_hInst_MainWnd,MAKEINTRESOURCE(IDB_MAINWND),IMAGE_BITMAP,0,0,0);             //Select the bitmap into to the compatible device context             HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp);             //Get the bitmap dimensions from the bitmap             BITMAP bmp;             GetObject(hBmp,sizeof(BITMAP),&bmp);             //Get the window area             RECT rc;             GetClientRect(hWnd,&rc);             //Copy the bitmap image from the memory DC to the screen DC             BitBlt(hdc,rc.left,rc.top,bmp.bmWidth,bmp.bmHeight,hdcMem,0,0,SRCCOPY);             //Restore original bitmap selection and destroy the memory DC             SelectObject(hdcMem,hOldSel);                 DeleteDC(hdcMem);             EndPaint(hWnd,&ps);             return 0;         }         我们都知道BeginPaint()和EndPaint()需要配套使用,并且这两个函数也只能用在WM_PAINT消息的相应函数当中.如果我们在WM_PAINT的响应函数中将以上两个绘制函数相应替换为GetDC()和ReleaseDC()会有什么结果呢?         即:         HDC hdc = BeginPaint(hWnd,&ps);    -->   HDC hdc = GetDC(hWnd);         EndPaint(hWnd,&ps);                -->   ReleaseDC(hWnd,hdc);                  编译并运行程序,我们发现窗口一片空白,好像没有绘制位图.但其实不尽然,我们采用单步调试,可以发现其实位图已经绘制出来,只不过又被背景颜色抹掉了.由此可知,如果需要使用GetDC(),我们对消息循环函数必须要加上对WM_ERASEBKGND的处理:         LRESULT CALLBACK MainWndProc(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam)         {             switch(wMsg)             {                 case WM_PAINT:                         OnPaintMainWnd(hWnd,wMsg,wParam,lParam);                         break;                 case WM_ERASEBKGND                             return 0;                         }             return DefWindowProc(hWnd,wMsg,wParam,lParam);         }         只要系统不对WM_ERASEBKGND进行默认处理,我们用GetDC()替代BeginPaint()就可以正常使用.                  至此我们可以看出BeginPaint(),EndPaint()和GetDC(),ReleaseDC()的区别.前一对只能用在WM_PAINT响应函数中,并且绘制背景时不会被抹掉;后一对随处可用,但如果用在WM_PAINT响应函数中,那么接下来将会被WM_ERASEBKGND消息的响应函数的背景绘制给抹掉.                                     2.绘图闪烁问题             有时候我们大量绘制屏幕时,可能会出现屏幕闪烁问题,这时候可以采用双缓冲的做法.步骤首先是创建一个内存DC,然后往内存DC中绘图,最后把内存DC的内容复制到显示DC中,完成绘制.具体过程并不复杂,结合代码来说明一下.     PS:这段代码也是相应WM_PAINT 消息的.          PAINTSTRUCT ps;     HDC hdc;     //获取屏幕显示DC             hdc = BeginPaint (hWnd, &ps);          //创建内存DC     HDC hdcMem = CreateCompatibleDC(hdc);     //创建一个bmp内存空间     HBITMAP hBmp = CreateCompatibleBitmap(hdc,SCREEN_WIDTH,SCREEN_HEIGHT);     //将bmp内存空间分配给内存DC     HGDIOBJ hOldSel = SelectObject(hdcMem,hBmp);          //这是使用者需要绘制的画面,全部往内存DC绘制     Rectangle(hdcMem,0,0,SCREEN_WIDTH,SCREEN_HEIGHT);     DrawMenuButton(hdcMem);          //将内存DC的内容复制到屏幕显示DC中,完成显示     BitBlt(hdc,0,0,SCREEN_WIDTH,SCREEN_HEIGHT,hdcMem,0,0,SRCCOPY);     //清除资源     SelectObject(hdcMem,hOldSel);         DeleteDC(hdcMem);         EndPaint(hWnd,&ps);  

    最新回复(0)