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

原文地址:http://blog.csdn.net/norains/archive/2006/09/07/1189065.aspx

//===================================================================

//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);

 

 

  PS:(朱铭雷),测试了一下norains前辈的代码,在MFC框架下,WM_PAINT 消息响应函数中,BeginPaint()GetDC()都可正常使用。不用手工添加WM_ERASEBKGND的消息响应函数OnEraseBkgnd

  自己的测试代码:http://download.csdn.net/source/2207342

你可能感兴趣的:(VC绘制位图--BeginPaint()与GetDC()的区别)