1。 Text----------------------------------------------------------------

case WM_PAINT:
      {
                  PAINTSTRUCT ps;
         BeginPaint (hwnd, &ps);

          //Make the bottom part of window a pattern so you can see what
         //the transparency flag does
         HBRUSH PatternBrush = CreateHatchBrush(HS_BDIAGONAL, RGB(0,0,255));

         HBRUSH OldBrush = (HBRUSH)SelectObject(ps.hdc, PatternBrush);

         Rectangle(ps.hdc,0, cyClient/2, cxClient, cyClient);

         //replace the old brush
         SelectObject(ps.hdc, OldBrush);

         //first a demonstration of TextOut
         char* text = "1. I ain't got time to bleed.";
         TextOut(ps.hdc, 5, 5, text, strlen(text));

         //now DrawText. First we create a text box
         //文本框
         RECT TextBox;
         TextBox.top = 30;
         TextBox.left = 100;
         TextBox.bottom = 200;
         TextBox.right = cxClient-100;

         //assign some text
         text = "2. You take the blue pill and the story ends.You wake in your bed and believe whatever you want to believe.You take the red pill and you stay in Wonderland and I show you how deep the rabbit-hole goes.";

         //now print the text
         DrawText(ps.hdc, text, strlen(text), &TextBox, DT_WORDBREAK);

         //3. 开始颜色变化
         //now to change the colors. First set text to red
          SetTextColor(ps.hdc, RGB(255, 0, 0));

         //background to black
         SetBkColor(ps.hdc, RGB(0, 0, 0));

         TextBox.top = 200;
         TextBox.left = 5;
         TextBox.bottom = 300;
         TextBox.right = cxClient-200;

         text = "3. The greatest trick the devil ever pulled was convincing the world he didn't exist.";
         DrawText(ps.hdc, text, strlen(text), &TextBox, DT_WORDBREAK);

         //now set background to transparent
         SetBkMode(ps.hdc, TRANSPARENT);

         TextBox.top = 300;
         TextBox.left = 100;
         TextBox.bottom = cyClient;
         TextBox.right = cxClient-50;

         text = "4. ...I抦 42 years old. In less than a year I抣l be dead";
         DrawText(ps.hdc, text, strlen(text), &TextBox, DT_WORDBREAK);
         EndPaint (hwnd, &ps);
      }

2。 使用PeekMessage not GetMessage--------------------------------------------

  // Enter the message loop
       bool bDone = false;

     MSG msg;

       while(!bDone)
     {
          while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
          {
              if( msg.message == WM_QUIT )
              {
                  // Stop loop if it's a quit message
                  bDone = true;
              }

              else
              {
                  TranslateMessage( &msg );
                  DispatchMessage( &msg );
              }
          }

            //this will call WM_PAINT which will render our scene
            InvalidateRect(hWnd, NULL, TRUE);
            UpdateWindow(hWnd);

      //*** your game loop goes here ***//
    }//end while

 

3。 bouncing ball----------------------------------------------------------------

LRESULT CALLBACK WindowProc (HWND   hwnd,
                             UINT   msg,
                             WPARAM wParam,
                             LPARAM lParam)
{

    static HPEN BluePen = CreatePen(PS_SOLID, 1, RGB(0,0,255));
    static HPEN OldPen  = NULL;

    static HBRUSH RedBrush = CreateSolidBrush(RGB(255,0,0));
    static HBRUSH OldBrush = NULL;

    static int cxClient, cyClient;
    //小球
    static SBall* balls = new SBall[NUM_BALLS];

    switch (msg)
    {

        //A WM_CREATE msg is sent when your application window is first
        //created
    case WM_CREATE:
        {
            RECT rect;
            GetClientRect(hwnd, &rect);
            cxClient = rect.right;
            cyClient = rect.bottom;

            srand((unsigned)time(NULL));

            //Initial the balls
            for(int i=0; i<NUM_BALLS; i++){
                balls[i].posX = RandInt(0, cxClient);
                balls[i].posY = RandInt(0, cyClient);
                balls[i].velX = RandInt(0, MAX_VELOCITY);
                balls[i].velY = RandInt(0, MAX_VELOCITY);
            }
            //绘制出小球?用Ellipse
            //让小球移动呢?用改变坐标的方法
            //小球的移动速度如何处理?刷新显示(就能看到)

        }

        break;
    case WM_SIZE:
        {
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
        }
        break;
    case WM_KEYUP:
        {
            switch(wParam)
            {
            case VK_ESCAPE:
                {
                    PostQuitMessage(0);
                }

                break;
            }
        }
        break;

    case WM_PAINT:
        {
            PAINTSTRUCT ps;

            BeginPaint (hwnd, &ps);

            //**this is where we do any drawing to the screen**
            OldPen    = (HPEN) SelectObject(ps.hdc, BluePen);
            OldBrush  = (HBRUSH) SelectObject(ps.hdc, RedBrush);

            for(int i=0; i&lt;NUM_BALLS; ++i){
                if((balls[i].posX>=cxClient)||(balls[i].posY<0))
                    balls[i].velX = -balls[i].velX;
                if((balls[i].posY>=cyClient)||(balls[i].posY<0))
                    balls[i].velY = -balls[i].velY;
                //Update their position
                balls[i].posX += balls[i].velX;
                balls[i].posY += balls[i].velY;

                //Render to display
                Ellipse(ps.hdc,
                    balls[i].posX - RADIUS,5
                    balls[i].posY - RADIUS,
                    balls[i].posX + RADIUS,
                    balls[i].posY + RADIUS);
            }
            SelectObject(ps.hdc, OldPen);
            //and brush
            SelectObject(ps.hdc, OldBrush);
            EndPaint (hwnd, &ps);
            //加了这句就能看到缓慢的刷新过程(移动过程)
            Sleep(10);
        }

        break;

    case WM_DESTROY:
        {
            // kill the application, this sends a WM_QUIT message 
            DeleteObject(BluePen);
            DeleteObject(OldPen);

            //and the brushes
            DeleteObject(RedBrush);
            DeleteObject(OldBrush);

            //and the balls
            delete[] balls;
            PostQuitMessage (0);
        }

        break;

    }//end switch

    //this is where all the messages not specifically handled by our
    //winproc are sent to be processed
    return DefWindowProc (hwnd, msg, wParam, lParam);
}

 

4。 bouncing ball (cache)------------------------------------------------------

      实现双缓冲: 如果要在内存中创建一块区域来表示前置(显示区域),首先需要的,是创建一个与显示DC相兼容的内存设备描述表。 分3步。

  • 用CreateCompatiableDC函数创建一个内存设备描述表:

        HDC hdcBackBuffer = CreateCompatibleDC(NULL);

        用NULL作为参数时,Windows默认创建一个与当前屏幕兼容的DC,而这正是编程者所希望实现的。但当内存设备描述表被创建出来时,它是单色的,并且宽度和高度各为一个像素,这并不实用。 因此, 在开始使用它绘图之前,需要创建一张大小和格式与前置缓冲区完全一致的位图,并利用SelectObject函数将其选入内存DC.

  • 当把显示设备的HDC以及它的高度和宽度作为参数传送到该函数后,它就会返回在内存中创建的一个位图的句柄。因此先要用GetDC函数取得设备描述表的句柄:

        HDC hdc = GetDC(hWnd);

        HBITMAP hBitmap = CreateCompatibleBitmap(hdc, cxClient, cyClient);

  • 最后一步将此位图选入第一步取得的设备描述表中。当这一步完成后,hdcBackBuffer就完成了设置,与前置缓冲的DC完全一样,这样就可以开始朝它绘画了。

         HBITMAP hOldBitMap = (HBITMAP) SelectObject( hdcBackBuffer, hBitmap);

已经存在的1*1像素的单色位图的一个备份被保留,因此可以在绘图完毕时将它返回来,清理后备缓冲。

    • 使用后备缓冲器
    • 1. 清楚后备缓冲--通常采用办法就是用背景色填充;BitBlt
    • 2。在后备缓冲区的hdcBackBuffer中绘图、写字等;
    • 3。将后备缓冲区中的内容复制到前台缓冲区。

