📄 kbdhid.cpp
字号:
DEBUGCHK((uiVk != 0) || (uiSc != 0));
DEBUGMSG(ZONE_USAGES, (_T("%s: Keybd event: vk: 0x%02x sc: 0x%02x flags: 0x%08x\r\n"),
pszFname, uiVk, uiSc, dwFlags));
RETAILMSG(1, (TEXT("KeyboardEvent: vk: 0x%08x sc: 0x%08x flags: 0x%08x\r\n\r\n"), uiVk, uiSc, dwFlags));
keybd_event(uiVk, uiSc, dwFlags, 0);
}
// Search for usage in the g_rgUsageToScInfo tables.
static
const USAGE_TO_SCANCODE *
FindUsageToSc(
USAGE usage
)
{
const USAGE_TO_SC_INFO *pUsageToScInfo;
const USAGE_TO_SCANCODE *pUsageToSc = NULL;
DWORD cUsageToScInfo = dim(g_rgUsageToScInfo);
DWORD dwNormalizedUsage;
DWORD dwIdx;
ValidateAllUsageToSc();
for (dwIdx = 0; dwIdx < cUsageToScInfo; ++dwIdx)
{
pUsageToScInfo = &g_rgUsageToScInfo[dwIdx];
ValidateUsageToSc(pUsageToScInfo);
if ( (usage >= pUsageToScInfo->uFirstUsage) &&
(usage <= pUsageToScInfo->uLastUsage) )
{
dwNormalizedUsage = usage - pUsageToScInfo->uFirstUsage;
DEBUGCHK(dwNormalizedUsage <= pUsageToScInfo->uLastUsage);
pUsageToSc = &pUsageToScInfo->pUsageToSc[dwNormalizedUsage];
break;
}
}
return pUsageToSc;
}
// Standard key processing.
static
void
ProcessStandard(
UINT uiVk,
UINT uiSc,
DWORD dwFlags,
HIDP_KEYBOARD_DIRECTION hidpKeyEvent,
KEY_STATE_FLAGS *pKeyStateFlags
)
{
KeyboardEvent(uiVk, uiSc, dwFlags);
}
// Updates the given key state with the given virtual key modifier.
// Only processes L/R Ctrl, Shift and Alt. The toggled key state is
// set through IOCTL calls from the Layout Manager.
static
void
UpdateKeyState(
KEY_STATE_FLAGS *pKeyStateFlags,
UINT8 vk,
HIDP_KEYBOARD_DIRECTION hidpKeyEvent
)
{
struct VKeyToShiftState {
UINT8 vk; // Virtual key
KEY_STATE_FLAGS ksf; // Corresponding shift state flag
};
static const VKeyToShiftState rgVKeyDownToShiftState[] = {
{ VK_LSHIFT, KeyShiftLeftShiftFlag },
{ VK_RSHIFT, KeyShiftRightShiftFlag },
{ VK_LCONTROL, KeyShiftLeftCtrlFlag },
{ VK_RCONTROL, KeyShiftRightCtrlFlag },
{ VK_LMENU, KeyShiftLeftAltFlag },
{ VK_RMENU, KeyShiftRightAltFlag },
};
DWORD dwIdx;
const VKeyToShiftState *pvkshiftCurr;
DEBUGCHK(pKeyStateFlags != NULL);
DEBUGCHK(vk != 0);
for (dwIdx = 0; dwIdx < dim(rgVKeyDownToShiftState); ++dwIdx) {
pvkshiftCurr = &rgVKeyDownToShiftState[dwIdx];
if (pvkshiftCurr->vk == vk) {
if (hidpKeyEvent == HidP_Keyboard_Make) {
*pKeyStateFlags |= pvkshiftCurr->ksf;
}
else {
*pKeyStateFlags &= ~pvkshiftCurr->ksf;
}
break;
}
}
}
// Modifier key processing.
static
void
ProcessModifier(
UINT uiVk,
UINT uiSc,
DWORD dwFlags,
HIDP_KEYBOARD_DIRECTION hidpKeyEvent,
KEY_STATE_FLAGS *pKeyStateFlags
)
{
UpdateKeyState(pKeyStateFlags, (UINT8) uiVk, hidpKeyEvent);
KeyboardEvent(uiVk, uiSc, dwFlags);
}
// NumPad key processing.
static
void
ProcessNumPad(
UINT uiVk,
UINT uiSc,
DWORD dwFlags,
HIDP_KEYBOARD_DIRECTION hidpKeyEvent,
KEY_STATE_FLAGS *pKeyStateFlags
)
{
static const UINT8 rgVkNumLockOff[] = {
VK_INSERT, // VK_NUMPAD0 0x60
VK_END, // VK_NUMPAD1 0x61
VK_DOWN, // VK_NUMPAD2 0x62
VK_NEXT, // VK_NUMPAD3 0x63
VK_LEFT, // VK_NUMPAD4 0x64
VK_CLEAR, // VK_NUMPAD5 0x65
VK_RIGHT, // VK_NUMPAD6 0x66
VK_HOME, // VK_NUMPAD7 0x67
VK_UP, // VK_NUMPAD8 0x68
VK_PRIOR, // VK_NUMPAD9 0x69
VK_MULTIPLY, // VK_MULTIPLY 0x6A
VK_ADD, // VK_ADD 0x6B
VK_SEPARATOR, // VK_SEPARATOR 0x6C
VK_SUBTRACT, // VK_SUBTRACT 0x6D
VK_DELETE // VK_DECIMAL 0x6E
};
DWORD dwNormalizedIdx;
DEBUGCHK(pKeyStateFlags != NULL);
DEBUGCHK(uiVk >= VK_NUMPAD0);
DEBUGCHK(uiVk < VK_NUMPAD0 + dim(rgVkNumLockOff));
RETAILMSG(1,(TEXT("ProcNumPad: KeyStateFlags: %08x, uiSc: %08x, uiVk: %08x.\r\n"), *pKeyStateFlags, uiSc, uiVk ));
if (IS_NUMLOCK_ENABLED() == FALSE)
{
dwNormalizedIdx = uiVk - VK_NUMPAD0;
DEBUGCHK(dwNormalizedIdx < dim(rgVkNumLockOff));
uiVk = rgVkNumLockOff[dwNormalizedIdx];
}
KeyboardEvent(uiVk, uiSc, dwFlags);
}
// Special key processing that does not fit into any other category.
static
void
ProcessSpecial(
UINT uiVk,
UINT uiSc,
DWORD dwFlags,
HIDP_KEYBOARD_DIRECTION hidpKeyEvent,
KEY_STATE_FLAGS *pKeyStateFlags
)
{
UINT uiScOld = uiSc;
DEBUGCHK(pKeyStateFlags != NULL);
if (uiSc == SC_PRTSCRN) {
if (ANY_ALT_DOWN()) {
uiSc = 0x84;
}
}
else if (uiSc == SC_PAUSE) {
if (ANY_CTRL_DOWN()) {
uiSc = 0xE07E;
}
}
// If the scan code changed, update the virtual key and extended flag.
if (uiSc != uiScOld)
{
uiVk = MapVirtualKey(uiSc, MAP_SC_TO_VK);
if ((uiSc & 0xFFFF00) == 0xE000) {
dwFlags |= KEYEVENTF_EXTENDEDKEY;
}
else {
dwFlags &= ~KEYEVENTF_EXTENDEDKEY;
}
}
KeyboardEvent(uiVk, uiSc, dwFlags);
}
// Remap the Japanese keydowns.
static
UINT8
RemapJpnKeyDown(
UINT8 vkOnly,
KEY_STATE_FLAGS *pKeyStateFlags
)
{
UINT8 vkDown = vkOnly;
if ( vkOnly == VK_DBE_SBCSCHAR )
{
if ( v_vkFullHalfSent )
{
vkDown = v_vkFullHalfSent;
}
else if ( ANY_ALT_DOWN() && !ANY_CTRL_DOWN() && !ANY_SHIFT_DOWN() )
{
vkDown = v_vkFullHalfSent = VK_KANJI;
}
else
{
// Don't use imm function if not configured.
// The remapping won't work correctly but at least there won't be link errors.
DWORD fdwConversion;
DWORD fdwSentence;
if ( ImmGetConversionStatus(NULL, &fdwConversion, &fdwSentence) )
{
if ( fdwConversion & IME_CMODE_FULLSHAPE )
{
vkDown = v_vkFullHalfSent = VK_DBE_SBCSCHAR;
}
else
{
vkDown = v_vkFullHalfSent = VK_DBE_DBCSCHAR;
}
}
else
{
vkDown = v_vkFullHalfSent = VK_DBE_SBCSCHAR;
}
}
}
else if ( vkOnly == VK_DBE_ALPHANUMERIC )
{
if ( v_vkAlphaNumSent )
{
vkDown = v_vkAlphaNumSent;
}
else if ( !ANY_ALT_DOWN() && !ANY_CTRL_DOWN() && !ANY_SHIFT_DOWN() )
{
vkDown = v_vkAlphaNumSent = VK_DBE_ALPHANUMERIC;
}
else
{
vkDown = v_vkAlphaNumSent = VK_CAPITAL;
}
}
else if ( vkOnly == VK_DBE_HIRAGANA )
{
if ( v_vkHiraKataSent )
{
vkDown = v_vkHiraKataSent;
}
else if ( !ANY_ALT_DOWN() && !ANY_CTRL_DOWN() && ANY_SHIFT_DOWN() )
{
vkDown = v_vkHiraKataSent = VK_DBE_KATAKANA;
}
else if ( !ANY_ALT_DOWN() && ANY_CTRL_DOWN() && ANY_SHIFT_DOWN() )
{
vkDown = v_vkHiraKataSent = VK_KANA;
}
else if ( ANY_ALT_DOWN() && !ANY_CTRL_DOWN() && !ANY_SHIFT_DOWN() )
{
DWORD fdwConversion;
DWORD fdwSentence;
if ( ImmGetConversionStatus(NULL, &fdwConversion, &fdwSentence) )
{
if ( fdwConversion & IME_CMODE_ROMAN )
{
vkDown = v_vkHiraKataSent = VK_DBE_NOROMAN;
}
else
{
vkDown = v_vkHiraKataSent = VK_DBE_ROMAN;
}
}
else
{
vkDown = v_vkHiraKataSent = VK_DBE_NOROMAN;
}
}
else {
v_vkHiraKataSent = vkOnly;
}
}
return vkDown;
}
// Remap the Japanese keyup.
static
UINT8
RemapJpnKeyUp(
UINT8 vkOnly,
KEY_STATE_FLAGS *pKeyStateFlags
)
{
UINT8 vkUp = vkOnly;
if ( vkOnly == VK_DBE_SBCSCHAR )
{
vkUp = v_vkFullHalfSent;
v_vkFullHalfSent = 0;
}
else if ( vkOnly == VK_DBE_ALPHANUMERIC )
{
vkUp = v_vkAlphaNumSent;
v_vkAlphaNumSent = 0;
}
else if ( vkOnly == VK_DBE_HIRAGANA )
{
vkUp = v_vkHiraKataSent;
v_vkHiraKataSent = 0;
}
return vkUp;
}
// Japanese key processing.
static
void
ProcessJpn(
UINT uiVk,
UINT uiSc,
DWORD dwFlags,
HIDP_KEYBOARD_DIRECTION hidpKeyEvent,
KEY_STATE_FLAGS *pKeyStateFlags
)
{
DEBUGCHK(pKeyStateFlags != NULL);
if (hidpKeyEvent == HidP_Keyboard_Make) {
uiVk = RemapJpnKeyDown(uiVk, pKeyStateFlags);
}
else {
uiVk = RemapJpnKeyUp(uiVk, pKeyStateFlags);
}
KeyboardEvent(uiVk, uiSc, dwFlags);
}
// Do not send a key up for this key.
static
void
ProcessNoBreak(
UINT uiVk,
UINT uiSc,
DWORD dwFlags,
HIDP_KEYBOARD_DIRECTION hidpKeyEvent,
KEY_STATE_FLAGS *pKeyStateFlags
)
{
DEBUGCHK(pKeyStateFlags != NULL);
if (hidpKeyEvent == HidP_Keyboard_Make) {
KeyboardEvent(uiVk, uiSc, dwFlags);
}
}
#ifdef DEBUG
// Validate a PHID_KBD structure
void
ValidateHidKbd(
PHID_KBD pHidKbd
)
{
DWORD cbUsageList;
DEBUGCHK(pHidKbd != NULL);
DEBUGCHK(pHidKbd->dwSig == HID_KBD_SIG);
DEBUGCHK(pHidKbd->hDevice != NULL);
DEBUGCHK(pHidKbd->pHidFuncs != NULL);
DEBUGCHK(pHidKbd->phidpPreparsedData != NULL);
DEBUGCHK(pHidKbd->hidpCaps.UsagePage == HID_USAGE_PAGE_GENERIC);
DEBUGCHK(pHidKbd->hidpCaps.Usage == HID_USAGE_GENERIC_KEYBOARD);
DEBUGCHK(pHidKbd->pbOutputBuffer != NULL);
if (pHidKbd->fhThreadInited == TRUE) {
DEBUGCHK(pHidKbd->hThread != NULL);
}
DEBUGCHK(pHidKbd->ARState <= AR_AUTOREPEATING);
if (pHidKbd->fhOSDeviceInited == TRUE) {
DEBUGCHK(pHidKbd->hOSDevice != NULL);
}
DEBUGCHK(pHidKbd->hevClosing != NULL);
cbUsageList = pHidKbd->dwMaxUsages * sizeof(USAGE_AND_PAGE);
DEBUGCHK(pHidKbd->puapPrevUsages != NULL);
DEBUGCHK(LocalSize(pHidKbd->puapPrevUsages) == cbUsageList * 5);
DEBUGCHK((DWORD) pHidKbd->puapCurrUsages == ((DWORD) pHidKbd->puapPrevUsages) + cbUsageList);
DEBUGCHK((DWORD) pHidKbd->puapBreakUsages == ((DWORD) pHidKbd->puapCurrUsages) + cbUsageList);
DEBUGCHK((DWORD) pHidKbd->puapMakeUsages == ((DWORD) pHidKbd->puapBreakUsages) + cbUsageList);
DEBUGCHK((DWORD) pHidKbd->puapOldMakeUsages == ((DWORD) pHidKbd->puapMakeUsages) + cbUsageList);
}
// Validate the given USAGE_TO_SC_INFO structure.
static
void
ValidateUsageToSc(
const USAGE_TO_SC_INFO *pUsageToScInfo
)
{
DEBUGCHK(pUsageToScInfo->pUsageToSc != NULL);
DEBUGCHK(pUsageToScInfo->uFirstUsage <= pUsageToScInfo->uLastUsage);
}
// Validate the list of USAGE_TO_SC_INFO structures.
static
void
ValidateAllUsageToSc(
)
{
const USAGE_TO_SC_INFO *pUsageToScInfo;
DWORD cUsageToScInfo = dim(g_rgUsageToScInfo);
DWORD dwOuter, dwInner;
// Check the definitions of EB and EP
DEBUGCHK(SET_EB(EB_COUNT) <= SET_PT(1));
for (dwOuter = 0; dwOuter < cUsageToScInfo; ++dwOuter)
{
pUsageToScInfo = &g_rgUsageToScInfo[dwOuter];
ValidateUsageToSc(pUsageToScInfo);
// Verify that this range does not overlap with any of the later ones
USHORT uFirstUsage = pUsageToScInfo->uFirstUsage;
USHORT uLastUsage = pUsageToScInfo->uLastUsage;
for (dwInner = dwOuter + 1; dwInner < cUsageToScInfo; ++dwInner) {
DEBUGCHK( (uFirstUsage < g_rgUsageToScInfo[dwInner].uFirstUsage) ||
(uLastUsage > g_rgUsageToScInfo[dwInner].uLastUsage) );
}
// Now make sure that each USAGE_TO_SCANCODE is valid
for (dwInner = 0; dwInner < (USHORT)(uLastUsage - uFirstUsage + 1); ++dwInner)
{
const USAGE_TO_SCANCODE *pUsageToSc = pUsageToScInfo->pUsageToSc;
DEBUGCHK(GET_EB(pUsageToSc->uiFlags) < EB_COUNT);
DEBUGCHK(GET_PT(pUsageToSc->uiFlags) < PT_COUNT);
}
}
}
#endif // DEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -