Verwenden von Fensterprozeduren

In diesem Abschnitt wird erläutert, wie Die folgenden Aufgaben im Zusammenhang mit Fensterprozeduren ausgeführt werden.

Entwerfen einer Fensterprozedur

Das folgende Beispiel zeigt die Struktur einer typischen Fensterprozedur. Die Fensterprozedur verwendet das Message-Argument in einer switch-Anweisung mit einzelnen Nachrichten, die von separaten Case-Anweisungen behandelt werden. Beachten Sie, dass jeder Fall einen bestimmten Wert für jede Nachricht zurückgibt. Für Nachrichten, die nicht verarbeitet werden, ruft die Fensterprozedur die DefWindowProc-Funktion auf.

LRESULT CALLBACK MainWndProc(
    HWND hwnd,        // handle to window
    UINT uMsg,        // message identifier
    WPARAM wParam,    // first message parameter
    LPARAM lParam)    // second message parameter
{ 
 
    switch (uMsg) 
    { 
        case WM_CREATE: 
            // Initialize the window. 
            return 0; 
 
        case WM_PAINT: 
            // Paint the window's client area. 
            return 0; 
 
        case WM_SIZE: 
            // Set the size and position of the window. 
            return 0; 
 
        case WM_DESTROY: 
            // Clean up window-specific data objects. 
            return 0; 
 
        // 
        // Process other messages. 
        // 
 
        default: 
            return DefWindowProc(hwnd, uMsg, wParam, lParam); 
    } 
    return 0; 
} 

Die WM_NCCREATE Nachricht wird direkt nach dem Erstellen des Fensters gesendet. Wenn jedoch eine Anwendung auf diese Nachricht mit FALSE antwortet, schlägt die CreateWindowEx-Funktion fehl. Die WM_CREATE Nachricht wird gesendet, nachdem Ihr Fenster bereits erstellt wurde.

Die WM_DESTROY Nachricht wird gesendet, wenn Ihr Fenster zerstört werden soll. Die DestroyWindow-Funktion sorgt dafür, dass alle untergeordneten Fenster des zerstörten Fensters zerstört werden. Die WM_NCDESTROY Nachricht wird unmittelbar vor der Zerstörung eines Fensters gesendet.

Zumindest sollte eine Fensterprozedur die WM_PAINT Nachricht verarbeiten, um sich selbst zu zeichnen. In der Regel sollte es auch Maus- und Tastaturnachrichten verarbeiten. Sehen Sie sich die Beschreibungen einzelner Nachrichten an, um zu bestimmen, ob diese von Ihrer Fensterprozedur verarbeitet werden sollen.

Ihre Anwendung kann die DefWindowProc-Funktion im Rahmen der Verarbeitung einer Nachricht aufrufen. In einem solchen Fall kann die Anwendung die Nachrichtenparameter ändern, bevor die Nachricht an DefWindowProc übergeben wird, oder sie kann mit der Standardverarbeitung fortfahren, nachdem sie eigene Vorgänge ausgeführt hat.

Eine Dialogfeldprozedur empfängt anstelle einer WM_CREATE nachricht eine WM_INITDIALOG-Nachricht und übergibt keine nicht verarbeiteten Nachrichten an die DefDlgProc-Funktion. Andernfalls entspricht eine Dialogfeldprozedur genau der einer Fensterprozedur.

Zuordnen einer Window-Prozedur zu einer Window-Klasse

Sie ordnen eine Fensterprozedur einer Fensterklasse zu, wenn Sie die -Klasse registrieren. Sie müssen eine WNDCLASS-Struktur mit Informationen zur -Klasse füllen, und der lpfnWndProc-Member muss die Adresse der Fensterprozedur angeben. Um die Klasse zu registrieren, übergeben Sie die Adresse der WNDCLASS-Struktur an die RegisterClass-Funktion . Nachdem die Fensterklasse registriert wurde, wird die Fensterprozedur automatisch jedem neuen Fenster zugeordnet, das mit dieser Klasse erstellt wurde.

Das folgende Beispiel zeigt, wie die Fensterprozedur im vorherigen Beispiel einer Fensterklasse zugeordnet wird.

int APIENTRY WinMain( 
    HINSTANCE hinstance,  // handle to current instance 
    HINSTANCE hinstPrev,  // handle to previous instance 
    LPSTR lpCmdLine,      // address of command-line string 
    int nCmdShow)         // show-window type 
{ 
    WNDCLASS wc; 
 
    // Register the main window class. 
    wc.style = CS_HREDRAW | CS_VREDRAW; 
    wc.lpfnWndProc = (WNDPROC) MainWndProc; 
    wc.cbClsExtra = 0; 
    wc.cbWndExtra = 0; 
    wc.hInstance = hinstance; 
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wc.hbrBackground = GetStockObject(WHITE_BRUSH); 
    wc.lpszMenuName =  "MainMenu"; 
    wc.lpszClassName = "MainWindowClass"; 
 
    if (!RegisterClass(&wc)) 
       return FALSE; 
 
    // 
    // Process other messages. 
    // 
 
} 

Unterklassen eines Fensters

Um eine instance eines Fensters unterzuklassifizieren, rufen Sie die SetWindowLong-Funktion auf, und geben Sie das Handle für das Fenster an, um das flag GWL_WNDPROC und einen Zeiger auf die Unterklassenprozedur unterzuklassifizieren. SetWindowLong gibt einen Zeiger auf die ursprüngliche Fensterprozedur zurück. Verwenden Sie diesen Zeiger, um Nachrichten an die ursprüngliche Prozedur zu übergeben. Die Unterklassenfensterprozedur muss die CallWindowProc-Funktion verwenden, um die ursprüngliche Fensterprozedur aufzurufen.

Hinweis

Verwenden Sie die SetWindowLongPtr-Funktion , um Code zu schreiben, der sowohl mit 32-Bit- als auch mit 64-Bit-Versionen von Windows kompatibel ist.

 

Das folgende Beispiel zeigt, wie Sie eine instance eines Bearbeitungssteuerelements in einem Dialogfeld unterklassig machen. Die Unterklassenfensterprozedur ermöglicht es dem Bearbeitungssteuerelement, alle Tastatureingaben einschließlich der EINGABETASTE und TAB-TASTE zu empfangen, wenn das Steuerelement den Eingabefokus hat.

WNDPROC wpOrigEditProc; 
 
LRESULT APIENTRY EditBoxProc(
    HWND hwndDlg, 
    UINT uMsg, 
    WPARAM wParam, 
    LPARAM lParam) 
{ 
    HWND hwndEdit; 
 
    switch(uMsg) 
    { 
        case WM_INITDIALOG: 
            // Retrieve the handle to the edit control. 
            hwndEdit = GetDlgItem(hwndDlg, ID_EDIT); 
 
            // Subclass the edit control. 
            wpOrigEditProc = (WNDPROC) SetWindowLong(hwndEdit, 
                GWL_WNDPROC, (LONG) EditSubclassProc); 
            // 
            // Continue the initialization procedure. 
            // 
            return TRUE; 
 
        case WM_DESTROY: 
            // Remove the subclass from the edit control. 
            SetWindowLong(hwndEdit, GWL_WNDPROC, 
                (LONG) wpOrigEditProc); 
            // 
            // Continue the cleanup procedure. 
            // 
            break; 
    } 
    return FALSE; 
        UNREFERENCED_PARAMETER(lParam); 
} 
 
// Subclass procedure 
LRESULT APIENTRY EditSubclassProc(
    HWND hwnd, 
    UINT uMsg, 
    WPARAM wParam, 
    LPARAM lParam) 
{ 
    if (uMsg == WM_GETDLGCODE) 
        return DLGC_WANTALLKEYS; 
 
    return CallWindowProc(wpOrigEditProc, hwnd, uMsg, 
        wParam, lParam); 
}