LRESULT CALLBACK WindowProc (HWND   hwnd,
                             UINT   msg,
                             WPARAM wParam,
                             LPARAM lParam)
{

    static HPEN BluePen = CreatePen(PS_SOLID, 1, RGB(0,0,255));
    static HPEN OldPen  = NULL;

    static HBRUSH RedBrush = CreateSolidBrush(RGB(255,0,0));
    static HBRUSH OldBrush = NULL;

    static int cxClient, cyClient;
    //小球
    static SBall* balls = new SBall[NUM_BALLS];
    //创建Back Buffer
    static HDC      hdcBackBuffer;
    static HBITMAP  hBitmap;
    static HBITMAP  hOldBitmap;

    switch (msg)
    {

        //A WM_CREATE msg is sent when your application window is first
        //created
    case WM_CREATE:
        {
            RECT rect;
            GetClientRect(hwnd, &rect);
            cxClient = rect.right;
            cyClient = rect.bottom;

            srand((unsigned)time(NULL));

            //Initial the balls
            for(int i=0; i&lt;NUM_BALLS; i++){
                balls[i].posX = RandInt(0, cxClient);
                balls[i].posY = RandInt(0, cyClient);
                balls[i].velX = RandInt(0, MAX_VELOCITY);
                balls[i].velY = RandInt(0, MAX_VELOCITY);
            }
            //绘制出小球?用Ellipse
            //让小球移动呢?用改变坐标的方法
            //小球的移动速度如何处理?刷新显示(就能看到)

            //创建后备缓冲区
            hdcBackBuffer = CreateCompatibleDC(NULL);
            HDC hdc = GetDC(hwnd);
            //cxClient 和 cyClient 变化了怎么办
            hBitmap = CreateCompatibleBitmap(hdc, cxClient, cyClient);
            hOldBitmap = (HBITMAP) SelectObject(hdcBackBuffer, hBitmap);
            //释放DC
            ReleaseDC(hwnd, hdc);

        }

        break;
    case WM_SIZE:
        {
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);

            //双缓冲
            //因为
            SelectObject(hdcBackBuffer, hOldBitmap);
            DeleteObject(hBitmap);
            HDC hdc = GetDC(hwnd);
            hBitmap = CreateCompatibleBitmap(hdc, cxClient, cyClient);
            ReleaseDC(hwnd, hdc);
            SelectObject(hdcBackBuffer, hBitmap);

        }
        break;
    case WM_KEYUP:
        {
            switch(wParam)
            {
            case VK_ESCAPE:
                {
                    PostQuitMessage(0);
                }

                break;
            }
        }
        break;

    case WM_PAINT:
        {
            PAINTSTRUCT ps;

            BeginPaint (hwnd, &ps);

            //1.使用缓冲区,使用BitBlt填充背景
            BitBlt(hdcBackBuffer,
                0,
                0,
                cxClient,
                cyClient,
                NULL,
                NULL,
                NULL,
                WHITENESS);

            //**this is where we do any drawing to the screen**
            OldPen    = (HPEN) SelectObject(hdcBackBuffer, BluePen);
            OldBrush  = (HBRUSH) SelectObject(hdcBackBuffer, RedBrush);

            for(int i=0; i&lt;NUM_BALLS; ++i){
                if((balls[i].posX>=cxClient)||(balls[i].posY<0))
                    balls[i].velX = -balls[i].velX;
                if((balls[i].posY>=cyClient)||(balls[i].posY&lt;0))
                    balls[i].velY = -balls[i].velY;
                //Update their position
                balls[i].posX += balls[i].velX;
                balls[i].posY += balls[i].velY;

                //Render to display
                Ellipse(hdcBackBuffer,
                    balls[i].posX - RADIUS,
                    balls[i].posY - RADIUS,
                    balls[i].posX + RADIUS,
                    balls[i].posY + RADIUS);
            }
            SelectObject(hdcBackBuffer, OldPen);
            //and brush
            SelectObject(hdcBackBuffer, OldBrush);

            BitBlt(ps.hdc,
                0,
                0,
                cxClient,
                cyClient,
                hdcBackBuffer,
                0,
                0,
                SRCCOPY);

            EndPaint (hwnd, &ps);
            //加了这句就能看到缓慢的刷新过程(移动过程)
            Sleep(10);
        }

        break;

    case WM_DESTROY:
        {
            // kill the application, this sends a WM_QUIT message 
            DeleteObject(BluePen);
            DeleteObject(OldPen);

            //and the brushes
            DeleteObject(RedBrush);
            DeleteObject(OldBrush);

            //and the balls
            delete[] balls;

            SelectObject(hdcBackBuffer, hOldBitmap);
            DeleteDC(hdcBackBuffer);
            DeleteObject(hBitmap);

            PostQuitMessage (0);
        }

        break;

    }//end switch

    //this is where all the messages not specifically handled by our
    //winproc are sent to be processed
    return DefWindowProc (hwnd, msg, wParam, lParam);
}

 

//利用到了WNDCLASSEX结构的填充,API还是会把窗口填充为白色背景,造成一定的闪烁
//winclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);