Usporedba Direct3D i OpenGL

Kreiranje prozora s Windows API

U prethodnom primjeru prikazano je kako se ispisuje prozor s porukom. Nažalost, ne postoji jedna funkcija za kreiranje forme. Razlog tome je što je Windows forma složen objekt sa puno parametara. Drugi razlog je što je potrebno implementirati upravljanje događajima poput pritisaka tipki, klikanje mišem itd. Kad se dogodi neki događaj poput pritiska neke tipke, Windows šalje poruku aplikaciji koja obrađuje događaje preko WinProc() procedure.

U donjem kodu se vidi način na koji se kreira samo jedna Windows forma. Radi se o priličnom broju linija, ali je ohrabrujuće to što se ovdje samo radi o kostruru tj. ovaj dio ostaje nepromijenjen kasnije kad se u to uključi i Direct3D. U programu se koristi procedura WindowProc() koja se aktivira kad se dogodi neki događaj, odnosno, kad ga Windows detektira. Nakon toga se u switch selekciji ispituje događaj, obavljaju se neke akcije. Ako nije došlo do akcija tada se poziv prosljeđuje Windowsima (ako je potrebno napraviti neke sustavske poslove).

Prozor je kreiran pomoću CreateWindowEx funkcije koja se nalazi u <windowsx.h> datoteci. Prethodno je trebalo registrirati kalsu prozora, postaviti različite parametre (detalje je moguće pogledati u MSDN dokumentacija za Windows API).

// ukljuci headere za windows API
#include <windows.h>
#include <windowsx.h>

// prototip funkcija WindowProc za obradu poruka
LRESULT CALLBACK WindowProc(HWND hWnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam);

// pocetak glavnog programa
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    // handle za prozor
    HWND hWnd;
    // struktura koja sadrzi opis novog prozora
    WNDCLASSEX wc;

    // resetiraj podatke u wc
    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    // popuni opis prozora
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszClassName = L"WindowClass1";

    // registriraj klasu prozora
    RegisterClassEx(&wc);

    // kreiranje prozora
    hWnd = CreateWindowEx(NULL,
                          L"WindowClass1",    // naziv klase
                          L"Novi Win32 prozor",   // naslov na prozoru
                          WS_OVERLAPPEDWINDOW,    // stil prozora (ispred svih)
                          300,    // x-pozicija
                          300,    // y-pozicija
                          500,    // duljina prozora
                          400,    // visina prozora
                          NULL,    // nema prozora roditelja, NULL
                          NULL,    // ne koristi se izbornik, NULL
                          hInstance,    // handle za aplikaciju
                          NULL);    // ne koristi se s vise prozora, NULL

    // prikazi prozor na ekranu
    ShowWindow(hWnd, nCmdShow);

    // kreni u glavnu petlju:

    // struktura koja sadrzi podatke o poruci
    MSG msg;

    // cekaj novu poruku, kad stigne spremi je u strukturu msg
    while(GetMessage(&msg, NULL, 0, 0))
    {
        // prevedi poruku koja je stigla s tipkovnice (znakovi)
        TranslateMessage(&msg);

        // posalji poruku na obradu proceduri WinProc
        DispatchMessage(&msg);
    }

    // vrati poruku o izlazu WM_QUIT windowsima
    return msg.wParam;
}

// funkcija koja je glavni upravitelj porukama u programu
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    // saznaj o kakvoj se poruci radi
    switch(message)
    {
        // ako je prozor zatvoren
        case WM_DESTROY:
            {
                // zatvori aplikaciju
                PostQuitMessage(0);
                return 0;
            } break;
    }

    // upravljanje sistemskim porukama koje switch nije obradio
    return DefWindowProc (hWnd, message, wParam, lParam);
}
	

Za upravljanje događajima se koristi while petlja u kojoj se pomoću funkcije GetMessage() ispituje OS je li stigla nova poruka (u poruci se nalazi opis događaja). Kad je došla nova poruka tada se prosljeđuje proceduri WinProc na obradu.

Kad se malo bolje razmisli, ovakav nađin obrade događaja će predstavljati problem za Direct3D. Slika se u prozoru treba stalno renderirati, ali u ovom slučaju se renderira samo onda kad npr. korisnik pritisne neku tipku ili pomakne miš. Zato su potrebne dodatne promijene da bi se logika prilagodila Direct3d-u.

C++ kod: KreiranjeProzora.cpp

Slijedi: Upravljanje događajima