자료실

Win32-키보드 메시지 살펴 보기 날짜:2022-1-31 5:45:16 조회수:164
작성자 : 작가K
포인트 : 1944
가입일 : 2020-02-14 22:27:56
방문횟수 : 293
글 216개, 댓글 82개
소개 : 철들기를 거부하는 개구쟁이 프로그래머
작성글 보기
쪽지 보내기
키보드 메시지는 여러 경로로 전달되는데 일일이 살펴 보기가 무척 어렵습니다.
특히 Alt키와 같이 누르면 시스템 키입력으로 간주하며 한글 입력 상태에서는 IME 메시지로 전달되어
정확하게 언제 어떤 메시지가 왔는지 알기 어렵습니다.
이 코드는 키보드 입력 메시지를 덤프하여 리스트 박스에 보여줍니다. 



창에 포커스를 두고(리스트 박스에 두면 안됨) 키를 누르면 이 키 입력에 대한 메시지를 리스트 박스에 표시합니다.
한글 모드일 때 Alt키와 같이 누를 때 어떤 메시지가 전달되는지 볼 수 있습니다.
Win32 프로젝트를 하나 만들고 다음 소스 파일을 작성하십시오.

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCTSTR lpszClass = TEXT("KeyMsgView");

int APIENTRY WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
    , _In_ LPSTR lpszCmdParam, _In_ int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    WNDCLASS WndClass;
    g_hInst = hInstance;

    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hInstance = hInstance;
    WndClass.lpfnWndProc = WndProc;
    WndClass.lpszClassName = lpszClass;
    WndClass.lpszMenuName = NULL;
    WndClass.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&WndClass);

    hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
        10, 100, 1024, 768,
        NULL, (HMENU)NULL, hInstance, NULL);
    ShowWindow(hWnd, nCmdShow);

    while (GetMessage(&Message, NULL, 0, 0)) {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
    return (int)Message.wParam;
}

HWND hList;
// 키 입력 메시지 한 곳으로 모음
void OnKey(bool bDown, bool bSys, WPARAM wParam, LPARAM lParam)
{
    // wParam에 가상키코드
    UINT vk = (UINT)wParam;
    // b30이 1이면 이전에 눌러져 있었음. 0이면 떨어져 있었음
    bool bPrevdown = (lParam & (1 << 30)) != 0;
    // b24가 1이면 확장키임.
    bool bExtend = (lParam & (1 << 24)) != 0;
    // Alt키와 함께 눌러졌으면 b29가 1이다. 
    bool bWithAlt = (lParam & (1 << 29)) != 0;
    // 하위 16비트에 반복 카운트. 거의 항상 1임
    int repeat = lParam & 0xffff;
    // b16 ~ b23까지 스캔코드
    unsigned char scan = (unsigned char)((lParam & 0xff0000) >> 16);

    TCHAR mes[3];
    TCHAR item[128];

    // 리스트 박스에 출력할 정보 조립
    if (bDown) {
        if (bSys) {
            lstrcpy(mes, L"SD");
        } else {
            lstrcpy(mes, L"KD");
        }
    } else {
        if (bSys) {
            lstrcpy(mes, L"SU");
        } else {
            lstrcpy(mes, L"KU");
        }
    }

    // 키 입력 정보 조립
    wsprintf(item, L"%s VK(wParam)=%x, lParam=%x, prev=%d, ext = %d, scan = %d, repeat = %d, alt = %d",
        mes, wParam, lParam, bPrevdown, bExtend, scan, repeat, bWithAlt);

    // 리스트 박스에 출력하고 제일 마지막 항목을 보이도록 한다.
    SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)item);
    int count = (int)SendMessage(hList, LB_GETCOUNT, 0, 0);
    SendMessage(hList, LB_SETCURSEL, count - 1, 0);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    LPCTSTR mes = TEXT("키보드로부터 입력된 메시지를 보여줍니다.");
    LPCTSTR mes2 = TEXT("마우스 클릭 = 포커스 이동 및 목록 지움");

    switch (iMessage) {
    case WM_CREATE:
        hList = CreateWindow(TEXT("listbox"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL |
            LBS_NOTIFY, 10, 10, 600, 700, hWnd, (HMENU)0, g_hInst, NULL);
        return 0;
    case WM_KEYDOWN:
        // 메뉴키는 0x05로 조사됨
        OnKey(true, false, wParam, lParam);
        return 0;
    case WM_KEYUP:
        OnKey(false, false, wParam, lParam);
        return 0;
    case WM_SYSKEYDOWN:
        // Alt키 입력시 전달. b24가 1이면 오른쪽, 0이면 왼쪽. b30이 0이면 처음 눌림, 1이면 계속 눌려져 있는 것
        OnKey(true, true, wParam, lParam);
        return 0;
    case WM_SYSKEYUP:
        // b24로 확장키 여부만 알 수 있으며 이전 상태인 b30은 항상 1임
        OnKey(false, true, wParam, lParam);
        return 0;
    case WM_LBUTTONDOWN:
        // 클릭시 리스트박스의 포커스를 윈도우로 옮기고 리스트 박스 비움
        SetFocus(hWnd);
        SendMessage(hList, LB_RESETCONTENT, 0, 0);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        TextOut(hdc, 630, 10, mes, lstrlen(mes));
        TextOut(hdc, 630, 30, mes2, lstrlen(mes2));
        EndPaint(hWnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

첨부한 프로젝트는 VS2022로 작성한 것이며 릴리즈 실행 파일도 포함되어 있습니다.
요즘 윈도우가 깐깐해져 실행 파일 때문에 다운로드가 안되는 경우도 있는데 이 경우 소스를 직접 입력해서
만들어 쓰십시오.


 



돈 못 벌어도 좋다. 즐겁게 살면 된다.
첨부 파일 220131-054516_KeyMsgView.zip(46208 byte). 다운로드 : 30

목록보기 삭제 수정 신고 스크랩


로그인하셔야 댓글을 달 수 있습니다.