Win32 API:如何在Edit控件中捕获转义键?

时间:2014-01-26 02:11:33

标签: c++ winapi

我发现由于某些未知原因焦点在编辑控件中,Escape键永远不会产生消息。 下面是创建父窗口的代码,以及它上面的编辑控件。在 MyCallBckProcedure()中,我在 printf(),以捕获由编辑生成的消息。更多 - 我甚至试图打印 MyCallBckProcedure()中捕获的所有消息;但如果专注于编辑,则转义键永远不会产生任何消息。 这可能是一个奇怪的问题?

#include <iostream>
#include <windows.h>
#include <stdio.h>

#define IDC_MAIN_EDIT 101

LRESULT __stdcall MyCallBckProcedure( HWND window, unsigned msg, WPARAM wp, LPARAM lp ){
    printf("%x ",msg);
    switch(msg){
        case WM_COMMAND://here should be catched the escape key of Edit
            printf("%x ",msg);
            break;
        case WM_KEYDOWN:
            printf("%x ",msg);
            if(wp == VK_ESCAPE)PostQuitMessage(0);
            break;
        case WM_DESTROY:
            std::cout << "\ndestroying window\n" ;
            PostQuitMessage(0);
            return 0;
        default:
            return DefWindowProc( window, msg, wp, lp ) ;

        break;
        case WM_SIZE:{
            HWND hEdit;
            RECT rcClient;

            GetClientRect(window, &rcClient);

            hEdit = GetDlgItem(window, IDC_MAIN_EDIT);
            SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);
        }
        break;
    }
}

int main(){
    const char* const myclass = "myclass";
    WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, MyCallBckProcedure,
                            0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
                            LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW+1),
                            0, myclass, LoadIcon(0,IDI_APPLICATION) };
    if(RegisterClassEx(&wndclass)<0){
        printf("ERR: in registering window class\n");
        return 1;
    }
    //Creating window
    HWND window = CreateWindowEx( 0, myclass, "title",
                   WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
                   CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0 );
    if(!window){
        printf("ERR: in creating window\n");
        return 1;
    }
    ShowWindow( window, SW_SHOWDEFAULT );
    MSG msg;
    //creating TextBox on the window
    HFONT hfDefault;
    HWND hEdit;
    hEdit = CreateWindowEx(0, "edit", "", 
        WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL, 
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        window, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(NULL), NULL);
    if(hEdit == NULL){
        MessageBox(window, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
        return 1;
    }
    hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
    //Now resize TextBox to fill whole parent window
    RECT RectSize;
    GetClientRect(window,&RectSize);
    hEdit = GetDlgItem(window,IDC_MAIN_EDIT);
    SetWindowPos(hEdit, 0,0,0,RectSize.right,RectSize.bottom,SWP_NOZORDER);
    //Process messages
    while(GetMessage(&msg,0,0,0) ){
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

1 个答案:

答案 0 :(得分:8)

当编辑处于焦点时按 ESC 不会向编辑的父窗口生成WM_COMMAND消息。它会向“编辑”窗口生成WM_KEYDOWNWM_KEYUPWM_CHARWM_UNICHAR条消息。

更新:您只处理发往父窗口的邮件。您需要为编辑窗口分配一个消息过程,例如:

WNDPROC lpEditWndProc;

LRESULT CALLBACK MyEditCallBckProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if( (uMsg == WM_CHAR) && (wParam == VK_ESCAPE) )
    {
        PostQuitMessage(0);
        return 0;
    }
    return CallWindowProc(lpEditWndProc, hWnd, uMsg, wParam, lParam);
}

...

HWND hEdit = CreateWindowEx(...);
lpEditWndProc := (WNDPROC) SetWindowLongPtr(hEdit, GWL_WNDPROC, (LONG_PTR)&MyEditCallBckProcedure);

可替换地:

LRESULT CALLBACK MyEditCallBckProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    if( (uMsg == WM_CHAR) && (wParam == VK_ESCAPE) )
    {
        PostQuitMessage(0);
        return 0;
    }
    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

...

HWND hEdit = CreateWindowEx(...);
SetWindowSubclass(hEdit, &MyEditCallBckProcedure, 0, 0);