Sök…


Skapa ett fönster

#define UNICODE
#define _UNICODE
#include <windows.h>
#include <tchar.h>
const TCHAR CLSNAME[] = TEXT("helloworldWClass");
LRESULT CALLBACK winproc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp);

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PTSTR cmdline,
                   int cmdshow)
{
    WNDCLASSEX wc = { };
    MSG msg;
    HWND hwnd;

    wc.cbSize        = sizeof (wc);
    wc.style         = 0;
    wc.lpfnWndProc   = winproc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInst;
    wc.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor (NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = CLSNAME;
    wc.hIconSm       = LoadIcon (NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&wc)) {
        MessageBox(NULL, TEXT("Could not register window class"), 
                  NULL, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindowEx(WS_EX_LEFT,
                          CLSNAME,
                          NULL,
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT,
                          CW_USEDEFAULT,
                          CW_USEDEFAULT,
                          CW_USEDEFAULT,
                          NULL,
                          NULL,
                          hInst,
                          NULL);
    if (!hwnd) {
        MessageBox(NULL, TEXT("Could not create window"), NULL, MB_ICONERROR);
        return 0;
    }

    ShowWindow(hwnd, cmdshow);
    UpdateWindow(hwnd);
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK winproc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp)
{
    return DefWindowProc(hwnd, wm, wp, lp);
}

Det första man ser är de två UNICODE , UNICODE och _UNICODE . Dessa makron gör att vårt program förstår breda teckensträngar ( wchar_t[n] ), inte vanliga smala strängar ( char[n] ). Som ett resultat måste alla strängbokstäver vara lindade i en TEXT( makro. Den generiska karaktärstypen för Win32-strängar är TCHAR , vars definition beror på om UNICODE är definierad eller inte. En ny rubrik ingår: <tchar.h> innehåller förklaring av TCHAR .

Ett fönster består av det som kallas fönsterklass . Detta beskriver information om ett fönster som ska delas mellan instanser av det, som ikonen, markören och andra. En fönsterklass identifieras med ett fönsterklassnamn, som anges i den globala variabeln CLSNAME i detta exempel. Den första akten av WinMain är att fylla i fönsterklassstrukturen, WNDCLASSEX wc . Medlemmarna är:

  • cbSize: Storleken, i byte, på strukturen
  • stil: Fönsterklassens stilar. Detta är 0 för nu.
  • lpfnWndProc: Detta är ett av de viktigare fälten. Den lagrar adressen till fönsterproceduren . Fönsterproceduren är en funktion som hanterar händelser för alla fönster som är fall i denna fönsterklass.
  • cbClsExtra: Antalet extra byte som ska tilldelas för fönsterklassen. För de flesta situationer är denna medlem 0.
  • cbWndExtra: Antalet extra byte som ska tilldelas för varje enskilt fönster. Förväxla inte detta med cbClsExtra , vilket är vanligt i alla fall. Detta är ofta 0.
  • hInstance: Instanshandtaget. hInst argumentet i WinMain till det här fältet.
  • hIcon: Ikonhandtaget för fönsterklassen. LoadIcon(NULL, IDI_APPLICATION) laddar standardprogramikonen.
  • h Markör: Markörhandtaget för fönsterklassen. LoadCursor(NULL, IDC_ARROW) laddar standardmarkören.
  • hbrBackground: Ett handtag till bakgrundsborsten. GetStockObject (WHITE_BRUSH) ger ett handtag till en vit borste. GetStockObject måste kastas eftersom GetStockObject returnerar ett generiskt objekt.
  • lpszMenuName: Resursnamnet på menyfältet som ska användas. Om ingen menyfält behövs kan detta fält vara NULL.
  • lpszClassName: Klassnamnet som identifierar denna fönsterklassstruktur. I det här exemplet CLSNAME globala variabeln CLSNAME fönsterklassens namn.
  • hIconSm: Ett handtag till den lilla klassikonen.

När denna struktur har initialiserats kallas funktionen RegisterClassEx . Detta gör att fönsterklassen registreras med Windows, vilket gör det känt för applikationen. Det returnerar 0 vid misslyckande.

Nu när fönsterklassen har registrerats kan vi visa fönstret med CreateWindowEx . Argumenten är:

  • stylesex: De utökade fönsterstilarna. Standardvärdet är WS_EX_LEFT.
  • clsname: Klassnamnet
  • cap: Fönstertitel eller bildtext. I det här fallet är det bildtexten som visas i fönstrets titelfält.
  • stilar: Fönsterstilarna. Om du vill skapa ett toppfönster (förälder) som det här är flaggan som ska passeras WS_OVERLAPPEDWINDOW.
  • x: X-koordinaten i det övre vänstra hörnet av fönstret.
  • y: Y-koordinaten i det övre vänstra hörnet av fönstret
  • cx: Fönsterbredden
  • cy: Höjden på fönstret
  • hwndParent: Handtaget till moderfönstret. Eftersom detta fönster i sig är ett överordnat fönster, är detta argument NULL.
  • hMenuOrID: Om fönstret som skapas är ett överordnat fönster, är detta argument ett handtag till fönstermenyn. Förväxla inte detta med klassmenyn, som är WNDCLASSEX::lpszClassName . Klassmenyn är gemensam för alla instanser av fönster med samma klassnamn. Detta argument är dock specifikt för just det här fallet. Om fönstret som skapas är ett barnfönster är detta ID för barnfönstret. I det här fallet skapar vi ett överordnat fönster utan meny, så NULL passeras.
  • hInst: Handtaget till applikationens instans.
  • etc: Den extra informationen som skickas till fönstret i fönstret. Om ingen extra information ska överföras, skicka NULL.

Om x eller y eller cx eller cy är CW_USEDEFAULT , kommer det argumentets värde att bestämmas av Windows. Det är vad som görs i detta exempel.

CreateWindowEx returnerar handtaget till det nyskapade fönstret. Om skapandet av fönster misslyckades returnerade det NULL .

Vi visar sedan fönstret genom att ringa ShowWindow . Det första argumentet för denna funktion är handtaget till fönstret. Det andra argumentet är showstilen, som indikerar hur fönstret ska visas. De flesta applikationer passerar bara cmdshow argumentet som gick i WinMain . När fönstret visas måste det uppdateras genom ett samtal till UpdateWindow . Det gör att ett uppdateringsmeddelande skickas till fönstret. Vi kommer att lära oss vad det betyder i en annan handledning.

Nu kommer applikationens hjärta: Meddelandepumpen. Den pumpar meddelanden som skickas till denna applikation av operativsystemet och skickar meddelandena till fönsterproceduren. GetMessage samtalet returnerar icke-noll tills applikationen tar emot ett meddelande som får det att sluta, i vilket fall det returnerar 0. Det enda argumentet som berör oss är pekaren till en MSG struktur som kommer att fyllas i med information om meddelandet. De andra argumenten är alla 0.

Inuti meddelandeslingan TranslateMessage TranslateMessage virtuella nyckelmeddelanden till teckenmeddelanden. Betydelsen av detta, återigen, är obetydlig för oss. Det tar en pekare till en MSG struktur. Samtalet som direkt följer det, DispatchMessage , skickar meddelandet som påpekas med dess argument till fönstret i fönstret. Det sista WinMain måste göra är att returnera en statuskod. wParam medlemmen i MSG strukturen innehåller detta returvärde, så det returneras.

Men det är bara för WinMain funktionen. Den andra funktionen är winproc , fönsterproceduren. Det kommer att hantera meddelanden för fönstret som skickas till det av Windows. Signaturen för winproc är:

  • hwnd: Ett handtag till fönstret vars meddelanden behandlas.
  • wm: Fönstermeddelandets identifierare
  • wp: Ett av meddelanden informationsargument. Detta beror på wm argumentet
  • lp: Ett av meddelanden informationsargument. Detta beror på wm argumentet. Detta argument används vanligtvis för att sända pekare eller handtag

I detta enkla program hanterar vi inga meddelanden själv. Men det betyder inte att Windows inte gör det heller. Därför måste man ringa DefWindowProc , som innehåller standardfönsterhanteringskod. Denna funktion måste anropas i slutet av varje fönsterprocedur.

Vad är ett handtag?

Ett handtag är en datatyp som representerar ett unikt objekt. De är pekare, men till hemliga datastrukturer som upprätthålls av operativsystemet. Detaljerna i dessa strukturer behöver inte beröra oss. Allt som en användare behöver göra är att helt enkelt skapa / hämta ett handtag igenom ett API-samtal och skicka det till andra API-samtal som tar den typen av handtag. Den enda typen av handtag som vi använde var HWND returnerades av CreateWindowEx .

Konstanter anter~~POS=HEADCOMP

I det här exemplet stöter vi på en handfull konstanter, som finns i alla-kepsar och börjar med ett prefix med två eller tre bokstäver. (Windows-typerna finns också i all-caps)

  • IDI_APPLICATION: Resursnamnet som innehåller standardprogramikonen. Detta används antingen med LoadIcon eller LoadImage (LoadIcon i detta exempel).
  • IDC_ARROW: Resursnamnet som innehåller standardprogrammarkören. Detta används antingen med LoadIcon eller LoadImage (LoadIcon i detta exempel).
  • WHITE_BRUSH: Namnet på ett lagerobjekt. Detta lagerobjekt är den vita borsten.
  • MB_ICONERROR: En flagga som används med MessageBox att visa en felikon.
  • WS_EX_LEFT: Standardutvidgad fönsterstil. Detta gör att fönstret har vänsterjusterade egenskaper.
  • WS_OVERLAPPEDWINDOW: En fönsterstil som indikerar att fönstret ska vara ett överordnat fönster med en titelrad, storleksrutan och andra element som är typiska för toppnivåfönster.
  • CW_USEDEFAULT: Används med CreateWindowEx x , y , cx eller cy argument. Gör att Windows väljer ett giltigt värde för det argument som CW_USEDEFAULT överfördes för.

Windows-typer

När du programmerar för Windows måste du vänja dig med Win32-typerna, som är alias för inbyggda typer. Dessa typer finns i alla mössor. Aliastyperna som används i detta program är:

  • TCHAR: Den generiska karaktärstypen. Om UNICODE är definierat är detta en wchar_t . I övrigt är det en char .
  • UINT: Ett osignerat heltal. Används för att representera meddelandets identifierare i fönsterprocedurer och andra syften.
  • WPARAM: I Win16 var detta ett WORD-argument (därav W prefixet). Med introduktionen av Win32 är detta emellertid nu en UINT_PTR . Detta illustrerar poängen med dessa Windows-alias; de är där för att skydda program från förändringar.
  • LPARAM: Detta är ett LONG argument ( LONG_PTR i Win64).
  • PTSTR: P betyder pekaren. T betyder generiskt tecken, och STR betyder sträng. Således är detta en pekare till en TCHAR sträng. Andra strängtyper inkluderar:
    • LPTSTR: Samma som PTSTR
    • LPCTSTR: betyder const TCHAR *
    • PCTSTR: Samma som LPCTSTR
    • LPWSTR: Bred sträng ( wchar_t * )
    • LPCWSTR: betyder const wchar_t *
    • PWSTR: Samma som LPWSTR
    • och mycket mer Som ni kan se, kan Win32-typerna vara ett besvär att förstå, särskilt med så många olika typer, som är en artefakt från Win16.
  • LRESULT: Denna typ används för att representera returvärdet för fönsterprocedurer. Det är vanligtvis en LÅNG (därav L ).


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow