Uso di procedure di finestra
Questa sezione illustra come eseguire le attività seguenti associate alle procedure della finestra.
- Progettazione di una procedura di finestra
- Associazione di una routine di finestra a una classe Window
- Sottoclasse di una finestra
Progettazione di una procedura di finestra
Nell'esempio seguente viene illustrata la struttura di una routine di finestra tipica. La procedura 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 procedura 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 WM_NCCREATE viene inviato subito dopo la creazione della finestra, ma se un'applicazione risponde a questo messaggio restituisce FALSE, la funzione CreateWindowEx non riesce. Il messaggio WM_CREATE viene inviato dopo la creazione della finestra.
Il messaggio di WM_DESTROY viene inviato quando la finestra sta per essere eliminata. La funzione DestroyWindow si occupa di distruggere qualsiasi finestra figlio della finestra distrutta. Il messaggio WM_NCDESTROY viene inviato appena prima che venga eliminata una finestra.
Almeno, una routine della finestra deve elaborare il messaggio di WM_PAINT per disegnare se stesso. 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 gestirle.
L'applicazione può chiamare la funzione DefWindowProc come parte dell'elaborazione di un messaggio. In tal caso, l'applicazione può modificare i parametri del messaggio prima di passare il messaggio a DefWindowProc oppure continuare con l'elaborazione predefinita dopo aver eseguito le proprie operazioni.
Una procedura della finestra di dialogo riceve un messaggio WM_INITDIALOG anziché un messaggio WM_CREATE e non passa messaggi non elaborati alla funzione DefDlgProc . In caso contrario, una procedura della finestra di dialogo corrisponde esattamente a una routine di finestra.
Associazione di una routine di finestra a una classe Window
Si associa una routine della finestra a una classe di finestra durante la registrazione della classe. È necessario riempire una struttura WNDCLASS con informazioni sulla classe e il membro lpfnWndProc deve specificare l'indirizzo della routine della finestra. Per registrare la classe, passare l'indirizzo della struttura WNDCLASS alla funzione RegisterClass . Dopo aver registrato la classe della finestra, la procedura della finestra viene associata automaticamente a ogni nuova finestra creata con tale classe.
Nell'esempio seguente viene illustrato come associare la routine della finestra nell'esempio precedente a una classe di finestra.
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.
//
}
Sottoclasse di una finestra
Per sottoclassere un'istanza di una finestra, chiamare la funzione SetWindowLong e specificare l'handle nella finestra per sottoclasse il flag di GWL_WNDPROC e un puntatore alla routine della sottoclasse. SetWindowLong restituisce un puntatore alla routine della finestra originale; usare questo puntatore per passare i messaggi alla procedura originale. La procedura della finestra della sottoclasse deve usare la funzione CallWindowProc per chiamare la routine della finestra originale.
Nota
Per scrivere codice compatibile sia con versioni a 32 bit che a 64 bit di Windows, usare la funzione SetWindowLongPtr .
Nell'esempio seguente viene illustrato come sottoclassare un'istanza di un controllo di modifica in una finestra di dialogo. La procedura della finestra della 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.
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);
}