⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 第6小节.txt

📁 游戏编程起源...中文版
💻 TXT
📖 第 1 页 / 共 2 页
字号:
   
  
 傻马乱踢   
 
 
  
游戏编程起源(初学者)Ⅵ
 
 

☆ 关闭你的应用程序(关闭窗口)

有三个消息看起来差不多,都是处理关闭的事情的。它们是WM_DESTROY,WM_CLOSE,和WM_QUIT。它们的确很相似,但你需要知道它们之间的不同!一个窗口或者应用程序应该被关闭时发出WM_CLOSE消息,当接收到WM_CLOSE消息时,如果你愿意,向用户提出是否真的退出。你知道让用户作确认或有错误出现或有什么应该注意的事情发生的时候,往往弹出一个消息框。消息框的制作是很容易的,由于它用途广泛,我们还是介绍一下:

int MessageBox(
    HWND hWnd,         // handle of owner window
    LPCTSTR lpText,    // address of text in message box
    LPCTSTR lpCaption, // address of title of message box
    UINT uType         // style of message box
);

这些参数,尤其是最后一个,需要一些解释:
※ HWND hWnd:过一会儿我将向你介绍一个不含有它的函数,我保证。
※ LPCTSTR lpText:这是将要显示在消息框里的文本。你可以用\n等调整一下格式。
※ LPCCTSTR lpCaption:这是显示在消息框标题栏里的文本。
※ UINT uType:这个参数可以联合使用几个不同的标记。这些标记可以根据你的目的选择,有好多MB_打头的标记供你选择,联合使用时要用“|”分隔开。下面列出了一些常用的:

……按钮类
◎ MB_ABORTRETRYIGNORE:建立有“Abort”、“Retry”、“Ignore”按钮的消息框。
◎ MB_OK:建立有“OK”按钮的消息框。
◎ MB_OKCANCEL:建立有“OK”和“Cancel”按钮的消息框。
◎ MB_RETRYCANCEL:建立有“Retry”、和“Cancel”按钮的消息框。
◎ MB_YESNO:建立有“Yes”和“NO”按钮的消息框。
◎ MB_YESNOCANCEL:建立有“Yes”、“No”和“Cancel”按钮的消息框。

……图标类
◎ MB_ICONEXCLAMATION:加个惊叹号图标。
◎ MB_ICONINFORMATION:加个消息图标。(好像是个问号)
◎ MB_ICONQUESTION:加个问号图标
◎ MB_ICONSTOP:加个停止图标。

……默认按钮标志
◎ MB_DEFBUTTON1:设置第一个按钮为默认按钮。(默认按钮即消息框弹出后,直接敲回车就被按下的那个按钮)
◎ MB_DEFBUTTON2:第二个为默认按钮。
◎ MB_DEFBUTTON3:第三个为默认按钮。
◎ MB_DEFBUTTON4:第四个为默认按钮。

……其它的标志
◎ MB_HELP:添加一个帮助按钮。通常按下该按钮或者敲F1键都将产生WM_HELP消息。
◎ MB_RIGHT:文本右对齐。
◎ MB_TOPMOST:设置消息框总在窗口的最上面。

我不知道你是怎么想的,但是我想Microsoft一定有一个程序员除了一件事,其它什么都不做,那就是全天写#define声明!^_^ 如果消息框建立失败,返回值为0,否则是下列任一个值:
◎ IDABORT:“Abort”按钮被选择。
◎ IDCANCEL:“Cancel”按钮被选择。
◎ IDIGNORE:“Ignore”按钮被选择。
◎ IDNO:“No”按钮被选择。
◎ IDOK:“OK”按钮被选择。
◎ IDRETRY:“Retry”按钮被选择。
◎ IDYES:“Yes”按钮被选择。
以上说了这么多,我几乎都忘了我们原来的话题了。总之,当收到WM_CLOSE消息,你可以做两件事儿。一件是你接受默认的处理返回一个值,你若这样做了,应用程序或窗口按照计划关闭;再者,你返回0,应用程序或窗口将保持原样。以下是代码的基本部分:

if (msg == WM_CLOSE)
{
    if (MessageBox(hMainWindow, "Are you sure want to quit?", "Notice", MB_YESNO | MB_ICONEXCLAMATION) == IDNO)
        return(0);

    // otherwise, let the default handler take care of it
}

WM_DESTROY消息有点儿不同。它是窗口正在关闭时发出的。当得到WM_DESTROY消息的时候,窗口已经从视觉上被删除。一个主窗口被关闭,并不意味着应用程序结束了,它将在没有窗口的条件下继续运行。然而,当一个用户关闭了主窗口,也就意味着他要结束应用程序,所以如果你希望应用程序结束,在收到WM_DESTROY消息的时候,你必须发出一个WM_QUIT消息。你可以使用PostMessage()函数,但由于这是一个特殊的情况,就为它准备了一个特殊的函数:

VOID PostQuitMessage(int nExitCode);

参数nExitCode是你的应用程序返回给Windows的一个退出代码(通常是0)。记住,WinMain()返回的是一个int(实数),不是void(空的)。nExitCode参数的值被赋值给wparam。WM_QUIT消息表示要关闭应用程序,所以得到这个消息后,你应跳出循环,把wparam返回给Windows。下面是一个简单的WinMain()函数实例:

int WinMain(HINSTANCE hinstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
    // initialization stuff goes here

    // main loop - infinite!
    while (TRUE)
    {
        // check the message queue
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT) // exit main loop on WM_QUIT
            break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        // main program logic goes here
    }

    // perform any shutdown functions here - releasing objects and such

    return(msg.wparam); // return exit code to Windows
}

对不起,罗罗嗦嗦讲了这么多,但这些都是你必须要了解的。继续你对我的耐心,让我们看看基础的GDI图形。

☆ 绘制象素
终于到了本章的戏肉儿!只要你取得了显示设备上下文的句柄,就可以用GDI绘制象素了。记住,要调用GetDC()取得句柄。绘制单个的象素,不出意外的话,你就用SetPixel()函数:

COLORREF SetPixel(
    HDC hdc,           // handle to device context
    int X,             // x-coordinate of pixel
    int Y,             // y-coordinate of pixel
    COLORREF crColor   // pixel color
);

返回类型COLORREF是我们没有讲过的。它不是一个结构,但是在表格0x00bbggrr里是一个32位的值。Bb是蓝色成分的8位值,gg是绿色,rr是红色。高字节00没有用,总是00。让我们看看函数里面的参数:
※ HDC hdc:你将要GetDC()得到的DC句柄。(DC就是设备上下文)你只能调用GetDC()一次,然后其它的函数也可以用这个DC句柄了。你每次绘制单个象素不用再取得新的DC句柄了。
※ int X,Y:是象素的x和y坐标。是在客户区的坐标,(0,0)即是窗口客户区左上角的坐标,不是屏幕左上角的坐标。
※ COLORREF crColor:象素的颜色。设置象素的颜色,用RGB()宏最简单。RGB()括号中的三个值分别是红色、绿色和蓝色,各个颜色的值可从0-255间取,不同的值组合成不同的颜色。
如果函数调用成功,将返回一个颜色,就是你要绘制的象素的颜色。由于视频硬件的限制,返回的颜色可能与调用函数时要求的颜色并不一致。如果调用失败,返回-1。如果你要设置窗口客户区的左上角为红色,函数将是这样:

SetPixel(hdc, 0, 0, RGB(255,0, 0));

是在假设你已经取得了DC句柄hdc后,调用这个函数。很简单,是不是?这个函数的更快的版本是SetPixelV():

BOOL SetPixelV(
    HDC hdc,           // handle to device context
    int X,             // x-coordinate of pixel
    int Y,             // y-coordinate of pixel
    COLORREF crColor   // new pixel color
);

参数相同,但返回类型不同。SetPixelV()返回的是布尔类型,成功,TRUE;失败,FALSE。如果你没有必要使用SetPixel()提供的额外信息,那我们当然是选择使用SetPixelV()了。(我们总是希望快一些)
还有一件事情,我们需要得到绘制好的象素的值(颜色)。没问题,使用GetPixel()函数就解决了:

COLORREF GetPixel(
    HDC hdc,  // handle to device context
    int XPos, // x-coordinate of pixel
    int nYPos // y-coordinate of pixel
);

很明显,返回值是象素所在位置的颜色。如果坐标出了DC句柄控制的区域,返回值是CLR_INVALID。参数同SetPixel()差不多:DC句柄,象素的x,y坐标。绘制象素就说到这吧,下面看看GDI的文本输出。

☆ GDI的文本输出函数
有两个关于绘制文本的函数,其中简单一点儿的是TextOut()函数,原形是:

BOOL TextOut(
    HDC hdc,          // handle to device context
    int nXStart,      // x-coordinate of starting position
    int nYStart,      // y-coordinate of starting position
    LPCTSTR lpString, // pointer to string
    int cbString      // number of characters in string
);

我们已经看过很多返回类型是布尔类型的函数了,意思都一样:成功TRUE,失败FALSE。函数的参数如下:
※ HDC hdc:DC句柄。它既可以使GetDC的返回值,也可以是在处理WM_PAINT消息时BeginPaint的返回值。
※ int nXStart,nYStart:定义客户区内字符串开始的位置。字符串中第一个字符的左上角位于坐标(xXStart,nYStart)。在默认DC中,客户区的左上角为(0,0)。
※ LPCTSTR lpString:要显示的字符串。由于下一个参数给出字符串的长度,所有字符串不需要空的中止符。
※ int cbString:串中字符的个数。(字符串的长度)
TextOut()函数使用当前的文本颜色,背景颜色和背景类型。你若想自己改变这些,就得用如下的函数:

COLORREF SetTextColor(
    HDC hdc,         // handle to device context
    COLORREF crColor // text color
);

COLORREF SetBkColor(
    HDC hdc,         // handle of device context
    COLORREF crColor // background color value
);

SetTextColor()函数设置当前文本颜色,SetBkColor()函数设置当前背景颜色。参数的解释是显而易见的。第一个是DC句柄。第二个是颜色,你当然记得可以用RGB()宏来设置颜色。例如设置文本为蓝色:SetTextColor(hdc,RGB(0,0,255))。设置背景为白色:SetBkColor(hdc,RGB(255,255,255))。最后,设置背景类型用SetBkMode()函数:

int SetBkMode(
    HDC hdc,     // handle of device context
    int iBkMode  // flag specifying background mode
);

第一个参数就不讲了。第二个参数iBkMode可以分别取两个值:TRANSPARENT或OPAQUE。如果取TRANSPARENT,文本不会对背景造成影响。如选择OPAQUE,则相反。函数的返回值是背景的模式。
关于TextOut()函数还有一点要说,你可以控制文本的排列方式,用SetTextAlign()实现:

UINT SetTextAlign(
    HDC hdc,    // handle to device context
    UINT fMode  // text-alignment flag
);

参数如下:
※ HDC hdc:DC句柄。没有什么特别的。
※ UINT fMode:一个标志或一组标志(用“|”分开)将决定TextOut()输出文本的对齐模式。你不可以随便组合,要合理组合。这些标志如下:
◎ TA_BASELINE:参考点将在文本的基线。
◎ TA_BOTTOM:参考点将在矩形范围的底边。
◎ TA_TOP:参考点将在矩形范围的顶部。
◎ TA_CENTER:参考点将在矩形范围的中心。
◎ TA_LEFT:参考点将在矩形范围的左边。
◎ TA_RIGHT:参考点将在矩形范围的右边。
◎ TA_NOUPDATECP:当前的位置没有被文本输出函数调用,参考点被每次调用传递。
◎ TA_UPDATECP:当前的位置被每次文本函数输出调用,当前的位置作为参考点。
默认的设置是TA_LEFT|TA_TOP|TA_NOUPDATECP。如果你设置成TA_UPDATECP,后来调用的TextOut()函数将忽略nXStart和nYStart这两个参数,把文本放置在……。OK,告一段落,我们来看看TextOut()函数的兄弟DrawText():

int DrawText(
    HDC hDC,          // handle to device context
    LPCTSTR lpString, // pointer to string to draw
    int nCount,       // string length, in characters

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -