qxtianlong 发表于 2005-12-17 18:50:25

回顾GDI绘制文本(一)

以下是游戏编程大师技巧里的代码
// get the dc and hold it
HDC hdc = GetDC(hwnd);
// enter main event loop, but this time we use PeekMessage()
// instead of GetMessage() to retrieve messages
while(TRUE)
{
    // test if there is a message in queue, if so get it
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
    {
    // test if this is a quit
       if (msg.message == WM_QUIT)
         break;

    // translate any accelerator keys
    TranslateMessage(&msg);
    // send the message to the window proc
    DispatchMessage(&msg);
    } // end if
   
    // main game processing goes here
   
    // set the foreground color to random
    SetTextColor(hdc, RGB(rand()%256,rand()%256,rand()%256));
    // set the background color to black
    SetBkColor(hdc, RGB(0,0,0));
    // finally set the transparency mode to transparent
    SetBkMode(hdc, TRANSPARENT);
    // draw some text at a random location
    TextOut(hdc,rand()%400,rand()%400, "GDI Text Demo!", strlen("GDI Text Demo!"));
    Sleep(10);

} // end while
// release the dc
ReleaseDC(hwnd,hdc);
以上代码作用是在一个大小400*400的窗口中随机绘制文本"GDI Text Demo!"
文本前景色为随机产生,使用RGB()控制.
文本背景色为黑色.
透明模式为TRANSPARENT
每次绘制采用Sleep(10)作延时
---------------------------------------------------------------------------------------------------------------------------------
我是菜鸟不是高手,在这里不讨论GDI+的内容,在这里发的只是个人的理解,希望对你学习GDI有所帮助^_^

[ 本帖最后由 qxtianlong 于 2005-12-22 10:57 AM 编辑 ]

qxtianlong 发表于 2005-12-22 10:53:11

回顾GDI绘制文本(二)

case WM_SIZE:
         {
         // extract size info
         int width= LOWORD(lparam);
         int height = HIWORD(lparam);
         // get a graphics context
         hdc = GetDC(hwnd);
         // set the foreground color to green
         SetTextColor(hdc, RGB(0,255,0));
         
         // set the background color to black
         SetBkColor(hdc, RGB(0,0,0));
         
         // set the transparency mode to OPAQUE
         SetBkMode(hdc, OPAQUE);
         // draw the size of the window
         sprintf(buffer,"WM_SIZE Called -New Size = (%d,%d)", width, height);
         TextOut(hdc, 0,0, buffer, strlen(buffer));
         // release the dc back
         ReleaseDC(hwnd, hdc);
         } break;
哇哈哈,这次新东西少了,主要是可以通过LOWORD(lparam)和HIWORD(lparam)跟踪客户区的尺寸
透明模式:OPAQUE
但是似乎XP系统里,WM_PAINT消息晚于WM_SIZE消息,这样在WM_SIZE消息中的显示信息都会被擦除啊

qxtianlong 发表于 2005-12-22 10:53:32

回顾GDI绘制文本(三)

case WM_CLOSE:
         {
      // kill message, so no further WM_DESTROY is sent
         return(0);
         } break;         
------------------------------------------------------------------------------------------------------------------------------------
WM_CLOSE消息发送于WM_DESTRY和WM_QUIT之前,所以我们什么都不做就不会传递窗口被关闭的消息了!酷吧~~
------------------------------------------------------------------------------------------------------------------------------------
case WM_CLOSE:
         {
         // display message box
         int result =MessageBox(hwnd, "Are you sure you want to close this application?",
                                        "WM_CLOSE Message Processor",
                                        MB_YESNO | MB_ICONQUESTION);
      
         // does the user want to close?
         if (result == IDYES)
            {
            // call default handler
            return (DefWindowProc(hwnd, msg, wparam, lparam));
            } // end if
         else // throw message away
             return(0);
         } break;         
------------------------------------------------------------------------------------------------------------------------------------
此为根据检测MessageBox的返回值来进行一些处理,当result=IDYES时就默认处理,当然你可以做别的处理啦!

qxtianlong 发表于 2005-12-22 10:53:47

回顾GDI绘制文本(四)

case WM_MOVE:
         {
         // extract the position
         int xpos = LOWORD(lparam);
         int ypos = HIWORD(lparam);
         // get a graphics context
         hdc = GetDC(hwnd);
         // set the foreground color to green
         SetTextColor(hdc, RGB(0,255,0));
         
         // set the background color to black
         SetBkColor(hdc, RGB(0,0,0));
         
         // set the transparency mode to OPAQUE
         SetBkMode(hdc, OPAQUE);
         // draw the size of the window
         sprintf(buffer,"WM_MOVE Called -New Positition = (%d,%d)", xpos, ypos);
         TextOut(hdc, 0,0, buffer, strlen(buffer));
         // release the dc back
         ReleaseDC(hwnd, hdc);
         } break;
这个和以前一样,只不过LOWORD(lparam)和HIWORD(lparam)捕获的是窗口移动时的坐标了而不再是WM_SIZE消息时的窗口大小

qxtianlong 发表于 2005-12-22 10:54:16

回顾GDI绘制文本(五)

case WM_CHAR:
         {
         // get the character
         char ascii_code = wparam;
         unsigned int key_state = lparam;
   
         // get a graphics context
         hdc = GetDC(hwnd);
         // set the foreground color to green
         SetTextColor(hdc, RGB(0,255,0));
         
         // set the background color to black
         SetBkColor(hdc, RGB(0,0,0));
         
         // set the transparency mode to OPAQUE
         SetBkMode(hdc, OPAQUE);
         // print the ascii code and key state
         sprintf(buffer,"WM_CHAR: Character = %c   ",ascii_code);
         TextOut(hdc, 0,0, buffer, strlen(buffer));
         sprintf(buffer,"Key State = 0X%X",key_state);
         TextOut(hdc, 0,16, buffer, strlen(buffer));
         // release the dc back
         ReleaseDC(hwnd, hdc);
         } break;
---------------------------------------------------------------
上面是一个检测按键消息的测试,使用WM_CHAR方式,wparam包含ascII码,lparam包含状态量
按键又一消息方式为
WM_KEYDOWN和WM_KEYUP
他们所不同的是一个跟踪按下的状态、一个跟踪松开时的状态
他们与WM_CHAR所不同的是wparam包含的不是ascII码而是虚拟键码,lparam包含的也是状态量
例如可以通过;
                int virtual_code = (int)wparam;
                switch(virtual_code)
                {
                   case VK_RIGHT:
                   {
                     //do someting
                   }break;
                ……………………
                  default:break;
               }
这样的方式来检测按键所发生的事情.
------------------------------------------------------
还有一种就是用Win32的函数GetAsyncKeyState等这一类的函数检测键盘状态
游戏大师中定义的宏
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
改函数的好处在于没有和事件循环耦合,可以随意的测试按键
例如:
// enter main event loop, but this time we use PeekMessage()
// instead of GetMessage() to retrieve messages
while(TRUE)
{
    // test if there is a message in queue, if so get it
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
    {
    // test if this is a quit
       if (msg.message == WM_QUIT)
         break;

    // translate any accelerator keys
    TranslateMessage(&msg);
    // send the message to the window proc
    DispatchMessage(&msg);
    } // end if
   
       // main game processing goes here

       // get a graphics context
       hdc = GetDC(hwnd);
       // set the foreground color to green
       SetTextColor(hdc, RGB(0,255,0));
         
       // set the background color to black
       SetBkColor(hdc, RGB(0,0,0));
         
       // set the transparency mode to OPAQUE
       SetBkMode(hdc, OPAQUE);
       // print out the state of each arrow key
       sprintf(buffer,"Up Arrow: = %d   ",KEYDOWN(VK_UP));
       TextOut(hdc, 0,0, buffer, strlen(buffer));
       sprintf(buffer,"Down Arrow: = %d   ",KEYDOWN(VK_DOWN));
       TextOut(hdc, 0,16, buffer, strlen(buffer));
       sprintf(buffer,"Right Arrow: = %d   ",KEYDOWN(VK_RIGHT));
       TextOut(hdc, 0,32, buffer, strlen(buffer));
       sprintf(buffer,"Left Arrow: = %d   ",KEYDOWN(VK_LEFT));
       TextOut(hdc, 0,48, buffer, strlen(buffer));
       // release the dc back
       ReleaseDC(hwnd, hdc);
} // end while
以上是在主循环中利用定义的宏不停的测试按键消息

qxtianlong 发表于 2005-12-22 10:54:36

回顾GDI绘制文本(六)

case WM_MOUSEMOVE:
         {
         // get the position of the mouse
         int mouse_x = (int)LOWORD(lparam);
         int mouse_y = (int)HIWORD(lparam);
         // get the button state
         int buttons = (int)wparam;
         // get a graphics context
         hdc = GetDC(hwnd);
         // set the foreground color to green
         SetTextColor(hdc, RGB(0,255,0));
         
         // set the background color to black
         SetBkColor(hdc, RGB(0,0,0));
         
         // set the transparency mode to OPAQUE
         SetBkMode(hdc, OPAQUE);
         // print the ascii code and key state
         sprintf(buffer,"Mouse (X,Y) = (%d,%d)      ",mouse_x,mouse_y);
         TextOut(hdc, 0,0, buffer, strlen(buffer));
         sprintf(buffer,"Right Button = %d",((buttons & MK_RBUTTON) ? 1 : 0));
         TextOut(hdc, 0,16, buffer, strlen(buffer));
         sprintf(buffer,"Left Button = %d",((buttons & MK_LBUTTON) ? 1 : 0));
         TextOut(hdc, 0,32, buffer, strlen(buffer));
         // release the dc back
         ReleaseDC(hwnd, hdc);
         } break;
WM_MOUSEMOVE消息,lparam包含鼠标位置量,wparam包含WM_MOUSEMOVE按键状态量
以上只有在鼠标移动中才会产生消息,如果不移动将不会有消息,不管你有没有按下鼠标键
因为它是WM_MOUSEMOVE!

qxtianlong 发表于 2005-12-22 10:54:57

回顾GDI绘制文本(七)

// enter main event loop, but this time we use PeekMessage()
// instead of GetMessage() to retrieve messages
while(TRUE)
{
    // test if there is a message in queue, if so get it
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
    {
    // test if this is a quit
       if (msg.message == WM_QUIT)
         break;

    // translate any accelerator keys
    TranslateMessage(&msg);
    // send the message to the window proc
    DispatchMessage(&msg);
    } // end if
   
       // main game processing goes here
    if (KEYDOWN(VK_ESCAPE))
          SendMessage(hwnd, WM_CLOSE, 0,0);
      
} // end while
自行发送消息有两种方式:一种是SendMessage(), 一种是PostMessage(),他们的区别在于
SendMessage是向窗口传递一个要求立即处理的消息,接受窗口处理完该消息后,该函数紧接着Winproc()返回.
PostMessage是将消息发送窗口的消息序列中去,如果你不在意延迟可以使用他!
对于窗口的关闭可以使用WM_CLOSE、WM_DESTROY,他们都可以起到关闭的作用。
我们可以利用以前定义的宏来实现:
例如上面的那样:
          if(KEYDOWN(VK_ESCAPE))
               SendMessage(hwnd,WM_CLOSE,0,0);
页: [1]
查看完整版本: 回顾GDI绘制文本(一)