Udostępnij za pośrednictwem


Korzystanie z funkcji okna

W tej sekcji opisano sposób wykonywania następujących zadań skojarzonych z procedurami okien.

Projektowanie procedury obsługi okna

Poniższy przykład przedstawia strukturę typowej procedury okna (window procedure). Procedura okna używa argumentu komunikatu w instrukcji przełącznika jako, gdzie poszczególne komunikaty są obsługiwane przez oddzielne instrukcje case. Zwróć uwagę, że każdy przypadek zwraca określoną wartość dla każdego komunikatu. W przypadku komunikatów, które nie są przetwarzane, procedura okna wywołuje funkcję DefWindowProc.

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

Komunikat WM_NCCREATE jest wysyłany tuż po utworzeniu okna, ale jeśli aplikacja odpowie na ten komunikat, zwracając false, funkcja CreateWindowEx zakończy się niepowodzeniem. Komunikat WM_CREATE jest wysyłany po utworzeniu okna.

Komunikat WM_DESTROY jest wysyłany, gdy okno ma zostać zniszczone. Funkcja DestroyWindow zajmuje się zniszczeniem wszelkich okien podrzędnych okna, które jest niszczone. Komunikat WM_NCDESTROY jest wysyłany tuż przed zniszczeniem okna.

Przynajmniej procedura okna powinna przetworzyć komunikat WM_PAINT, aby wykonać rysowanie. Zazwyczaj powinna obsługiwać również komunikaty myszy i klawiatury. Zapoznaj się z opisami poszczególnych komunikatów, aby określić, czy procedura okna powinna je obsługiwać.

Aplikacja może wywołać funkcję DefWindowProc w ramach przetwarzania komunikatu. W takim przypadku aplikacja może zmodyfikować parametry komunikatu przed przekazaniem komunikatu do DefWindowProclub może kontynuować domyślne przetwarzanie po wykonaniu własnych operacji.

Procedura okna dialogowego odbiera komunikat WM_INITDIALOG zamiast komunikatu WM_CREATE i nie przekazuje nieprzetworzonych komunikatów do funkcji DefDlgProc. W przeciwnym razie procedura okna dialogowego jest dokładnie taka sama jak procedura okna.

Kojarzenie procedury okna z klasą okien

Podczas rejestrowania klasy okna należy skojarzyć procedurę okna z klasą okien. Należy wypełnić strukturę WNDCLASS informacjami o klasie, a element członkowski lpfnWndProc musi określić adres procedury okna. Aby zarejestrować klasę, przekaż adres struktury WNDCLASS do funkcji RegisterClass . Po zarejestrowaniu klasy okna procedura okna jest automatycznie skojarzona z każdym nowym oknem utworzonym z tą klasą.

W poniższym przykładzie pokazano, jak skojarzyć procedurę okna w poprzednim przykładzie z klasą okien.

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. 
    // 
 
} 

Podklasowanie okna

Aby podklasować wystąpienie okna, wywołaj funkcję SetWindowLong i określ uchwyt do okna z flagą GWL_WNDPROC oraz wskaźnik do procedury podklasy. SetWindowLong zwraca wskaźnik do oryginalnej procedury okna; użyj tego wskaźnika, aby przekazać komunikaty do oryginalnej procedury. Procedura okna podklasy musi używać funkcji CallWindowProc, aby wywołać oryginalną procedurę okna.

Notatka

Aby napisać kod zgodny zarówno z 32-bitowymi, jak i 64-bitowymi wersjami systemu Windows, użyj funkcji SetWindowLongPtr.

 

W poniższym przykładzie pokazano, jak podklasować wystąpienie kontrolki edycji w oknie dialogowym. Procedura okna podklasy umożliwia kontrolce edycji odbieranie wszystkich danych wejściowych klawiatury, w tym ENTER i TAB, za każdym razem, gdy kontrolka ma fokus wejściowy.

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