📄 vktochar.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
@doc EXTERNAL DRIVERS
@module vkremap.cpp |
This file implements the character generation part of the platform
independent code of the keyboard driver. This is provided as a sample to
platform driver writers. Note that most of the tables are UINT8 in order to
save space. Returning Unicode characters > 255 will require UINT16 tables.
*/
#include <windows.h>
#include <memory.h>
#include <nkintr.h>
#include <keybddr.h>
#include <keybdpdd.h>
#define C_VIRTUAL_KEYS 256
// Languages besides English may return more than one character.
// It is usually a dead char and another character.
#define MAX_TO_UNICODE_CHARACTERS 2
#define VK_0 0x30
#define VK_9 0x39
#define VK_A 0x41
#define VK_F 0x46
#define VK_X 0x58
// @doc EXTERNAL DRIVERS
/* @struct TO_UNICODE_STATE |
State info needed by the driver to convert virtual keys to Unicode.
@xref
<tab><f KeybdDriverGetDeviceInfo><nl>
<tab><f KeybdDriverInitStates><nl>
<tab><f KeybdDriverVKeyToUnicode><nl>
@comm This struct would be used by the driver to maintain any state
information needed between key events in order to generate Unicode
characters from virtual keys.
@comm This structure is not visible outside of the driver. The driver
provides information on its size via the <f KeybdDriverGetDeviceInfo>
function. The input system allocates a buffer for the structure and
passes it in when it calls <f KeybdDriverVKeyToUnicode>.
@comm In the sample driver code, it is used to convert Alt+Num keys to a
unicode character.
*/
#define C_ALT_NUM_VK 5
struct TO_UNICODE_STATE
{
BOOL bAltNumAltDownTransition;
BOOL bAltNumInProgress;
BOOL bAltNumHex;
int cAltNumVk;
unsigned int vkAltNum[C_ALT_NUM_VK];
};
void
VKeyToUnicodeInfo(
KBDI_VKEY_TO_UNICODE_INFO *pInfo
)
{
pInfo -> cbToUnicodeState = sizeof(TO_UNICODE_STATE);
pInfo -> cMaxToUnicodeCharacters = MAX_TO_UNICODE_CHARACTERS;
return;
}
BOOL
AltNumOkToStart(
KEY_STATE_FLAGS ShiftFlags
)
{
if ( ShiftFlags & ( KeyShiftAnyCtrlFlag |
KeyShiftLeftWinFlag |
KeyShiftRightWinFlag |
KeyShiftAnyShiftFlag ) )
return FALSE;
return TRUE;
}
BOOL
AltNumKeyEvent(
UINT32 VirtualKey,
KEY_STATE_FLAGS KeyEvent,
TO_UNICODE_STATE *pToUnicodeState,
KEY_STATE_FLAGS *pShiftFlags,
UINT32 *pCharacterBuffer
)
{
KEY_STATE_FLAGS ShiftFlags = *pShiftFlags;
BOOL bGeneratedCharacter = FALSE;
UINT32 chGenerated;
unsigned int uiBase;
int i;
UINT32 vk;
if ( VirtualKey == VK_MENU )
{
if ( KeyEvent & KeyStateDownFlag )
{
// Down transition with no other keys?
if ( !( KeyEvent & KeyStatePrevDownFlag ) &&
( AltNumOkToStart(ShiftFlags) ) )
{
// Now armed to looked for number keys.
pToUnicodeState -> bAltNumAltDownTransition = TRUE;
pToUnicodeState -> bAltNumInProgress = FALSE;
pToUnicodeState -> bAltNumHex = FALSE;
pToUnicodeState -> cAltNumVk = 0;
}
}
else // Alt key up
{
pToUnicodeState -> bAltNumAltDownTransition = FALSE;
if ( pToUnicodeState -> bAltNumInProgress )
{
pToUnicodeState -> bAltNumInProgress = FALSE;
if ( pToUnicodeState -> cAltNumVk > 1 )
{
chGenerated = 0;
if ( pToUnicodeState -> bAltNumHex )
{
uiBase = 16;
}
else
{
uiBase = 10;
}
for ( i = 0;
i < pToUnicodeState -> cAltNumVk;
i++ )
{
vk = pToUnicodeState -> vkAltNum[i];
if ( ( vk >= VK_0 ) && ( vk <= VK_9 ) )
{
vk -= VK_0;
}
else if ( pToUnicodeState -> bAltNumHex &&
( ( vk >= VK_A ) && ( vk <= VK_F ) ) )
{
vk -= VK_A;
vk += 10;
}
else
{
break; // bad character
}
chGenerated *= uiBase;
chGenerated += vk;
}
bGeneratedCharacter = TRUE;
*pCharacterBuffer = chGenerated;
}
else
{
// Alt+N app startup here.
}
}
}
}
else if ( ( pToUnicodeState -> bAltNumAltDownTransition ) &&
( KeyEvent & KeyStateDownFlag ) )
{
if ( ( VirtualKey >= VK_0 ) && ( VirtualKey <= VK_9 ) )
{
// We were armed to look for number keys and we found one, so now we
// are actually in progress.
pToUnicodeState -> bAltNumInProgress = TRUE;
if ( pToUnicodeState -> cAltNumVk < C_ALT_NUM_VK )
{
pToUnicodeState -> vkAltNum[pToUnicodeState -> cAltNumVk++] = VirtualKey;
}
}
else if ( ( pToUnicodeState -> bAltNumHex ) &&
( ( VirtualKey >= VK_A ) && ( VirtualKey <= VK_F ) ) )
{
// Hex characters are split out separately for convenience in case the design changes.
pToUnicodeState -> bAltNumInProgress = TRUE;
if ( pToUnicodeState -> cAltNumVk < C_ALT_NUM_VK )
{
pToUnicodeState -> vkAltNum[pToUnicodeState -> cAltNumVk++] = VirtualKey;
}
}
else if ( ( pToUnicodeState -> bAltNumInProgress ) &&
( VirtualKey == VK_X ) )
{
pToUnicodeState -> bAltNumHex = TRUE;
}
else if ( pToUnicodeState -> bAltNumInProgress )
{
// If we are in progress, ignore unknown keys.
}
else
{
// If we see a key we can't handle when not in progress, disarm
pToUnicodeState -> bAltNumAltDownTransition = FALSE;
}
}
if ( pToUnicodeState -> bAltNumInProgress )
{
ShiftFlags |= KeyShiftUseVKNullFlag | KeyShiftNoCharacterFlag;
}
*pShiftFlags = ShiftFlags;
return pToUnicodeState -> bAltNumInProgress || bGeneratedCharacter;
}
extern "C"
// @doc EXTERNAL DRIVERS
/* @func
Initializes the virtual key state and driver specific state.
@xref
<tab><t KEY_STATE><nl>
<tab><t TO_UNICODE_STATE><nl>
<tab><f KeybdDriverGetInfo><nl>
<tab><c KBDI_VKEY_TO_UNICODE_INFO_ID><nl>
<tab><t KBDI_VKEY_TO_UNICODE_INFO><nl>
@comm After calling <f KeybdDriverGetInfo> and allocating its required
memory, the input system calls this function to allow the driver to
initialize the memory.
@comm The pKeybdDriverToUnicodeState is a pointer to a piece of memory of
at least cbToUnicodeState bytes as reported by the <f KeybdDriverGetInfo>
function in the <t KBDI_VKEY_TO_UNICODE_INFO> structure. If
cbToUnicodeState was reported as 0, this parameter may be NULL.
@comm This function must be re-entrant since it is exposed by the input
system via the <f KeybdInitStates> function and may be called by multiple
threads.
*/
BOOL KeybdDriverInitStates(
INT iKeybdId, // @parm Id of the keyboard to initialize keystate data for.
KEY_STATE KeyState, // @parm Key state to initialize.
void *pKeybdDeviceToUnicodeState // @parm Keyboard specific state to initialize.
)
{
TO_UNICODE_STATE *pDemoState = (TO_UNICODE_STATE*)pKeybdDeviceToUnicodeState;
int i;
// We have some state, so check for it.
if ( pDemoState == NULL )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
for ( i = 0; i < COUNT_VKEYS; i++ )
{
KeyState[i] = 0;
}
return TRUE;
}
#ifdef DEBUG
PFN_KEYBD_DRIVER_INIT_STATES v_pfnInitStatesTest = KeybdDriverInitStates;
#endif
/*++
MapLRVKeys:
Map left and right virtual keys to their common vkey.
Return Value:
The common vkey.
--*/
UINT32
MapLRVKeys(
UINT32 vkey
)
{
if ( ( vkey == VK_LCONTROL ) ||
( vkey == VK_RCONTROL ) )
return VK_CONTROL;
if ( ( vkey == VK_LMENU ) ||
( vkey == VK_RMENU ) )
return VK_MENU;
if ( ( vkey == VK_LSHIFT ) ||
( vkey == VK_RSHIFT ) )
return VK_SHIFT;
// VK_LWIN and VK_RWIN do not have a merged key.
return vkey;
}
/*++
NewKeyStateFlags:
Figure out the new key state flags based on the current state and the
event.
Return Value:
The new flag settings.
--*/
UINT32
NewKeyStateFlags(
KEY_STATE_FLAGS CurrentState,
KEY_STATE_FLAGS KeyEventFlags
)
{
// Just interested in down/up flag.
KeyEventFlags &= KeyStateDownFlag;
// First update the key state for the specific key.
// Remember the previous state.
if ( KeyStateIsDown(CurrentState) )
CurrentState |= KeyStatePrevDownFlag;
else
CurrentState &= ~KeyStatePrevDownFlag;
// Set the new state.
if ( KeyEventFlags )
CurrentState |= KeyStateDownFlag | KeyStateGetAsyncDownFlag;
else
CurrentState &= ~KeyStateDownFlag;
// Toggle flag only changes on down transition, not auto repeat.
if ( KeyStateIsDownTransition(CurrentState) )
CurrentState ^= KeyStateToggledFlag;
return CurrentState;
}
/*++
KeybdDriverKeyStateToShiftFlags:
Collapse the shift state from a given key state array into a single
element.
Notes:
For the given virtual key, the current flags from the key state array are
put into the low bits of the output flags.
--*/
void
KeybdDriverKeyStateToShiftFlags(
KEY_STATE KeyState, // Key state array.
UINT32 VKey, // Virtual key.
KEY_STATE_FLAGS *pShiftStateFlags // Location to put collapsed shift state.
)
{
KEY_STATE_FLAGS ShiftFlags = 0;
// Add the standard keys.
if ( KeyStateIsDown(KeyState[VK_CONTROL]) )
{
ShiftFlags |= KeyShiftAnyCtrlFlag;
}
if ( KeyStateIsDown(KeyState[VK_LCONTROL]) )
{
ShiftFlags |= KeyShiftLeftCtrlFlag;
}
if ( KeyStateIsDown(KeyState[VK_RCONTROL]) )
{
ShiftFlags |= KeyShiftRightCtrlFlag;
}
if ( KeyStateIsDown(KeyState[VK_SHIFT]) )
{
ShiftFlags |= KeyShiftAnyShiftFlag;
}
if ( KeyStateIsDown(KeyState[VK_LSHIFT]) )
{
ShiftFlags |= KeyShiftLeftShiftFlag;
}
if ( KeyStateIsDown(KeyState[VK_RSHIFT]) )
{
ShiftFlags |= KeyShiftRightShiftFlag;
}
if ( KeyStateIsDown(KeyState[VK_MENU]) )
{
ShiftFlags |= KeyShiftAnyAltFlag;
}
if ( KeyStateIsDown(KeyState[VK_LMENU]) )
{
ShiftFlags |= KeyShiftLeftAltFlag;
}
if ( KeyStateIsDown(KeyState[VK_RMENU]) )
{
ShiftFlags |= KeyShiftRightAltFlag;
}
if ( KeyStateIsDown(KeyState[VK_LWIN]) )
{
ShiftFlags |= KeyShiftLeftWinFlag;
}
if ( KeyStateIsDown(KeyState[VK_RWIN]) )
{
ShiftFlags |= KeyShiftRightWinFlag;
}
if ( KeyStateIsToggled(KeyState[VK_CAPITAL]) )
ShiftFlags |= KeyShiftCapitalFlag;
// Set the low order bits to reflect the current key.
*pShiftStateFlags = ShiftFlags | KeyState[VKey];
return;
}
/*
The following defines will be used for converting the key pressed
into a Unicode character using the context information (the state
of other keys). We are assuming here that the count of bytes required
for state info for Unicode character generation (cbToUnicodeState
field in KEYBD_DRIVER_INFO structure) is zero, ie the driver does
not maintain any state information (besides CAPS, SHIFT, ALT and
CONTROL state) for Unicode character generation.
The Unicode character generated depends on the key pressed and
the state of the following keys: CAPS, SHIFT, ALT and CONTROL. Hence
for every Virtual key generated by the PDD, there can be a total of
16 different Unicode Characters in the worst case. Since there are
a total of 256 different virtual keys possible, storing all possible
states would require a lot of memory. Hence rows which are together
have been grouped and columns which have the same corresponding values
in every row of the group have been merged together to minimise storage.
*/
#define NO_CHAR 255
#define FIRST_COLUMN 0
#define SECOND_COLUMN 1
#define THIRD_COLUMN 2
#define FOURTH_COLUMN 3
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -