📄 chapter9.txt
字号:
第一节窗口的移动和改变大小时
case WM_SIZE:
case WM_MOVE:
if (IsIconic(hWnd))
{
Msg("FoxBear is minimized, pausing");
PauseGame();
}
if (bFullscreen)
{
SetRect(&rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
}
else
{
GetClientRect(hWnd, &rcWindow);
ClientToScreen(hWnd, (LPPOINT)&rcWindow);
ClientToScreen(hWnd, (LPPOINT)&rcWindow+1);
}
Msg("WINDOW RECT: [%d,%d,%d,%d]", rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.bottom);
break;
case WM_SIZE:是在窗口的大小被改变时发送的。
case WM_MOVE:是在窗口被移动时发送的。
当收到这两个消息后,首先检测窗口是否最小化了,如果是则暂停游戏。否则再检测游戏是否转为全屏模式,若是则改变用户区的大小为全屏。如果只是改变了窗口的大小但并没有使显示模式变成全屏或窗口最小化,则先取得窗口的用户区坐标(左上角的x、y及右下角的x、y的值)将之存入结构rcWindows,再将rcWindows中的坐标转换为屏幕坐标。请注意rcWindows是RECT型的结构,但ClientToScreen()要求的是POINT型的结构,在结构RECT中存放的是一个矩形的左上角的x、y及右下角的x、y的值而结构POINT中存放的就只是x和y的值。故此在
ClientToScreen(hWnd, (LPPOINT)&rcWindow);
ClientToScreen(hWnd, (LPPOINT)&rcWindow+1);
中先对rcWindow进行强制类型转换,而且两次调用该函数,同时在第二次掉用时使rcWindow的地址自加1。
第二节窗口被激活时
case WM_ACTIVATEAPP:
bIsActive = (BOOL)wParam && GetForegroundWindow() == hWnd;
if (bIsActive)
Msg("FoxBear is active");
else
Msg("FoxBear is not active");
if (bPaused && bIsActive)
{
if (RestoreGame())
{
UnPauseGame();
}
else
{
if (GetForegroundWindow() == hWnd)
{
if (InitGame())
{
UnPauseGame();
}
}
}
}
break;
case WM_ACTIVATEAPP:当不同于当前窗口的应用程序的窗口被激活时发送本消息。
当接收到这个消息时,首先令bIsActive 等于 (BOOL)wParam && GetForegroundWindow() == hWnd,然后检测bIsActive是否为TURE。这里的意思就是检测游戏的窗口是否被激活且处于当前系统中最高优先级。接下来先检测游戏窗口是否是从暂停状态到激活的状态,若是则运行RestoreGame()从新开始,若RestoreGame()成功则运行UnPauseGame(),如果不是从暂停状态到激活的状态,则检测本程序的窗口是否拥有最高的优先级,若有则从新初始化游戏(运行InitGame()),初始化成功后则运行UnPauseGame()。
第三节 实现逻辑调色板时
case WM_QUERYNEWPALETTE:
if (!bFullscreen && lpPalette && lpFrontBuffer)
{
HRESULT ddrval;
ddrval = IDirectDrawSurface_SetPalette(lpFrontBuffer,lpPalette);
if( ddrval == DDERR_SURFACELOST )
{
IDirectDrawSurface_Restore( lpFrontBuffer );
ddrval= IDirectDrawSurface_SetPalette(lpFrontBuffer,lpPalette);
if( ddrval == DDERR_SURFACELOST )
{
Msg(" Failed to restore palette after second try");
}
}
if( ddrval == DD_OK )
{
SetWindowText( hWnd, OUR_APP_NAME );
}
}
break;
WM_QUERYNEWPALETTE:在窗口收到输入焦点前发出,当窗口收到输入焦点后将返回显示它是否能实现逻辑调色板。
在这个消息获得后,程序先检测是否运行于窗口模式且调色板和前缓冲区已设定,然后设定一次调色板,若失败则恢复前缓冲区然后再试一次,如果仍然失败则输出错误信息。两次设定若成功一次则将标题改为“Win Fox Application”。
第四节 改变系统调色板时
case WM_PALETTECHANGED:
if ((HWND)wParam != hWnd)
{
if( !bFullscreen )
{
if( !bStress )
{
Msg("***** PALETTE CHANGED, PAUSING GAME");
PauseGame();
}
else
{
Msg("Lost palette but continuing");
SetWindowText( hWnd, OUR_APP_NAME
" - palette changed COLORS PROBABLY WRONG" )
}
}
}
break;
WM_PALETTECHANGED:本消息在拥有输入焦点的当前窗口实现其逻辑调色板时送往所有的窗口。这时,系统调色板被改变,本消息允许不带输入焦点的窗口使用调色板去实现自己的逻辑调色板和更新其用户区域。
在得到这个消息后,程序首先是否是当前窗口改变了系统调色板,如果是则直接跳出窗口过程,若不是则再检测是否是全屏模式,若是则直接跳出窗口过程,若非则先检测bStress是否为FLASE,若为FLASE则暂停游戏,若为TURE则将标题条改为“ - palette changed COLORS PROBABLY WRONG”。
第五节当操作键按下时
WM_KEYDOWN消息是在一个非系统键按下时产生的,非系统键是指没有按下ALT键时按下的键,或是当某窗口已有输入焦点时按下的键。
在该消息的wParam参数中包含了识别所按下的键的虚键码,由不同的虚键码就可以完成键盘对游戏的操作。我们知道键盘对游戏的操作中所按的键可以分为:操作键和功能键两类。下面让我们先看看例程中是如何定义操作键的吧。
在上一章我们就介绍过在本例程中操作键是小建盘上的“2345678”,但一直没有谈到如何实现的,现在就让我们来看一看。
对操作键的功能的定义是在
case VK_NUMPAD5:
lastInput=KEY_STOP;
break;
case VK_DOWN:
case VK_NUMPAD2:
lastInput=KEY_DOWN;
break;
case VK_LEFT:
case VK_NUMPAD4:
lastInput=KEY_LEFT;
break;
case VK_RIGHT:
case VK_NUMPAD6:
lastInput=KEY_RIGHT;
break;
case VK_UP:
case VK_NUMPAD8:
lastInput=KEY_UP;
break;
case VK_HOME:
case VK_NUMPAD7:
lastInput=KEY_JUMP;
break;
case VK_NUMPAD3:
lastInput=KEY_THROW;
break;
您可以看到在得到每个虚键码之后都对lastInput进行赋值,这时就完成了对操作键的定义了,至于操作键是如何其作用的,在本章的第八节中您可以看到。
第六节 当功能键按下时
在本游戏中的功能键是F3、F4、F5、F6、F7、F8、F9。这些键的作用时什么,是如何实现的呢?下面就让我们一个一个的看看吧!
1.F3的作用是暂停游戏和解除暂停。在程序中这个作用是这样实现的:
case VK_F3:
bPaused = !bPaused;
break;
2.F4的作用是实现ALT+ENTER的作用。在程序中是使用
case VK_F4:
PostMessage(hWnd, WM_SYSKEYUP, VK_RETURN, 0);
break;
4.F6的作用是逐个使用在显示模式列表中的显示模式。
case VK_F6:
{
static i;
if(bFullscreen)
{
for (i=0; i<NumModes; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -