return 0;
}
break;
case WM_KEYDOWN:
if (wParam < 256) // Is key code in a valid range?
{
gInfo.keys [wParam] = true;
return 0;
}
break;
case WM_KEYUP:
if (wParam < 256)
{
gInfo.keys [wParam] = false;
return 0;
}
break;
case WM_TOGGLEFULLSCREEN: // Toggle full screen mode On/Off
gInfo.bFull = !gInfo.bFull;
PostMessage (hWnd, WM_QUIT, 0, 0);
break;
}
return DefWindowProc (hWnd, msg, wParam, lParam);
}
bool RegisterWndClass ()
{
WNDCLASSEX wc; ZeroMemory (&wc, sizeof(wc));
wc.lpszClassName= gInfo.cls;
wc.hInstance = gInfo.hInst;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.hbrBackground= (HBRUSH)COLOR_WINDOW + 1;
wc.hCursor = LoadCursor (0, IDC_ARROW);
wc.cbSize = sizeof (WNDCLASSEX);
if (RegisterClassEx (&wc) == 0)
{
MessageBox (HWND_DESKTOP, "RegisterClassEx Failed!",
"Error", MB_OK | MB_ICONEXCLAMATION);
return false;
}
return true;
}
bool ReCreate ()
{
if (CreateGLWindow () && Init ())
return true;
MessageBox (HWND_DESKTOP, "Error Creating OpenGL Window",
"Error", MB_OK | MB_ICONEXCLAMATION);
return false;
}
int WINAPI WinMain (HINSTANCE hInst, HINSTANCE, LPSTR, int)
{
gInfo.hInst = hInst; // Store the application handle
if (!RegisterWndClass())
return 0;
if (MessageBox (HWND_DESKTOP, "Start FullScreen?",
"Display Mode", MB_YESNO | MB_ICONQUESTION) == IDNO)
gInfo.bFull = false;
while (!gInfo.bQuit) // Full-screen/Window toggling loop
{
if (!ReCreate ()) // Create a full-screen (or usual) window
break; // and set it up to render OpenGL
MSG msg;
while (true) // Windows message handling loop
{
if (PeekMessage (&msg, gInfo.hWnd, 0, 0, PM_REMOVE) != 0)
{
// Do not quit, but break and see if it is time to really quit (gInfo.bQuit)
if (msg.message == WM_QUIT)
break;
DispatchMessage (&msg);
}
else // If there are no messages
{
if (!gInfo.bVisible)// If window is not visible
WaitMessage (); // It is minimized - wait for a message
else
{
DWORD t = GetTickCount (); // Get The Tick Count
Update (t - gInfo.ticks); // Update The Counter
gInfo.ticks = t;
Draw ();
SwapBuffers (gInfo.hDC);
}
}
}
DestroyGLWindow (); // Destroy The Active Window
}
Deinitialize();
UnregisterClass (gInfo.cls, gInfo.hInst); // UnRegister Window Class
return 0;
}
Здесь вы, вероятно, встретили достаточно много новых (непонятных) элементов и технологических приемов. Новый каркас потребует значительного времени на освоение заложенных в него возможностей. Рекомендую не стараться уяснить все сразу. Вы постепенно к нему привыкните и поймете все детали, а сейчас постарайтесь понять необходимость двух циклов while (см. WinMain), вместо одного, используемого в традиционном каркасе. Они характеризуют новый подход, при котором мы можем переключать экранные режимы. Переключение требует разрушить и заново создать Windows-окно. Именно поэтому необходимо иметь не один цикл обработки сообщений, а два.
q Первый, внешний цикл длится до тех пор, пока пользователь не нажмет клавишу Esc, ALT+F4 или не закроет окно приложения. Он позволяет переключать режимы и заново создавать главное окно (см. вызов функции ReCreate).
q Второй цикл обычно завершается c приходом сообщения WM_QUIT (которое посылается при закрытии окна и обычно завершает приложение), но в нашем случае WM_QUIT не завершает приложение, а лишь позволяет произвести переключение режимов.
q Действительное завершение приложения (внешнего цикла while) осуществляется путем установки в true флага bQuit. Мы делаем это в обработчике WM_CLOSE. Позже мы установим флаг bQuit и при нажатии клавиши Esc.
q Особую роль играют функции Init, Update, Draw и Deinitialize, которые дают возможность другому, пользовательскому модулю управлять анимацией (Update), перерисовкой (Draw), а также ресурсами (Init и Deinitialize).
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.