Программирование стратегических игр с DirectX 9.0

         

Функция WinMain()


Следуя далее мы столкнемся с функцией WinMain(). Как я говорил ранее, она является неотъемлимой частью всех программ Windows, а также является первой функцией, вызываемой во время выполнения программы.

На Рисунок 2.1 под функцией WinMain() располагается блок условия с текстом «Событие для обработки?». Он изображает цикл обработки сообщений, являющийся стандартной частью большинства приложений для Windows. Обычно после того как вы инициализировали программу Windows, чтобы она отображала окно и необходимые кнопки, начинается ожидание событий. В большинстве случаев в коде программы присутствует тот или иной вид цикла, проверяющего наличие событий в очереди. На рисунке это изображено пунктирной линией, ведущей к очереди событий. Цикл обработки событий проверяет очередь, пока не обнаружит наличие в ней какой-либо информации.

Как только в очереди найдено событие, оно извлекается и передается для дальнейшей обработки обработчику сообщений.


Первой представляющей интерес функцией является WinMain(). Как и в любой программе для Windows, она является главной точкой входа в код. Вот как выглядит ее листинг:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hWnd; MSG msg; WNDCLASSEX wndclass; RECT rcWindowClient; // Инициализация класса окна wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = fnMessageProcessor; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "Title Demo"; wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // Регистрация класса окна if(RegisterClassEx(&wndclass) == NULL) { // Выход из программы при сбое exit(1); } // Создание окна hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "Title Demo", "D3D_TitleScreen", WS_OVERLAPPEDWINDOW, 0, 0, g_iWindowWidth, g_iWindowHeight, NULL, NULL, hInstance, NULL); // Отображение окна ShowWindow(hWnd, iCmdShow); // Получение размеров клиентской области GetClientRect(hWnd, &rcWindowClient); // Вычисление смещения визуализации на основе размеров клиентской области g_iXOffset = (g_iWindowWidth - (rcWindowClient.right - rcWindowClient.left)); g_iYOffset = (g_iWindowHeight - (rcWindowClient.bottom - rcWindowClient.top)); // Изменение размеров окна, чтобы они соответствовали желаемому разрешению SetWindowPos(hWnd, NULL, 0, 0, g_iWindowWidth + g_iXOffset, // Ширина g_iWindowHeight + g_iYOffset, // Высота NULL); // Очистка структуры сообщения ZeroMemory(&msg, sizeof(msg)); // Инициализация Direct3D if(SUCCEEDED(InitD3D(hWnd))) { // Инициализация виртуального буфера для отображения четырехугольников vInitInterfaceObjects(); // Вход в цикл сообщений while(msg.message != WM_QUIT) { if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { // Визуализация сцены vRender(); } } } // Освобождение ресурсов и выход из приложения vCleanup(); UnregisterClass("Title Demo", wndclass.hInstance); return 0; }

Чтобы отделить код, относящийся к Direct3D от «стандартного» кода программы для Windows, взгляните на Рисунок 6.12.




Функция WinMain() в рассматриваемой программе изменилась весьма незначительно. Взгляните на приведенный ниже фрагмент кода, в котором выделены главные отличия:

// Инициализация Direct3D if(SUCCEEDED(InitD3D(hWnd))) { // Инициализация виртуального буфера для отображения четырехугольников vInitInterfaceObjects(); // Инициализация активных зон vSetupMouseZones(0); // Начало цикла обработки сообщений while(msg.message != WM_QUIT) { if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { // Если все нормально, обработать щелчок мыши if(timeGetTime() > dwInputTimer) { // Проверка входных данных vCheckInput(); dwInputTimer = timeGetTime() + 50; } // Проверка необходимости выхода из программы if(g_iCurrentScreen == 3) { break; } // Визуализация сцены vRender(); } } }

Первым изменением является добавленный вызов функции vSetupMouseZones(). Программа только что была запущена и вызов этой функции необходим для того, чтобы установить активные зоны для первого экрана. На Рисунок 6.23 показан первый экран, выводимый программой.



Содержание раздела