Usando procedimentos de janela
Esta seção explica como executar as tarefas a seguir associadas aos procedimentos de janela.
- Criando um procedimento de janela
- Associando um procedimento de janela a uma classe window
- Subclasse de uma janela
Criando um procedimento de janela
O exemplo a seguir mostra a estrutura de um procedimento de janela típico. O procedimento de janela usa o argumento de mensagem em uma instrução switch com mensagens individuais manipuladas por instruções case separadas. Observe que cada caso retorna um valor específico para cada mensagem. Para mensagens que ele não processa, o procedimento de janela chama a função 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;
}
A mensagem WM_NCCREATE é enviada logo após a criação da janela, mas se um aplicativo responder a essa mensagem retornando FALSE, a função CreateWindowEx falhará. A mensagem WM_CREATE é enviada após a criação da janela.
A mensagem WM_DESTROY é enviada quando sua janela está prestes a ser destruída. A função DestroyWindow cuida da destruição de qualquer janela filho da janela que está sendo destruída. A mensagem WM_NCDESTROY é enviada pouco antes de uma janela ser destruída.
No mínimo, um procedimento de janela deve processar a mensagem WM_PAINT para desenhar a si mesmo. Normalmente, ele também deve lidar com mensagens de mouse e teclado. Consulte as descrições de mensagens individuais para determinar se o procedimento de janela deve tratá-las.
Seu aplicativo pode chamar a função DefWindowProc como parte do processamento de uma mensagem. Nesse caso, o aplicativo pode modificar os parâmetros de mensagem antes de passar a mensagem para DefWindowProc ou pode continuar com o processamento padrão depois de executar suas próprias operações.
Um procedimento de caixa de diálogo recebe uma mensagem WM_INITDIALOG em vez de uma mensagem WM_CREATE e não passa mensagens não processadas para a função DefDlgProc . Caso contrário, um procedimento de caixa de diálogo é exatamente o mesmo que um procedimento de janela.
Associando um procedimento de janela a uma classe window
Você associa um procedimento de janela a uma classe de janela ao registrar a classe . Você deve preencher uma estrutura WNDCLASS com informações sobre a classe e o membro lpfnWndProc deve especificar o endereço do procedimento de janela. Para registrar a classe, passe o endereço da estrutura WNDCLASS para a função RegisterClass . Depois que a classe de janela for registrada, o procedimento de janela será automaticamente associado a cada nova janela criada com essa classe.
O exemplo a seguir mostra como associar o procedimento de janela no exemplo anterior a uma classe de janela.
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.
//
}
Subclasse de uma janela
Para subclasse uma instância de uma janela, chame a função SetWindowLong e especifique o identificador para a janela para subclasse o sinalizador GWL_WNDPROC e um ponteiro para o procedimento de subclasse. SetWindowLong retorna um ponteiro para o procedimento de janela original; use esse ponteiro para passar mensagens para o procedimento original. O procedimento de janela de subclasse deve usar a função CallWindowProc para chamar o procedimento de janela original.
Observação
Para escrever código compatível com versões de 32 bits e 64 bits do Windows, use a função SetWindowLongPtr .
O exemplo a seguir mostra como subclasse uma instância de um controle de edição em uma caixa de diálogo. O procedimento de janela de subclasse permite que o controle de edição receba todas as entradas de teclado, incluindo as teclas ENTER e TAB, sempre que o controle tiver o foco de entrada.
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);
}