키보드 입력 개요

애플리케이션은 마우스뿐만 아니라 키보드에서도 사용자 입력을 받아들여야 합니다. 애플리케이션은 키보드 입력을 해당 창에 게시된 메시지 형식으로 받습니다.

키보드 입력 모델

시스템은 현재 키보드에 적합한 키보드 디바이스 드라이버를 설치하여 디바이스 독립적 키보드 지원을 애플리케이션에 제공합니다. 시스템은 사용자 또는 애플리케이션에서 현재 선택한 언어별 키보드 레이아웃을 사용하여 언어 독립적 키보드 지원을 제공합니다. 키보드 디바이스 드라이버는 키보드에서 스캔 코드를 받습니다. 이 스캔 코드는 키보드 레이아웃에 보내져 메시지로 변환되고 애플리케이션의 해당 창에 게시됩니다.

키보드의 각 키에 할당된 고유한 값은 스캔 코드라는 키보드 키에 대한 디바이스 종속적 식별자입니다. 사용자가 키를 입력하면 키보드에서 두 개의 스캔 코드를 생성합니다. 하나는 사용자가 키를 누를 때, 다른 하나는 사용자가 키를 놓을 때의 스캔 코드입니다.

키보드 디바이스 드라이버는 스캔 코드를 해석하고 가상 키 코드로 변환(매핑)합니다. 이 코드는 키의 목적을 식별하는 시스템에서 정의하는 디바이스 독립적 값입니다. 스캔 코드가 번역되면 키보드 레이아웃에서 스캔 코드, 가상 키 코드 및 키 입력에 대한 기타 정보를 포함하는 메시지를 만든 다음, 해당 메시지를 시스템 메시지 큐에 배치합니다. 시스템은 시스템 메시지 큐에서 메시지를 제거하고 적절한 스레드의 메시지 큐에 게시합니다. 결국에는 스레드의 메시지 루프에서 메시지를 제거하고 처리를 위한 적절한 창 프로시저에 전달합니다. 다음 그림에서는 키보드 입력 모델을 보여 줍니다.

keyboard input processing model

키보드 포커스 및 활성화

시스템은 키보드 메시지를 키보드 포커스가 있는 창을 만든 포그라운드 스레드의 메시지 큐에 게시합니다. 키보드 포커스는 창의 임시 속성입니다. 시스템은 키보드 포커스를 사용자의 방향으로 한 창에서 다른 창으로 이동하여 디스플레이의 모든 창 간에 키보드를 공유합니다. 키보드 포커스가 있는 창은 포커스가 다른 창으로 변경될 때까지 창을 만든 스레드의 메시지 큐에서 모든 키보드 메시지를 받습니다.

스레드는 GetFocus 함수를 호출하여 현재 키보드 포커스가 있는 창(있는 경우)을 확인할 수 있습니다. 스레드는 SetFocus 함수를 호출하여 키보드 포커스를 창 중 하나에 제공할 수 있습니다. 키보드 포커스가 한 창에서 다른 창으로 변경되면 시스템은 WM_KILLFOCUS 메시지를 포커스가 손실된 창에 보낸 다음, 포커스를 얻은 창에 WM_SETFOCUS 메시지를 보냅니다.

키보드 포커스의 개념은 활성 창의 포커스와 관련이 있습니다. 활성 창은 사용자가 현재 작업 중인 최상위 창입니다. 키보드 포커스가 있는 창은 활성 창이거나 활성 창의 자식 창입니다. 사용자가 활성 창을 식별할 수 있도록 시스템에서 창을 Z 순서의 맨 위에 배치하고 제목 표시줄(있는 경우)과 테두리를 강조 표시합니다.

사용자는 최상위 창을 클릭하거나 Alt+Tab 또는 Alt+Esc 키 조합을 사용하여 선택하거나 작업 목록에서 선택하여 최상위 창을 활성화할 수 있습니다. 스레드는 SetActiveWindow 함수를 사용하여 최상위 창을 활성화할 수 있습니다. GetActiveWindow 함수를 사용하여 만든 최상위 창이 활성 상태인지 여부를 확인할 수 있습니다.

한 창이 비활성화되고 다른 창이 활성화되면 시스템에서 WM_ACTIVATE 메시지를 보냅니다. wParam 매개 변수의 하위 단어는 창이 비활성화되는 경우 0이고, 활성화되는 경우 0이 아닙니다. 기본 창 프로시저에서 WM_ACTIVATE 메시지를 받으면 키보드 포커스가 활성 창으로 설정됩니다.

키보드 및 마우스 입력 이벤트가 애플리케이션에 도달하지 못하도록 차단하려면 BlockInput을 사용합니다. BlockInput 함수는 비동기 키보드 입력 상태 테이블을 방해하지 않습니다. 즉, 입력이 차단된 상태에서 SendInput 함수를 호출하면 비동기 키보드 입력 상태 테이블이 변경됩니다.

키 입력 메시지

키를 누르면 키보드 포커스가 있는 창에 연결된 스레드 메시지 큐에 WM_KEYDOWN 또는 WM_SYSKEYDOWN 메시지가 배치됩니다. 키를 놓으면 WM_KEYUP 또는 WM_SYSKEYUP 메시지가 큐에 배치됩니다.

키 위로 및 키 아래로 메시지는 일반적으로 쌍으로 발생하지만, 사용자가 키보드의 자동 반복 기능을 시작할 수 있을 만큼 키를 길게 누르면 시스템에서 여러 WM_KEYDOWN 또는 WM_SYSKEYDOWN 메시지를 연속으로 생성합니다. 그런 다음, 사용자가 키를 놓으면 단일 WM_KEYUP 또는 WM_SYSKEYUP 메시지를 생성합니다.

이 섹션에서는 다음 항목을 다룹니다.

시스템 및 비 시스템 키 입력

시스템은 시스템 키 입력과 비 시스템 키 입력을 구분합니다. 시스템 키 입력은 WM_SYSKEYDOWNWM_SYSKEYUP 시스템 키 입력 메시지를 생성합니다. 비 시스템 키 입력은 WM_KEYDOWNWM_KEYUP 비 시스템 키 입력 메시지를 생성합니다.

