Suche…


Fenster erstellen

#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);
}

Als erstes sieht man die beiden Makrodefinitionen UNICODE und _UNICODE . Diese Makros bewirken, dass unser Programm breite Zeichenketten ( wchar_t[n] ) und keine einfachen schmalen Zeichenfolgen ( char[n] ) versteht. Als Folge müssen alle Stringliterale in einem gewickelt werden TEXT( Makro Der generische Zeichentyp für Win32 - Strings ist. TCHAR , Definition dessen hängt davon ab , ob oder ob nicht UNICODE definiert ist ein neuer Header enthalten ist. <tchar.h> enthält die Erklärung von TCHAR .

Ein Fenster besteht aus einer sogenannten Fensterklasse . Hier werden Informationen zu einem Fenster beschrieben, das von Instanzen, z. B. dem Symbol, dem Cursor und anderen, gemeinsam genutzt werden soll. Eine Fensterklasse wird durch einen Fensterklassennamen identifiziert, der in diesem Beispiel in der globalen Variablen CLSNAME angegeben ist. Der erste Vorgang von WinMain ist das Ausfüllen der Fensterklassenstruktur WNDCLASSEX wc . Die Mitglieder sind:

  • cbSize: Die Größe der Struktur in Bytes
  • style: Die Fensterklassenstile. Dies ist momentan 0.
  • lpfnWndProc: Dies ist eines der wichtigeren Felder. Es speichert die Adresse der Fensterprozedur . Die Fensterprozedur ist eine Funktion, die Ereignisse für alle Fenster behandelt, die Instanzen dieser Fensterklasse sind.
  • cbClsExtra: Die Anzahl der zusätzlichen Bytes, die für die Fensterklasse zugewiesen werden sollen. In den meisten Situationen ist dieses Mitglied 0.
  • cbWndExtra: Die Anzahl der zusätzlichen Bytes, die für jedes einzelne Fenster zugewiesen werden sollen. Verwechseln Sie dies nicht mit cbClsExtra , das allen Instanzen gemeinsam ist. Dies ist oft 0.
  • hInstance: Das Instanzhandle. hInst WinMain diesem Feld einfach das Argument WinMain in WinMain zu.
  • hIcon: Das Icon-Handle für die Fensterklasse. LoadIcon(NULL, IDI_APPLICATION) lädt das Standardanwendungssymbol.
  • hCursor: Das Cursor-Handle für die Fensterklasse. LoadCursor(NULL, IDC_ARROW) lädt den Standardcursor.
  • hbrBackground: Ein Griff zum Hintergrundpinsel. GetStockObject (WHITE_BRUSH) gibt einem weißen Pinsel einen Griff. Der Rückgabewert muss umgewandelt werden, da GetStockObject ein generisches Objekt zurückgibt.
  • lpszMenuName: Der Ressourcenname der zu verwendenden Menüleiste. Wenn keine Menüleiste benötigt wird, kann dieses Feld NULL sein.
  • lpszClassName: Der Klassenname, der diese Fensterklassenstruktur identifiziert. In diesem Beispiel speichert die globale Variable CLSNAME den CLSNAME des Fensters.
  • hIconSm: Ein Handle für das kleine Klassensymbol.

Nachdem diese Struktur initialisiert wurde, wird die RegisterClassEx Funktion aufgerufen. Dadurch wird die Fensterklasse bei Windows registriert und der Anwendung bekannt gemacht. Bei einem Fehler wird 0 zurückgegeben.

CreateWindowEx die Fensterklasse registriert wurde, können Sie das Fenster mit CreateWindowEx . Die Argumente sind:

  • stylesex: Die erweiterten Fensterstile. Der Standardwert ist WS_EX_LEFT.
  • clsname: Der Klassenname
  • cap: Der Fenstertitel oder die Bildunterschrift. In diesem Fall wird die Beschriftung in der Titelleiste eines Fensters angezeigt.
  • Stile: Die Fensterstile. Wenn Sie ein (übergeordnetes) Fenster der obersten Ebene wie dieses erstellen möchten, ist WS_OVERLAPPEDWINDOW das zu übergebende Flag.
  • x: Die x-Koordinate der oberen linken Ecke des Fensters.
  • y: Die y-Koordinate der oberen linken Ecke des Fensters
  • cx: Die Breite des Fensters
  • cy: Die Höhe des Fensters
  • hwndParent: Das Handle für das übergeordnete Fenster. Da dieses Fenster selbst ein übergeordnetes Fenster ist, ist dieses Argument NULL.
  • hMenuOrID: Wenn das erstellte Fenster ein übergeordnetes Fenster ist, ist dieses Argument ein Handle für das Fenstermenü. Verwechseln Sie dies nicht mit dem Klassenmenü WNDCLASSEX::lpszClassName . Das Klassenmenü gilt für alle Instanzen von Fenstern mit demselben Klassennamen. Dieses Argument ist jedoch nur für diesen Fall spezifisch. Wenn das erstellte Fenster ein untergeordnetes Fenster ist, ist dies die ID des untergeordneten Fensters. In diesem Fall erstellen wir ein übergeordnetes Fenster ohne Menü, sodass NULL übergeben wird.
  • hInst: Das Handle für die Instanz der Anwendung.
  • etc: Die zusätzlichen Informationen, die an die Fensterprozedur des Fensters übergeben werden. Wenn keine zusätzlichen Informationen übertragen werden sollen, übergeben Sie NULL.

Wenn x oder y oder cx oder cy CW_USEDEFAULT ist, wird der Wert dieses Arguments von Windows bestimmt. Das ist, was in diesem Beispiel gemacht wird.

CreateWindowEx gibt das Handle an das neu erstellte Fenster zurück. Wenn die Fenstererstellung fehlgeschlagen ist, wurde NULL .

Wir zeigen dann das Fenster, indem ShowWindow aufrufen. Das erste Argument für diese Funktion ist das Handle für das Fenster. Das zweite Argument ist der Showstil, der angibt, wie das Fenster angezeigt werden soll. Die meisten Anwendungen übergeben nur das in cmdshow Argument WinMain . Nachdem das Fenster angezeigt wird, muss es durch einen Aufruf von UpdateWindow aktualisiert werden. Dadurch wird eine Aktualisierungsnachricht an das Fenster gesendet. Was das bedeutet, erfahren Sie in einem anderen Tutorial.

Nun kommt das Herz der Anwendung: Die Nachrichtenpumpe. Es pumpt Meldungen, die vom Betriebssystem an diese Anwendung gesendet werden, und sendet die Meldungen an die Fensterprozedur. Der GetMessage Aufruf gibt nicht null zurück, bis die Anwendung eine Nachricht erhält, die dazu führt, dass sie beendet wird. In diesem Fall wird 0 zurückgegeben. Das einzige Argument, das uns betrifft, ist der Zeiger auf eine MSG Struktur, die mit Informationen zur Nachricht gefüllt wird. Die anderen Argumente sind alle 0.

Innerhalb der Nachrichtenschleife TranslateMessage TranslateMessage Nachrichten mit virtuellen Schlüsseln in Zeichennachrichten. Die Bedeutung davon ist uns wiederum unwichtig. Es benötigt einen Zeiger auf eine MSG Struktur. Der direkt darauf folgende Aufruf, DispatchMessage , sendet die Nachricht, auf die sein Argument zeigt, an die Fensterprozedur des Fensters. Das letzte, was WinMain tun muss, ist einen Statuscode zurückzugeben. Das wParam Member der MSG Struktur enthält diesen Rückgabewert und wird daher zurückgegeben.

Das ist aber nur für die WinMain Funktion. Die andere Funktion ist winproc , die Fensterprozedur. Es verarbeitet Nachrichten für das Fenster, die von Windows an dieses Fenster gesendet werden. Die Unterschrift für winproc lautet:

  • hwnd: Ein Handle für das Fenster, dessen Nachrichten verarbeitet werden.
  • wm: Die Fensternachrichtenkennung
  • wp: Eines der Nachrichteninformationsargumente. Dies hängt vom Argument wm
  • lp: Eines der Nachrichteninformationsargumente. Dies hängt vom Argument wm . Dieses Argument wird normalerweise verwendet, um Zeiger oder Handles zu übertragen

In diesem einfachen Programm behandeln wir selbst keine Nachrichten. Das heißt aber auch nicht, dass Windows dies nicht tut. Aus diesem Grund muss DefWindowProc , das den Standardcode für die Fensterbehandlung enthält. Diese Funktion muss am Ende jeder Fensterprozedur aufgerufen werden.

Was ist ein Griff?

Ein Handle ist ein Datentyp, der ein eindeutiges Objekt darstellt. Sie sind Zeiger, aber auf geheime Datenstrukturen, die vom Betriebssystem verwaltet werden. Die Details dieser Strukturen brauchen uns nicht zu interessieren. Ein Benutzer muss lediglich einen Handle mithilfe eines API-Aufrufs erstellen / abrufen und ihn an andere API-Aufrufe weiterleiten, die diesen Typ von Handle verwenden. Der einzige Typ von Handle, den wir verwendet haben, war der von HWND zurückgegebene CreateWindowEx .

Konstanten

In diesem Beispiel stoßen wir auf eine Handvoll Konstanten, die in Großbuchstaben stehen und mit einem Präfix aus 2 oder 3 Buchstaben beginnen. (Die Windows-Typen sind auch in Großbuchstaben)

  • IDI_APPLICATION: Der Ressourcenname, der das Standardsymbol der Anwendung enthält. Dies wird entweder mit LoadIcon oder LoadImage (in diesem Beispiel LoadIcon) verwendet.
  • IDC_ARROW: Der Ressourcenname, der den Standard-Anwendungscursor enthält. Dies wird entweder mit LoadIcon oder LoadImage (in diesem Beispiel LoadIcon) verwendet.
  • WHITE_BRUSH: Der Name eines Aktienobjekts. Dieses Lagerobjekt ist der weiße Pinsel.
  • MB_ICONERROR: Ein Flag, das in MessageBox zum Anzeigen eines Fehlersymbols verwendet wird.
  • WS_EX_LEFT: Der Standardstil für erweiterte Fenster. Dies bewirkt, dass das Fenster links ausgerichtete Eigenschaften hat.
  • WS_OVERLAPPEDWINDOW: Ein Fensterstil, der angibt, dass das Fenster ein übergeordnetes Fenster mit einer Titelleiste, einem Größenfeld und anderen Elementen sein sollte, die für Fenster der obersten Ebene typisch sind.
  • CW_USEDEFAULT: Gebrauchte mit CreateWindowEx ‚s x , y , cx oder cy Argumente. Bewirkt, dass Windows einen gültigen Wert für das Argument CW_USEDEFAULT für das CW_USEDEFAULT wurde.

Windows-Typen

Wenn Sie für Windows programmieren, müssen Sie sich an die Win32-Typen gewöhnen, bei denen es sich um Aliase für eingebaute Typen handelt. Diese Typen sind in allen Kappen. Die in diesem Programm verwendeten Alias-Typen sind:

  • TCHAR: Der generische Zeichentyp. Wenn UNICODE definiert ist, ist dies ein wchar_t . Otheriwse, es ist ein char .
  • UINT: Eine vorzeichenlose Ganzzahl. Wird verwendet, um die Nachrichten-ID in Fensterprozeduren und zu anderen Zwecken darzustellen.
  • WPARAM: In Win16 war dies ein WORD-Argument (daher das W Präfix). Mit der Einführung von Win32 ist dies jedoch jetzt ein UINT_PTR . Dies veranschaulicht den Sinn dieser Windows-Aliase. Sie sind dazu da, Programme vor Veränderungen zu schützen.
  • LPARAM: Dies ist ein LONG Argument ( LONG_PTR in Win64).
  • PTSTR: Das P bedeutet Zeiger. Das T für ein generisches Zeichen und das STR eine Zeichenfolge. Dies ist also ein Zeiger auf eine TCHAR Zeichenfolge. Andere Zeichenfolgentypen umfassen:
    • LPTSTR: Wie PTSTR
    • LPCTSTR: Mittel const TCHAR *
    • PCTSTR: Wie LPCTSTR
    • LPWSTR: Wide String ( wchar_t * )
    • LPCWSTR: Bedeutet const wchar_t *
    • PWSTR: Wie LPWSTR
    • und vieles mehr Wie man sieht, lassen sich die Win32-Typen mühelos verstehen, vor allem bei so vielen Typen, die ein Artefakt von Win16 sind.
  • LRESULT: Dieser Typ wird verwendet, um den Rückgabewert von Fensterprozeduren darzustellen. Es ist normalerweise ein LANG (daher das L ).


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow