Partilhar via


Usando procedimentos de janela

Esta seção explica como executar as seguintes tarefas associadas aos procedimentos de janela.

Projetando 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 numa instrução switch, em que mensagens individuais são tratadas em instruções case separadas. Observe que cada caso retorna um valor específico para cada mensagem. Para mensagens que 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 janela ser criada, mas, se um aplicativo responder a essa mensagem retornando FALSE, a função CreateWindowEx falhará. A mensagem WM_CREATE é enviada depois que a janela já foi criada.

A mensagem WM_DESTROY é enviada quando a janela está prestes a ser destruída. A função DestroyWindow encarrega-se de destruir todas as janelas infantis da janela que está a ser 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 mesma. Normalmente, ele deve lidar com mensagens de mouse e teclado também. Consulte as descrições das mensagens individuais para determinar se o procedimento da janela deve processá-las.

O seu aplicativo pode chamar a função DefWindowProc como parte do processamento de uma mensagem. Nesse caso, o aplicativo pode modificar os parâmetros da 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çãoDefDlgProc. Caso contrário, um procedimento de caixa de diálogo é exatamente o mesmo que um procedimento de janela.

Associar um processo de janela a uma classe de janela

Você associa um procedimento de janela a uma classe de janela ao registrar a classe. Você deve preencher uma estrutura de WNDCLASS com informações sobre a classe, e o membro do lpfnWndProc deve especificar o endereço do procedimento da janela. Para registar a classe, passe o endereço da estrutura WNDCLASS para a função RegisterClass. Depois que a classe window for registrada, o procedimento window será automaticamente associado a cada nova janela criada com essa classe.

O exemplo a seguir mostra como associar o procedimento window no exemplo anterior a uma 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. 
    // 
 
} 

Subclassificando uma janela

Para subclassificar uma instância de uma janela, chame a função SetWindowLong e especifique o identificador da janela que deve ser subclassificada, o sinalizador GWL_WNDPROC e um ponteiro para o procedimento de subclasse. SetWindowLong retorna um ponteiro para o procedimento da janela original; use este ponteiro para passar mensagens para o procedimento da janela original. O procedimento da janela de subclasse deve usar a função CallWindowProc para chamar o procedimento da janela original.

Observação

Para escrever código compatível com as versões de 32 bits e 64 bits do Windows, use a funçãoSetWindowLongPtr.

 

O exemplo a seguir mostra como subclassificar uma instância de um controle de edição em uma caixa de diálogo. O procedimento da janela de subclasse permite que o controle de edição receba todas as entradas do 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); 
}