창 프로시저에서 시스템 키 입력 메시지를 처리해야 하는 경우 프로시저에서 메시지를 처리한 후 해당 메시지를 DefWindowProc 함수에 전달해야 합니다. 그렇지 않으면 키보드 포커스가 창에 있을 때마다 Alt 키와 관련된 모든 시스템 작업이 사용하지 않도록 설정됩니다. 즉, 사용자는 창의 메뉴 또는 시스템 메뉴에 액세스할 수 없으며 Alt+Esc 또는 Alt+Tab 키 조합을 사용하여 다른 창을 활성화할 수 없습니다.

시스템 키 입력 메시지는 주로 애플리케이션이 아닌 시스템에서 사용하기 위한 것입니다. 시스템은 이를 사용하여 메뉴에 대한 기본 제공 키보드 인터페이스를 제공하고 사용자가 활성 창을 제어할 수 있도록 합니다. 시스템 키 입력 메시지는 사용자가 Alt 키와 함께 키를 입력하거나 사용자가 입력하고 키보드 포커스가 있는 창이 없을 때(예: 활성 애플리케이션이 최소화된 경우) 생성됩니다. 이 경우 메시지는 활성 창에 연결된 메시지 큐에 게시됩니다.

비 시스템 키 입력 메시지는 애플리케이션 창에서 사용하기 위한 것이며, DefWindowProc 함수는 아무 작업도 수행하지 않습니다. 창 프로시저는 필요하지 않은 비 시스템 키 입력 메시지를 삭제할 수 있습니다.

가상 키 코드 설명

키 입력 메시지의 wParam 매개 변수에는 누르거나 놓은 키의 가상 키 코드가 포함됩니다. 창 프로시저는 가상 키 코드의 값에 따라 키 입력 메시지를 처리하거나 무시합니다.

일반적인 창 프로시저는 받는 키 입력 메시지의 작은 하위 집합만 처리하고 나머지는 무시합니다. 예를 들어 창 프로시저는 WM_KEYDOWN 키 입력 메시지와 커서 이동 키, Shift 키(제어 키라고도 함) 및 기능 키에 대한 가상 키 코드가 포함된 메시지만 처리할 수 있습니다. 일반적인 창 프로시저는 문자 키의 키 입력 메시지를 처리하지 않습니다. 대신 TranslateMessage 함수를 사용하여 메시지를 문자 메시지로 변환합니다. TranslateMessage 및 문자 메시지에 대한 자세한 내용은 문자 메시지를 참조하세요.

키 입력 메시지 플래그

키 입력 메시지의 lParam 매개 변수에는 메시지를 생성한 키 입력에 대한 추가 정보가 포함됩니다. 이 정보에는 반복 횟수, 스캔 코드, 확장 키 플래그, 컨텍스트 코드, 이전 키 상태 플래그전환 상태 플래그가 포함됩니다. 다음 그림에서는 lParam 매개 변수에서 이러한 플래그와 값의 위치를 보여 줍니다.

the locations of the flags and values in the lparam parameter of a keystroke message

애플리케이션은 다음 값을 사용하여 lParam의 상위 단어에서 키 입력 플래그를 가져올 수 있습니다.

설명
KF_EXTENDED
0x0100
확장 키 플래그를 조작합니다.
KF_DLGMODE
0x0800
대화 상자가 활성 상태인지 여부를 나타내는 대화 모드 플래그를 조작합니다.
KF_MENUMODE
0x1000
메뉴가 활성 상태인지 여부를 나타내는 메뉴 모드 플래그를 조작합니다.
KF_ALTDOWN
0x2000
컨텍스트 코드 플래그를 조작합니다.
KF_REPEAT
0x4000
이전 키 상태 플래그를 조작합니다.
KF_UP
0x8000
전환 상태 플래그를 조작합니다.

예제 코드:

case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
{
    WORD vkCode = LOWORD(wParam);                                 // virtual-key code
    
    WORD keyFlags = HIWORD(lParam);

    WORD scanCode = LOBYTE(keyFlags);                             // scan code
    BOOL isExtendedKey = (keyFlags & KF_EXTENDED) == KF_EXTENDED; // extended-key flag, 1 if scancode has 0xE0 prefix
    
    if (isExtendedKey)
        scanCode = MAKEWORD(scanCode, 0xE0);

    BOOL wasKeyDown = (keyFlags & KF_REPEAT) == KF_REPEAT;        // previous key-state flag, 1 on autorepeat
    WORD repeatCount = LOWORD(lParam);                            // repeat count, > 0 if several keydown messages was combined into one message

    BOOL isKeyReleased = (keyFlags & KF_UP) == KF_UP;             // transition-state flag, 1 on keyup

    // if we want to distinguish these keys:
    switch (vkCode)
    {
    case VK_SHIFT:   // converts to VK_LSHIFT or VK_RSHIFT
    case VK_CONTROL: // converts to VK_LCONTROL or VK_RCONTROL
    case VK_MENU:    // converts to VK_LMENU or VK_RMENU
        vkCode = LOWORD(MapVirtualKeyW(scanCode, MAPVK_VSC_TO_VK_EX));
        break;
    }

    // ...
}
break;

반복 횟수

반복 횟수를 확인하여 키 입력 메시지가 둘 이상의 키 입력을 나타내는지 여부를 확인할 수 있습니다. 키보드가 애플리케이션에서 처리할 수 있는 것보다 빠르게 WM_KEYDOWN 또는 WM_SYSKEYDOWN 메시지를 생성하면 시스템에서 횟수를 증분합니다. 이는 사용자가 키보드의 자동 반복 기능을 시작할 수 있을 만큼 키를 길게 누르고 있을 때 발생하는 경우가 많습니다. 시스템 메시지 큐를 결과 키 아래로 메시지로 채우는 대신 시스템에서 메시지를 단일 키 아래로 메시지로 결합하고 반복 횟수를 증분합니다. 키를 놓으면 자동 반복 기능을 시작할 수 없으므로 WM_KEYUPWM_SYSKEYUP 메시지에 대한 반복 횟수는 항상 1로 설정됩니다.

스캔 코드

Diagram of a Type 4 keyboard with the key locations for each key.

스캔 코드는 사용자가 키를 누를 때 시스템에서 생성하는 값입니다. 키가 나타내는 문자와 달리 활성 키보드 레이아웃에 관계없이 누른 키를 식별하는 값입니다. 애플리케이션은 일반적으로 스캔 코드를 무시합니다. 대신 가상 키 코드를 사용하여 키 입력 메시지를 해석합니다.

최신 키보드는 HID(휴먼 인터페이스 디바이스) 사양을 사용하여 컴퓨터와 통신합니다. 키보드 드라이버는 키보드에서 보낸 REPORTED HID 사용량 값을 변환하여 сode를 스캔하고 애플리케이션에 전달합니다.

참고 항목

가상 키 코드는 일반적으로 데스크톱 애플리케이션에 더 유용하지만 현재 키보드 레이아웃에 관계없이 어떤 키를 눌러야 하는지 알아야 하는 경우 특정 경우에 검사 코드가 필요할 수 있습니다. 예를 들어 미국 QWERTY 또는 프랑스어 AZERTY 키보드 레이아웃에서 일관된 키 형성을 보장하는 게임에 대한 WASD(W가 위쪽, A가 왼쪽, S가 다운되고 D가 오른쪽임) 키 바인딩이 있습니다.

다음 표에서는 현재 Windows에서 인식되는 검사 코드 집합을 나열합니다. HID 사용 페이지/HID 사용 ID/HID 사용 이름 값은 HID 사용 테이블 문서를 참조합니다. 키 위치 값은 이전 키보드 이미지를 참조합니다.

스캔 1 만들기 코드는 WM_KEYDOWN WM_KEYUP/WM_SYSKEYDOWN/WM_SYSKEYUP/및 WM_INPUT 메시지로 전달됩니다.

HID 사용 페이지 이름 HID 사용량 이름 HID 사용 페이지 HID 사용량 ID 스캔 1 만들기 키 위치
일반 데스크톱 시스템 전원 다운 0x0001 0x0081 0xE05E
일반 데스크톱 시스템 절전 모드 0x0001 0x0082 0xE05F
일반 데스크톱 시스템 절전 모드 해제 0x0001 0x0083 0xE063
키보드/키패드 ErrorRollOver 0x0007 0x0001 0x00FF
키보드/키패드 키보드 A 0x0007 0x0004 0x001E 31
키보드/키패드 키보드 B 0x0007 0x0005 0x0030 50
키보드/키패드 키보드 C 0x0007 0x0006 0x002E 48
키보드/키패드 키보드 D 0x0007 0x0007 0x0020 33
키보드/키패드 키보드 E 0x0007 0x0008 0x0012 19
키보드/키패드 키보드 F 0x0007 0x0009 0x0021 34
키보드/키패드 키보드 G 0x0007 0x000A 0x0022 35
키보드/키패드 키보드 H 0x0007 0x000B 0x0023 36
키보드/키패드 키보드 I 0x0007 0x000C 0x0017 24
키보드/키패드 키보드 J 0x0007 0x000D 0x0024 37
키보드/키패드 키보드 K 0x0007 0x000E 0x0025 38
키보드/키패드 키보드 L 0x0007 0x000F 0x0026 39
키보드/키패드 키보드 M 0x0007 0x0010 0x0032 52
키보드/키패드 키보드 N 0x0007 0x0011 0x0031 51
키보드/키패드 키보드 O 0x0007 0x0012 0x0018 25
키보드/키패드 키보드 P 0x0007 0x0013 0x0019 26
키보드/키패드 키보드 Q 0x0007 0x0014 0x0010 17
키보드/키패드 키보드 R 0x0007 0x0015 0x0013 20
키보드/키패드 키보드 S 0x0007 0x0016 0x001F 32
키보드/키패드 키보드 T 0x0007 0x0017 0x0014 21
키보드/키패드 키보드 U 0x0007 0x0018 0x0016 23
키보드/키패드 키보드 V 0x0007 0x0019 0x002F 49
키보드/키패드 키보드 W 0x0007 0x001A 0x0011 18
키보드/키패드 키보드 X 0x0007 0x001B 0x002D 47
키보드/키패드 키보드 Y 0x0007 0x001C 0x0015 22
키보드/키패드 키보드 Z 0x0007 0x001D 0x002C 46
키보드/키패드 키보드 1 및 뱅 0x0007 0x001E 0x0002 2
키보드/키패드 키보드 2 및 At 0x0007 0x001F 0x0003 3
키보드/키패드 키보드 3 및 해시 0x0007 0x0020 0x0004 4
키보드/키패드 키보드 4 및 달러 0x0007 0x0021 0x0005 5
키보드/키패드 키보드 5 및 백분율 0x0007 0x0022 0x0006 6
키보드/키패드 키보드 6 및 Caret 0x0007 0x0023 0x0007 7
키보드/키패드 키보드 7 및 앰퍼샌드 0x0007 0x0024 0x0008 8
키보드/키패드 키보드 8 및 별표 0x0007 0x0025 0x0009 9
키보드/키패드 키보드 9 및 왼쪽 대괄호 0x0007 0x0026 0x000A 10
키보드/키패드 키보드 0 및 오른쪽 대괄호 0x0007 0x0027 0x000B 11
키보드/키패드 키보드 반환 Enter 0x0007 0x0028 0x001C 43
키보드/키패드 키보드 이스케이프 0x0007 0x0029 0x0001 110
키보드/키패드 키보드 삭제 0x0007 0x002A 0x000E 15
키보드/키패드 키보드 탭 0x0007 0x002B 0x000F 16
키보드/키패드 키보드 스페이스바 0x0007 0x002C 0x0039 61
키보드/키패드 키보드 대시 및 밑줄 0x0007 0x002D 0x000C 12
키보드/키패드 키보드 등가 및 더하기 0x0007 0x002E 0x000D 13
키보드/키패드 키보드 왼쪽 중괄호 0x0007 0x002F 0x001A 27
키보드/키패드 키보드 오른쪽 중괄호 0x0007 0x0030 0x001B 28
키보드/키패드 키보드 파이프 및 슬래시 0x0007 0x0031 0x002B 29
키보드/키패드 미국 이외의 키보드 0x0007 0x0032 0x002B 42
키보드/키패드 키보드 세미콜론 및 콜론 0x0007 0x0033 0x0027 40
키보드/키패드 키보드 아포스트로피 및 큰따옴표 0x0007 0x0034 0x0028 41
키보드/키패드 키보드 그레이브 악센트 및 물결표 0x0007 0x0035 0x0029 1
키보드/키패드 키보드 쉼표 0x0007 0x0036 0x0033 53
키보드/키패드 키보드 기간 0x0007 0x0037 0x0034 54
키보드/키패드 키보드 질문 표시 0x0007 0x0038 0x0035 55
키보드/키패드 키보드 대문자 잠금 0x0007 0x0039 0x003A 30
키보드/키패드 키보드 F1 0x0007 0x003A 0x003B 112
키보드/키패드 키보드 F2 0x0007 0x003B 0x003C 113
키보드/키패드 키보드 F3 0x0007 0x003C 0x003D 114
키보드/키패드 키보드 F4 0x0007 0x003D 0x003E 115
키보드/키패드 키보드 F5 0x0007 0x003E 0x003F 116
키보드/키패드 키보드 F6 0x0007 0x003F 0x0040 117
키보드/키패드 키보드 F7 0x0007 0x0040 0x0041 118
키보드/키패드 키보드 F8 0x0007 0x0041 0x0042 119
키보드/키패드 키보드 F9 0x0007 0x0042 0x0043 120
키보드/키패드 키보드 F10 0x0007 0x0043 0x0044 121
키보드/키패드 키보드 F11 0x0007 0x0044 0x0057 122
키보드/키패드 키보드 F12 0x0007 0x0045 0x0058 123
키보드/키패드 키보드 PrintScreen 0x0007 0x0046 0xE037
0x0054 *참고 1
124
키보드/키패드 키보드 스크롤 잠금 0x0007 0x0047 0x0046 125
키보드/키패드 키보드 일시 중지 0x0007 0x0048 0xE11D45
0xE046 *참고 2
0x0045 *참고 3
126
키보드/키패드 키보드 삽입 0x0007 0x0049 0xE052 75
키보드/키패드 키보드 홈 0x0007 0x004A 0xE047 80
키보드/키패드 키보드 PageUp 0x0007 0x004B 0xE049 85
키보드/키패드 앞으로 키보드 삭제 0x0007 0x004C 0xE053 76
키보드/키패드 키보드 끝 0x0007 0x004D 0xE04F 81
키보드/키패드 키보드 PageDown 0x0007 0x004E 0xE051 86
키보드/키패드 키보드 RightArrow 0x0007 0x004F 0xE04D 89
키보드/키패드 키보드 LeftArrow 0x0007 0x0050 0xE04B 79
키보드/키패드 키보드 DownArrow 0x0007 0x0051 0xE050 84
키보드/키패드 키보드 UpArrow 0x0007 0x0052 0xE048 83
키보드/키패드 키패드 Num 잠금 및 지우기 0x0007 0x0053 0x0045
0xE045 *참고 3
90
키보드/키패드 키패드 슬래시 0x0007 0x0054 0xE035 95
키보드/키패드 키패드 별 0x0007 0x0055 0x0037 100
키보드/키패드 키패드 대시 0x0007 0x0056 0x004A 105
키보드/키패드 키패드 플러스 0x0007 0x0057 0x004E 106
키보드/키패드 키패드 ENTER 0x0007 0x0058 0xE01C 108
키보드/키패드 키패드 1 및 끝 0x0007 0x0059 0x004F 93
키보드/키패드 키패드 2 및 아래쪽 화살표 0x0007 0x005A 0x0050 98
키보드/키패드 키패드 3 및 PageDn 0x0007 0x005B 0x0051 103
키보드/키패드 키패드 4 및 왼쪽 화살표 0x0007 0x005C 0x004B 92
키보드/키패드 키패드 5 0x0007 0x005D 0x004C 97
키보드/키패드 키패드 6 및 오른쪽 화살표 0x0007 0x005E 0x004D 102
키보드/키패드 키패드 7 및 홈 0x0007 0x005F 0x0047 91
키보드/키패드 키패드 8 및 위쪽 화살표 0x0007 0x0060 0x0048 96
키보드/키패드 키패드 9 및 PageUp 0x0007 0x0061 0x0049 101
키보드/키패드 키패드 0 및 삽입 0x0007 0x0062 0x0052 99
키보드/키패드 키패드 기간 0x0007 0x0063 0x0053 104
키보드/키패드 키보드 미국 이외의 슬래시 막대 0x0007 0x0064 0x0056 45
키보드/키패드 키보드 애플리케이션 0x0007 0x0065 0xE05D 129
키보드/키패드 키보드 전원 0x0007 0x0066 0xE05E
키보드/키패드 키패드 등가 0x0007 0x0067 0x0059
키보드/키패드 키보드 F13 0x0007 0x0068 0x0064
키보드/키패드 키보드 F14 0x0007 0x0069 0x0065
키보드/키패드 키보드 F15 0x0007 0x006A 0x0066
키보드/키패드 키보드 F16 0x0007 0x006B 0x0067
키보드/키패드 키보드 F17 0x0007 0x006C 0x0068
키보드/키패드 키보드 F18 0x0007 0x006D 0x0069
키보드/키패드 키보드 F19 0x0007 0x006E 0x006A
키보드/키패드 키보드 F20 0x0007 0x006F 0x006B
키보드/키패드 키보드 F21 0x0007 0x0070 0x006C
키보드/키패드 키보드 F22 0x0007 0x0071 0x006D
키보드/키패드 키보드 F23 0x0007 0x0072 0x006E
키보드/키패드 키보드 F24 0x0007 0x0073 0x0076
키보드/키패드 키패드 쉼표 0x0007 0x0085 0x007E 107 *참고 4
키보드/키패드 키보드 International1 0x0007 0x0087 0x0073 56 *참고 4, 5
키보드/키패드 키보드 International2 0x0007 0x0088 0x0070 133 *참고 5
키보드/키패드 키보드 국제3 0x0007 0x0089 0x007D 14 *참고 5
키보드/키패드 키보드 International4 0x0007 0x008A 0x0079 132 *참고 5
키보드/키패드 키보드 International5 0x0007 0x008B 0x007B 131 *참고 5
키보드/키패드 키보드 International6 0x0007 0x008C 0x005C
키보드/키패드 키보드 LANG1 0x0007 0x0090 0x0072 *참고 6
0x00F2 *참고 3, 6
키보드/키패드 키보드 LANG2 0x0007 0x0091 0x0071 *참고 6
0x00F1 *참고 3, 6
키보드/키패드 키보드 LANG3 0x0007 0x0092 0x0078
키보드/키패드 키보드 LANG4 0x0007 0x0093 0x0077
키보드/키패드 키보드 LANG5 0x0007 0x0094 0x0076
키보드/키패드 키보드 LeftControl 0x0007 0x00E0 0x001D 58
키보드/키패드 키보드 LeftShift 0x0007 0x00E1 0x002A 44
키보드/키패드 키보드 LeftAlt 0x0007 0x00E2 0x0038 60
키보드/키패드 키보드 왼쪽 GUI 0x0007 0x00E3 0xE05B 127
키보드/키패드 키보드 RightControl 0x0007 0x00E4 0xE01D 64
키보드/키패드 키보드 RightShift 0x0007 0x00E5 0x0036 57
키보드/키패드 키보드 RightAlt 0x0007 0x00E6 0xE038 62
키보드/키패드 키보드 오른쪽 GUI 0x0007 0x00E7 0xE05C 128
소비자 다음 트랙 검사 0x000C 0x00B5 0xE019
소비자 이전 트랙 검사 0x000C 0x00B6 0xE010
소비자 중지 0x000C 0x00B7 0xE024
소비자 재생/일시 정지 0x000C 0x00CD 0xE022
소비자 음소거 0x000C 0x00E2 0xE020
소비자 볼륨 증가 0x000C 0x00E9 0xE030
소비자 볼륨 감소 0x000C 0x00EA 0xE02E
소비자 AL 소비자 제어 구성 0x000C 0x0183 0xE06D
소비자 AL 전자 메일 읽기 권한자 0x000C 0x018A 0xE06C
소비자 AL 계산기 0x000C 0x0192 0xE021
소비자 AL 로컬 컴퓨터 브라우저 0x000C 0x0194 0xE06B
소비자 AC 검색 0x000C 0x0221 0xE065
소비자 AC 홈 0x000C 0x0223 0xE032
소비자 AC 뒤로 0x000C 0x0224 0xE06A
소비자 AC Forward 0x000C 0x0225 0xE069
소비자 AC 중지 0x000C 0x0226 0xE068
소비자 AC 새로 고침 0x000C 0x0227 0xE067
소비자 AC 책갈피 0x000C 0x022A 0xE066

참고:

  1. Alt+Print 화면 키 입력에 SysRq 키 검사 코드가 내보내집니다.
  2. Control+Pause 키 입력 시 중단 키 검사 코드가 내보내집니다.
  3. 레거시 키보드 메시지에서 볼 수 있듯이
  4. 키는 브라질 키보드에 있습니다.
  5. 키는 일본어 키보드에 있습니다.
  6. 검사 코드는 키 릴리스 이벤트에만 내보내집니다.

확장 키 플래그

확장 키 플래그는 키 입력 메시지가 향상된 101/102 키 키보드의 추가 키 중 하나에서 시작되었는지 여부를 나타냅니다. 확장 키는 키보드의 오른쪽에 있는 Alt 및 Ctrl 키, 숫자 키패드의 왼쪽 모음에 있는 Ins, Del, Home, End, Page Up, Page Down 및 화살표 키, Num Lock 키, Break(Ctrl+Pause) 키, Print Screen 키 및 숫자 키패드의 나누기(/) 및 Enter 키로 구성됩니다. 오른쪽 Shift 키는 확장 키로 간주되지 않으며, 대신 별도의 스캔 코드가 있습니다.

지정되는 경우 스캔 코드는 2바이트 시퀀스로 구성되며, 첫 번째 바이트의 값은 0xE0입니다.

컨텍스트 코드

컨텍스트 코드는 키 입력 메시지가 생성되었을 때 Alt 키를 눌렀는지 여부를 나타냅니다. Alt 키를 눌렀으면 코드는 1이고, 놓았으면 0입니다.

이전 키 상태 플래그

이전 키 상태 플래그는 키 입력 메시지를 생성한 키를 이전에 눌렀거나 놓았는지 여부를 나타냅니다. 이전에 키를 눌렀으면 1이고, 이전에 키를 놓았으면 0입니다. 이 플래그를 사용하여 키보드의 자동 반복 기능에서 생성된 키 입력 메시지를 식별할 수 있습니다. 이 플래그는 자동 반복 기능에서 생성된 WM_KEYDOWNWM_SYSKEYDOWN 키 입력 메시지에 대해 1로 설정됩니다. WM_KEYUPWM_SYSKEYUP 메시지에 대해서는 항상 1로 설정됩니다.

전환 상태 플래그

전환 상태 플래그는 키 입력 메시지를 생성한 키를 누르거나 놓았는지 여부를 나타냅니다. 이 플래그는 WM_KEYDOWNWM_SYSKEYDOWN 메시지에 대해 항상 0으로 설정됩니다. WM_KEYUPWM_SYSKEYUP 메시지에 대해서는 항상 1로 설정됩니다.

문자 메시지

