Condividi tramite


Utilizzo delle procedure di finestra

In questa sezione viene illustrato come eseguire le attività seguenti associate alle procedure di finestra.

Progettazione di una routine finestra

Nel seguente esempio viene mostrata la struttura di una tipica procedura finestra. La routine della finestra usa l'argomento del messaggio in un'istruzione switch con singoli messaggi gestiti da istruzioni case separate. Si noti che ogni caso restituisce un valore specifico per ogni messaggio. Per i messaggi che non elabora, la routine della finestra chiama la funzione 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; 
} 

Il messaggio di WM_NCCREATE viene inviato subito dopo la creazione della finestra, ma se un'applicazione risponde a questo messaggio restituendo FALSE, funzione CreateWindowEx ha esito negativo. Il messaggio WM_CREATE viene inviato dopo la creazione della finestra.

Il messaggio WM_DESTROY viene inviato quando la finestra sta per essere eliminata definitivamente. La funzione DestroyWindow si occupa di distruggere tutte le finestre figlio della finestra in fase di distruzione. Il messaggio di WM_NCDESTROY viene inviato subito prima che una finestra venga eliminata definitivamente.

Come minimo, una procedura finestra dovrebbe elaborare il messaggio di WM_PAINT per disegnare se stessa. In genere, deve gestire anche i messaggi del mouse e della tastiera. Consultare le descrizioni dei singoli messaggi per determinare se la procedura della finestra deve gestirli.

L'applicazione può chiamare la funzionedefWindowProccome parte dell'elaborazione di un messaggio. In questo caso, l'applicazione può modificare i parametri del messaggio prima di passare il messaggio a DefWindowProcoppure può continuare con l'elaborazione predefinita dopo aver eseguito le proprie operazioni.

Una routine di finestra di dialogo riceve un messaggio di WM_INITDIALOG anziché un messaggio WM_CREATE e non passa messaggi non elaborati alla funzione DefDlgProc. In caso contrario, una routine della finestra di dialogo è esattamente la stessa di una routine di finestra.

Associazione di una routine Window a una classe Window

Quando si registra la classe, si associa una procedura della finestra a una classe di finestra. È necessario compilare una struttura di WNDCLASS con informazioni sulla classe, e il membro lpfnWndProc deve specificare l'indirizzo della procedura finestra. Per registrare la classe, passare l'indirizzo della struttura WNDCLASS alla funzione RegisterClass. Dopo la registrazione della classe window, la routine della finestra viene associata automaticamente a ogni nuova finestra creata con tale classe.

Nell'esempio seguente viene illustrato come associare la routine window nell'esempio precedente a una classe window.

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

Creazione di sottoclassi di una finestra

Per sottoclassare un'istanza di una finestra, chiamare la funzione SetWindowLong e specificare l'handle per la finestra per sottoclassare il flag GWL_WNDPROC e un puntatore alla routine della sottoclasse. SetWindowLong restituisce un puntatore alla routine della finestra originale; utilizzare questo puntatore per passare messaggi alla routine originale. La routine della finestra della sottoclasse deve usare la funzione CallWindowProc per chiamare la routine della finestra originale.

Nota

Per scrivere codice compatibile con entrambe le versioni a 32 bit e a 64 bit di Windows, usare la funzionesetWindowLongPtr.

 

Nell'esempio seguente viene illustrato come sottoclassare un'istanza di un controllo di modifica in una finestra di dialogo. La procedura della finestra di sottoclasse consente al controllo di modifica di ricevere tutti gli input della tastiera, inclusi i tasti INVIO e TAB, ogni volta che il controllo ha lo stato attivo per l'input.

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