키 입력 메시지는 키 입력에 대한 많은 정보를 제공하지만 문자 키 입력에 대한 문자 코드는 제공하지 않습니다. 문자 코드를 검색하려면 애플리케이션에서 TranslateMessage 함수를 스레드 메시지 루프에 포함해야 합니다. TranslateMessageWM_KEYDOWN 또는 WM_SYSKEYDOWN 메시지를 키보드 레이아웃에 전달합니다. 레이아웃은 메시지의 가상 키 코드를 검사하고, 문자 키에 해당하는 경우 Shift 및 Caps Lock 키의 상태를 고려하여 동등한 문자 코드를 제공합니다. 그런 다음, 문자 코드가 포함된 문자 메시지를 생성하고 메시지를 메시지 큐의 맨 위에 배치합니다. 메시지 루프의 다음 반복은 큐에서 문자 메시지를 제거하고 메시지를 적절한 창 프로시저로 디스패치합니다.

이 섹션에서는 다음 항목을 다룹니다.

비 시스템 문자 메시지

창 프로시저는 WM_CHAR, WM_DEADCHAR, WM_SYSCHAR, WM_SYSDEADCHARWM_UNICHAR 문자 메시지를 받을 수 있습니다. TranslateMessage 함수는 WM_KEYDOWN 메시지를 처리할 때 WM_CHAR 또는 WM_DEADCHAR 메시지를 생성합니다. 마찬가지로 WM_SYSKEYDOWN 메시지를 처리할 때 WM_SYSCHAR 또는 WM_SYSDEADCHAR 메시지를 생성합니다.

키보드 입력을 처리하는 애플리케이션은 일반적으로 WM_CHARWM_UNICHAR 메시지를 제외한 모든 메시지를 무시하고, 다른 메시지는 DefWindowProc 함수에 전달합니다. WM_CHAR는 UTF-16(16비트 유니코드 변환 형식) 또는 ANSI 문자 집합을 사용하고, WM_UNICHAR는 항상 UTF-32(32비트 유니코드 변환 형식)를 사용합니다. 시스템은 WM_SYSCHARWM_SYSDEADCHAR 메시지를 사용하여 메뉴 니모닉을 구현합니다.

모든 문자 메시지의 wParam 매개 변수에는 누른 문자 키의 문자 코드가 포함되어 있습니다. 문자 코드의 값은 메시지를 받는 창의 창 클래스에 따라 달라집니다. RegisterClass 함수의 유니코드 버전을 사용하여 창 클래스를 등록한 경우 시스템에서 유니코드 문자를 해당 클래스의 모든 창에 제공합니다. 그렇지 않은 경우 시스템에서 ANSI 문자 코드를 제공합니다. 자세한 내용은 창 클래스 등록Windows 앱에서 UTF-8 코드 페이지 사용을 참조하세요.

문자 메시지의 lParam 매개 변수 콘텐츠는 문자 메시지를 생성하기 위해 번역된 키 아래로 메시지의 lParam 매개 변수 콘텐츠와 동일합니다. 자세한 내용은 키 입력 메시지 플래그를 참조하세요.

배달 못한 문자 메시지

영어가 아닌 일부 키보드에는 자체적으로 문자를 생성하지 않을 것으로 예상되는 문자 키가 포함되어 있습니다. 대신 분음 부호를 후속 키 입력에서 생성된 문자에 추가하는 데 사용됩니다. 이러한 키를 배달 못한 키라고 합니다. 독일어 키보드의 곡절 부호 키는 배달 못한 키의 예입니다. 곡절 부호가 있는 "o"로 구성된 문자를 입력하려면 독일어 사용자가 곡절 부호 키와 "o" 키를 차례로 입력합니다. 키보드 포커스가 있는 창에서 받는 메시지 시퀀스는 다음과 같습니다.

  1. WM_KEYDOWN
  2. WM_DEADCHAR
  3. WM_KEYUP
  4. WM_KEYDOWN
  5. WM_CHAR
  6. WM_KEYUP

TranslateMessage는 배달 못한 키에서 WM_KEYDOWN 메시지를 처리할 때 WM_DEADCHAR 메시지를 생성합니다. WM_DEADCHAR 메시지의 wParam 매개 변수에 배달 못한 키에 대한 분음 부호의 문자 코드가 포함되어 있지만 이러한 메시지는 일반적으로 애플리케이션에서 무시합니다. 대신 후속 키 입력에서 생성된 WM_CHAR 메시지를 처리합니다. WM_CHAR 메시지의 wParam 매개 변수에는 분음 부호가 있는 문자의 문자 코드가 포함되어 있습니다. 후속 키 입력에서 분음 부호와 결합할 수 없는 문자를 생성하는 경우 시스템은 두 개의 WM_CHAR 메시지를 생성합니다. 첫 번째 메시지의 wParam 매개 변수에는 분음 부호의 문자 코드가 포함되고, 두 번째 메시지의 wParam 매개 변수에는 후속 문자 키의 문자 코드가 포함됩니다.

TranslateMessage 함수는 시스템 배달 못한 키(Alt 키와 함께 누르는 배달 못한 키)에서 WM_SYSKEYDOWN 메시지를 처리할 때 WM_SYSDEADCHAR 메시지를 생성합니다. WM_SYSDEADCHAR 메시지는 일반적으로 애플리케이션에서 무시합니다.

키 상태

키보드 메시지를 처리하는 동안 애플리케이션은 현재 메시지를 생성한 키 외에도 다른 키의 상태를 확인해야 할 수 있습니다. 예를 들어 사용자가 Shift+End를 눌러 텍스트 블록을 선택할 수 있는 워드 프로세싱 애플리케이션은 End 키에서 키 입력 메시지를 받을 때마다 Shift 키의 상태를 확인해야 합니다. 애플리케이션은 GetKeyState 함수를 사용하여 현재 메시지가 생성된 시점의 가상 키 상태를 확인할 수 있습니다. GetAsyncKeyState 함수를 사용하여 가상 키의 현재 상태를 검색할 수 있습니다.

키보드 레이아웃은 이름 목록을 유지 관리합니다. 단일 문자를 생성하는 키의 이름은 키에서 생성하는 문자와 동일합니다. Tab 및 Enter와 같은 비문자 키의 이름은 문자열로 저장됩니다. 애플리케이션은 GetKeyNameText 함수를 호출하여 디바이스 드라이버에서 키 이름을 검색할 수 있습니다.

키 입력 및 문자 번역

시스템에는 스캔 코드, 문자 코드 및 다양한 키 입력 메시지에서 제공하는 가상 키 코드를 번역하는 특수 용도의 몇 가지 기능이 포함되어 있습니다. 이러한 함수에는 MapVirtualKey, ToAscii, ToUnicodeVkKeyScan이 포함됩니다.

또한 Microsoft Rich Edit 3.0은 사용자가 바로 가기 키를 사용하여 16진수와 유니코드 문자 간에 변환할 수 있는 HexToUnicode IME를 지원하여 습니다. 즉, Microsoft Rich Edit 3.0이 애플리케이션에 통합되면 애플리케이션에서 HexToUnicode IME의 기능을 상속합니다.

바로 가기 키 지원

바로 가기 키WM_HOTKEY 메시지를 생성하는 키 조합입니다. 이는 시스템에서 스레드의 메시지 큐 맨 위에 배치하여 큐의 기존 메시지를 무시하는 메시지입니다. 애플리케이션은 바로 가기 키를 사용하여 사용자로부터 우선 순위가 높은 키보드 입력을 얻습니다. 예를 들어 Ctrl+C 키 조합으로 구성된 바로 가기 키를 정의하면 애플리케이션에서 사용자가 긴 작업을 취소할 수 있습니다.

바로 가기 키를 정의하기 위해 애플리케이션에서 RegisterHotKey 함수를 호출하여 WM_HOTKEY 메시지를 생성하는 키 조합, 메시지를 받을 창에 대한 핸들 및 바로 가기 키의 식별자를 지정합니다. 사용자가 바로 가기 키를 누르면 WM_HOTKEY 메시지가 창을 만든 스레드의 메시지 큐에 배치됩니다. 메시지의 wParam 매개 변수에는 바로 가기 키의 식별자가 포함되어 있습니다. 애플리케이션은 스레드에 대해 여러 바로 가기 키를 정의할 수 있지만 스레드의 각 바로 가기 키에는 고유 식별자가 있어야 합니다. 애플리케이션이 종료되기 전에 UnregisterHotKey 기능을 사용하여 바로 가기 키를 삭제해야 합니다.

사용자가 바로 가기 키를 쉽게 선택할 수 있도록 애플리케이션에서 바로 가기 키 컨트롤을 사용할 수 있습니다. 바로 가기 키 컨트롤은 일반적으로 창을 활성화하는 바로 가기 키를 정의하는 데 사용됩니다. RegisterHotKeyUnregisterHotKey 함수는 사용하지 않습니다. 대신 바로 가기 키 컨트롤을 사용하는 애플리케이션에서 일반적으로 WM_SETHOTKEY 메시지를 보내 바로 가기 키를 설정합니다. 사용자가 바로 가기 키를 누를 때마다 시스템에서 SC_HOTKEY를 지정하는 WM_SYSCOMMAND 메시지를 보냅니다. 바로 가기 키 컨트롤에 대한 자세한 내용은 바로 가기 키 컨트롤의 "바로 가기 키 컨트롤 사용"을 참조하세요.

검색 및 기타 기능에 대한 키보드 키

Windows는 검색 기능, 미디어 기능, 애플리케이션 시작 및 전원 관리에 대한 특수 키가 있는 키보드를 지원합니다. WM_APPCOMMAND는 추가 키보드 키를 지원합니다. 또한 추가 키보드 키를 지원하도록 ShellProc 함수가 수정되었습니다.

구성 요소 애플리케이션의 자식 창에서 이러한 추가 키보드 키에 대한 명령을 직접 구현할 가능성은 거의 없습니다. 따라서 이러한 키 중 하나를 누르면 DefWindowProc에서 WM_APPCOMMAND 메시지를 창에 보냅니다. DefWindowProcWM_APPCOMMAND 메시지를 부모 창에 버블링합니다. 이는 마우스 오른쪽 단추를 사용하여 상황에 맞는 메뉴가 호출되는 방식과 비슷합니다. 즉, DefWindowProc는 오른쪽 단추 클릭 시 WM_CONTEXTMENU 메시지를 보내고 이 메시지를 해당 부모 창에 버블링합니다. 또한 DefWindowProc에서 최상위 창에 대한 WM_APPCOMMAND 메시지를 받으면 HSHELL_APPCOMMAND 코드를 사용하여 셸 후크를 호출합니다.

Windows는 5개의 단추가 있는 마우스인 Microsoft IntelliMouse Explorer도 지원합니다. 두 개의 추가 단추는 앞으로 및 뒤로 브라우저 탐색을 지원합니다. 자세한 내용은 XBUTTON을 참조하세요.

입력 시뮬레이션

중단 없는 일련의 사용자 입력 이벤트를 시뮬레이션하려면 SendInput 함수를 사용합니다. 이 함수는 세 개의 매개 변수를 허용합니다. 첫 번째 매개 변수인 cInputs는 시뮬레이션할 입력 이벤트의 수를 나타냅니다. 두 번째 매개 변수인 rgInputsINPUT 구조체의 배열이며, 각 구조체는 입력 이벤트 유형과 해당 이벤트에 대한 추가 정보를 설명합니다. 마지막 매개 변수인 cbSizeINPUT 구조체의 크기(바이트)를 허용합니다.

SendInput 함수는 일련의 시뮬레이션된 입력 이벤트를 디바이스의 입력 스트림에 삽입하여 작동합니다. 효과는 keybd_event 또는 mouse_event 함수를 반복적으로 호출하는 것과 비슷합니다. 하지만 시스템에서 다른 입력 이벤트가 시뮬레이션된 이벤트와 섞이지 않도록 보장한다는 점이 다릅니다. 호출이 완료되면 반환 값은 성공적으로 재생된 입력 이벤트의 수를 나타냅니다. 이 값이 0이면 입력이 차단된 것입니다.

SendInput 함수는 키보드의 현재 상태를 다시 설정하지 않습니다. 따라서 이 함수를 호출할 때 사용자가 키를 누른 경우 이 함수에서 생성하는 이벤트를 방해할 수 있습니다. 간섭이 발생할 수 있는 경우 GetAsyncKeyState 함수를 사용하여 키보드의 상태를 확인하고 필요에 따라 수정합니다.

언어, 로캘 및 키보드 레이아웃

언어는 영어, 프랑스어, 일본어와 같은 자연어입니다. 하위 언어는 영국과 미국에서 사용되는 영어 하위 언어와 같이 특정 지역에서 사용되는 자연어의 변형입니다. 애플리케이션은 언어 식별자라는 값을 사용하여 언어와 하위 언어를 고유하게 식별합니다.

애플리케이션은 일반적으로 로캘을 사용하여 입력 및 출력이 처리되는 언어를 설정합니다. 예를 들어 키보드에 대한 로캘을 설정하면 키보드에서 생성되는 문자 값에 영향을 줍니다. 디스플레이 또는 프린터에 대한 로캘을 설정하면 표시되거나 인쇄되는 문자 모양에 영향을 줍니다. 애플리케이션은 키보드 레이아웃을 로드하고 사용하여 키보드의 로캘을 설정합니다. 지정된 로캘을 지원하는 글꼴을 선택하여 디스플레이 또는 프린터에 대한 로캘을 설정합니다.

키보드 레이아웃은 키보드에서 키의 실제 위치를 지정할 뿐만 아니라 해당 키를 눌러 생성되는 문자 값도 결정합니다. 각 레이아웃은 현재 입력 언어를 식별하고 키와 키의 특정 조합으로 생성되는 문자 값을 결정합니다.

모든 키보드 레이아웃에는 레이아웃과 언어를 식별하는 해당 핸들이 있습니다. 핸들의 하위 단어는 언어 식별자입니다. 상위 단어는 실제 레이아웃을 지정하는 디바이스 핸들이거나 기본 실제 레이아웃을 나타내는 0입니다. 사용자는 입력 언어를 실제 레이아웃과 연결할 수 있습니다. 예를 들어 매우 드물지만 프랑스어로 작업하는 영어 사용자는 키보드의 실제 레이아웃을 변경하지 않고 키보드의 입력 언어를 프랑스어로 설정할 수 있습니다. 즉, 사용자가 익숙한 영어 레이아웃을 사용하여 텍스트를 프랑스어로 입력할 수 있습니다.

애플리케이션은 일반적으로 입력 언어를 직접 조작할 필요가 없습니다. 대신 사용자가 언어와 레이아웃의 조합을 설정한 다음, 이러한 조합 중에서 전환합니다. 사용자가 다른 언어로 표시된 텍스트를 클릭하면 애플리케이션에서 ActivateKeyboardLayout 함수를 호출하여 해당 언어에 대한 사용자의 기본 레이아웃을 활성화합니다. 사용자가 텍스트를 활성 목록에 없는 언어로 편집하는 경우 언어에 따라 레이아웃을 가져오기 위해 애플리케이션에서 해당 언어를 사용하여 LoadKeyboardLayout 함수를 호출할 수 있습니다.

ActivateKeyboardLayout 함수는 현재 작업에 대한 입력 언어를 설정합니다. hkl 매개 변수는 키보드 레이아웃에 대한 핸들이거나 0 확장 언어 식별자일 수 있습니다. 키보드 레이아웃 핸들은 LoadKeyboardLayout 또는 GetKeyboardLayoutList 함수에서 가져올 수 있습니다. HKL_NEXTHKL_PREV 값을 사용하여 다음 또는 이전 키보드를 선택할 수도 있습니다.

GetKeyboardLayoutName 함수는 호출 스레드에 대한 활성 키보드 레이아웃의 이름을 검색합니다. 애플리케이션에서 LoadKeyboardLayout 함수를 사용하여 활성 레이아웃을 만드는 경우 GetKeyboardLayoutName은 레이아웃을 만드는 데 사용되는 동일한 문자열을 검색합니다. 그렇지 않은 경우 문자열은 활성 레이아웃의 로캘에 해당하는 기본 언어 식별자입니다. 즉, 함수에서 동일한 기본 언어를 사용하는 여러 레이아웃을 반드시 구분할 필요는 없으므로 입력 언어에 대한 특정 정보를 반환할 수 없습니다. 그러나 GetKeyboardLayout 함수는 입력 언어를 확인하는 데 사용할 수 있습니다.

LoadKeyboardLayout 함수는 키보드 레이아웃을 로드하고 사용자가 해당 레이아웃을 사용할 수 있도록 합니다. 애플리케이션에서 KLF_ACTIVATE 값을 사용하여 현재 스레드에 대한 레이아웃을 즉시 활성화할 수 있습니다. 애플리케이션은 KLF_ACTIVATE 값을 지정하지 않고도 KLF_REORDER 값을 사용하여 레이아웃의 순서를 변경할 수 있습니다. 애플리케이션에서 키보드 레이아웃을 로드할 때 항상 KLF_SUBSTITUTE_OK 값을 사용하여 사용자의 기본 설정(있는 경우)이 선택되었는지 확인해야 합니다.

다국어를 지원하기 위해 LoadKeyboardLayout 함수에서 KLF_REPLACELANGKLF_NOTELLSHELL 플래그를 제공합니다. KLF_REPLACELANG 플래그는 언어를 변경하지 않고 기존 키보드 레이아웃을 바꾸도록 함수에 지시합니다. 동일한 언어 식별자를 사용하지만 KLF_REPLACELANG을 지정하지 않고 기존 레이아웃을 바꾸려고 하면 오류가 발생합니다. KLF_NOTELLSHELL 플래그는 레이아웃을 추가하거나 바꿀 때 함수에서 셸에 알리지 않도록 방지합니다. 이는 일련의 연속 호출에서 여러 레이아웃을 추가하는 애플리케이션에 유용합니다. 이 플래그는 마지막 호출을 제외한 모든 호출에서 사용해야 합니다.

UnloadKeyboardLayout 함수는 시스템 기본 입력 언어를 언로드할 수 없다는 점에서 제한됩니다. 이렇게 하면 사용자가 항상 셸 및 파일 시스템에서 사용하는 것과 동일한 문자 집합을 사용하여 텍스트 입력에 사용할 수 있는 하나의 레이아웃을 갖습니다.