📄 keybdmdd.cpp
字号:
( pCharacterBuffer == NULL ) )
{
SetLastError(ERROR_INVALID_PARAMETER);
return ERROR_INVALID_PARAMETER;
}
// Update the virtual key state.
KeyState[VirtualKey] = NewKeyStateFlags(KeyState[VirtualKey], KeyEvent);
// Now check the duplicate keys.
VKeyCommon = MapLRVKeys(VirtualKey);
if ( VKeyCommon != VirtualKey )
{
KeyState[VKeyCommon] = NewKeyStateFlags(KeyState[VKeyCommon], KeyEvent);
VirtualKey = VKeyCommon;
}
// Figure out the new shift state flags.
KeybdDriverKeyStateToShiftFlags(KeyState, VirtualKey, &ShiftFlags);
// Always return the shift state which counts for one entry.
*pcCharacters = 1;
// Do multiple characters here if necessary
if ( KeyEvent & KeyStateDownFlag )
{
*pCharacterBuffer = VKeyToUnicode(VirtualKey, &ShiftFlags);
}
else
{
ShiftFlags |= KeyShiftNoCharacterFlag;
}
*pShiftStateBuffer = ShiftFlags;
return ERROR_SUCCESS;
}
#ifdef DEBUG
PFN_KEYBD_DRIVER_VKEY_TO_UNICODE v_pfnVKeyToUnicodeTest = KeybdDriverVKeyToUnicode;
#endif
extern "C"
// @doc EXTERNAL DRIVERS
/* @func
Sets information about the keyboard device.
@rdesc If the function succeeds the return value is TRUE, otherwise, it is
FALSE. Extended error information is available via the GetLastError
function.
@xref
<tab><f KeybdDriverGetIno><nl>
<tab><c KBDI_AUTOREPEAT_INFO_ID><nl>
--*/
BOOL KeybdDriverSetMode(
INT iKeybdId, // @parm Id of the keyboard to set the information.
INT iIndex, // @parm Id of info to set.
LPVOID lpInput // @parm Input buffer.
)
{
if ( lpInput == NULL )
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
switch ( iIndex )
{
case KBDI_AUTOREPEAT_INFO_ID:
{
struct KBDI_AUTOREPEAT_INFO *pInfo =
(struct KBDI_AUTOREPEAT_INFO*)lpInput;
if ( pInfo -> CurrentInitialDelay > AUTO_REPEAT_INITIAL_DELAY_MAX )
{
// RETAILMSG(1,
// (TEXT("Initial delay too large, using %d\r\n"),
// AUTO_REPEAT_INITIAL_DELAY_MAX));
v_AutoRepeatInitialDelay = AUTO_REPEAT_INITIAL_DELAY_MAX;
}
else if ( pInfo -> CurrentInitialDelay < AUTO_REPEAT_INITIAL_DELAY_MIN )
{
// RETAILMSG(1,
// (TEXT("Initial delay too small, using %d\r\n"),
// AUTO_REPEAT_INITIAL_DELAY_MIN));
v_AutoRepeatInitialDelay = AUTO_REPEAT_INITIAL_DELAY_MIN;
}
else
{
v_AutoRepeatInitialDelay = pInfo -> CurrentInitialDelay;
}
if ( pInfo -> CurrentRepeatRate > AUTO_REPEAT_KEYS_PER_SEC_MAX )
{
// RETAILMSG(1,
// (TEXT("Initial repeat rate too large, using %d\r\n"),
// AUTO_REPEAT_KEYS_PER_SEC_MAX));
v_AutoRepeatKeysPerSec = AUTO_REPEAT_KEYS_PER_SEC_MAX;
}
else if ( ( pInfo -> CurrentRepeatRate < AUTO_REPEAT_KEYS_PER_SEC_MIN ) &&
( pInfo -> CurrentRepeatRate != 0 ) )
{
// RETAILMSG(1,
// (TEXT("Initial repeat rate too small, using %d\r\n"),
// AUTO_REPEAT_KEYS_PER_SEC_MIN));
v_AutoRepeatKeysPerSec = AUTO_REPEAT_KEYS_PER_SEC_MIN;
}
else
{
v_AutoRepeatKeysPerSec = pInfo -> CurrentRepeatRate;
}
}
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return TRUE;
}
#ifdef DEBUG
PFN_KEYBD_DRIVER_SET_MODE v_pfnSetModeTest = KeybdDriverSetMode;
#endif
/*++
KeybdSendKeyDownToUser:
On a key down, do all of the mapping on the keyboard and send the
keys to the input system.
Notes:
The basic pattern for each special key is to see if we are already sending
a virtual key and auto-repeat it or check if its particular modifier is
down and send the modified key or just send the unmodified key.
For modified keys, we need to make it look like the modifier key went up
and then the desired virtual key went down. Additionally, when the
modifier is the Alt key, we need to send a null character before the Alt
up so that menus do not activate.
--*/
void
KeybdSendKeyDownToUser(
UINT32 VirtualKey,
KEY_STATE_FLAGS KeyStateFlags
)
{
UINT32 vkUp = 0;
UINT32 vkDown;
BOOL fSendNull = FALSE;
UINT32 vkOnly = VirtualKey & 0xff; // Just the vkey
UINT32 vkOther = VirtualKey & ~0xff; // Just the other stuff
if ( vkOnly == VK_OFF )
{
vkDown = VK_OFF | KEYBD_DEVICE_SILENT_REPEAT;
}
else if ( vkOnly == VK_LSHIFT )
{
if ( v_LShiftVKeySent ) // Key is auto-repeating.
{
vkDown = v_LShiftVKeySent; // Send out whatever we sent last time.
}
else if ( v_fRShiftDown ) // Modifier key is down.
{
vkUp = VK_RSHIFT; // Make the right shift go up.
vkDown = v_LShiftVKeySent = v_RShiftVKeySent = VK_CAPITAL | // Send VK_CAPITAL instead of VK_LSHIFT.
KEYBD_DEVICE_SILENT_REPEAT;
}
else
{
vkDown = v_LShiftVKeySent = VK_LSHIFT | KEYBD_DEVICE_SILENT_REPEAT; // No modifier, send VK_LSHIFT.
}
v_fLShiftDown = TRUE;
}
else if ( vkOnly == VK_RSHIFT ) // etc.
{
if ( v_RShiftVKeySent )
{
vkDown = v_RShiftVKeySent;
}
else if ( v_fLShiftDown )
{
vkUp = VK_LSHIFT;
vkDown = v_RShiftVKeySent = v_LShiftVKeySent = VK_CAPITAL |
KEYBD_DEVICE_SILENT_REPEAT;
}
else
{
vkDown = v_RShiftVKeySent = VK_RSHIFT | KEYBD_DEVICE_SILENT_REPEAT;
}
v_fRShiftDown = TRUE;
}
else if ( vkOnly == VK_BACK )
{
if ( v_BackVKeySent )
{
vkDown = v_BackVKeySent;
}
else if ( v_fLShiftDown )
{
vkUp = VK_LSHIFT;
vkDown = v_BackVKeySent = VK_DELETE;
}
else if ( v_fRShiftDown )
{
vkUp = VK_RSHIFT;
vkDown = v_BackVKeySent = VK_DELETE;
}
else
{
vkDown = v_BackVKeySent = VK_BACK;
}
}
else if ( vkOnly == VK_COMMA )
{
if ( v_CommaVKeySent )
{
vkDown = v_CommaVKeySent;
}
else if ( ANY_ALT_DOWN() && !ANY_CTRL_DOWN() && !ANY_SHIFT_DOWN() )
{
fSendNull = TRUE;
vkUp = VK_MENU;
vkDown = v_CommaVKeySent = KEYBD_DEVICE_CONTRAST_LESS;
}
else
{
vkDown = v_CommaVKeySent = VK_COMMA;
}
}
else if ( vkOnly == VK_PERIOD )
{
if ( v_PeriodVKeySent )
{
vkDown = v_PeriodVKeySent;
}
else if ( ANY_ALT_DOWN() && !ANY_CTRL_DOWN() && !ANY_SHIFT_DOWN() )
{
fSendNull = TRUE;
vkUp = VK_MENU;
vkDown = v_PeriodVKeySent = KEYBD_DEVICE_CONTRAST_MORE;
}
else
{
vkDown = v_PeriodVKeySent = VK_PERIOD;
}
}
else if ( vkOnly == VK_RIGHT )
{
if ( v_RightVKeySent )
{
vkDown = v_RightVKeySent;
}
else if ( ANY_ALT_DOWN() )
{
fSendNull = TRUE;
vkUp = VK_MENU;
vkDown = v_RightVKeySent = VK_END;
}
else
{
vkDown = v_RightVKeySent = VK_RIGHT;
}
}
else if ( vkOnly == VK_LEFT )
{
if ( v_LeftVKeySent )
{
vkDown = v_LeftVKeySent;
}
else if ( ANY_ALT_DOWN() )
{
fSendNull = TRUE;
vkUp = VK_MENU;
vkDown = v_LeftVKeySent = VK_HOME;
}
else
{
vkDown = v_LeftVKeySent = VK_LEFT;
}
}
else if ( vkOnly == VK_UP )
{
if ( v_UpVKeySent )
{
vkDown = v_UpVKeySent;
}
else if ( ANY_ALT_DOWN() )
{
fSendNull = TRUE;
vkUp = VK_MENU;
vkDown = v_UpVKeySent = VK_PRIOR;
}
else
{
vkDown = v_UpVKeySent = VK_UP;
}
}
else if ( vkOnly == VK_DOWN )
{
if ( v_DownVKeySent )
{
vkDown = v_DownVKeySent;
}
else if ( ANY_ALT_DOWN() )
{
fSendNull = TRUE;
vkUp = VK_MENU;
vkDown = v_DownVKeySent = VK_NEXT;
}
else
{
vkDown = v_DownVKeySent = VK_DOWN;
}
}
else if ( vkOnly == VK_LMENU )
{
vkDown = VK_LMENU | KEYBD_DEVICE_SILENT_REPEAT;
v_fLAltDown = TRUE;
v_fLPseudoAltDown = TRUE;
}
else if ( vkOnly == VK_RMENU )
{
vkDown = VK_RMENU | KEYBD_DEVICE_SILENT_REPEAT;
v_fRAltDown = TRUE;
v_fRPseudoAltDown = TRUE;
}
else if ( vkOnly == VK_LCONTROL )
{
vkDown = vkOnly | KEYBD_DEVICE_SILENT_REPEAT;
v_fLCtrlDown = TRUE;
}
else if ( vkOnly == VK_RCONTROL )
{
vkDown = vkOnly | KEYBD_DEVICE_SILENT_REPEAT;
v_fRCtrlDown = TRUE;
}
else if ( ( vkOnly == VK_LWIN ) ||
( vkOnly == VK_RWIN ) )
{
vkDown = vkOnly | KEYBD_DEVICE_SILENT_REPEAT;
}
else
{
vkDown = vkOnly;
}
// May need to send null character to keep menus from activating.
if ( fSendNull )
{
(*v_pfnKeybdEventCallback)(
KEYBD_DEVICE_SILENT | vkOther, // Virtual key == 0 down.
KeyStateDownFlag);
(*v_pfnKeybdEventCallback)(vkOther, 0); // Virtual key == 0 up.
}
// Make it look like the modifier(s) went up.
if ( vkUp )
{
if ( vkUp == VK_MENU )
{
if ( v_fLAltDown )
{
(*v_pfnKeybdEventCallback)(VK_LMENU | vkOther, 0);
v_fLPseudoAltDown = FALSE;
}
if ( v_fRAltDown )
{
(*v_pfnKeybdEventCallback)(VK_RMENU | vkOther, 0);
v_fRPseudoAltDown = FALSE;
}
}
else
{
(*v_pfnKeybdEventCallback)(vkUp | vkOther, 0);
}
}
v_fLastKeyDownWasPseudoAlt = FALSE;
// Finally! Send the key down.
(*v_pfnKeybdEventCallback)(vkDown|vkOther, KeyStateFlags);
return;
}
/*++
KeybdSendKeyUpToUser:
On a key up, undo all of the mapping on the keyboard and send the
keys to the input system.
Notes:
When a special key is released, we send an up event for whatever virtual
key was original sent as going down.
If the special key's modifier key is still down, we send a down event for
it to keep the state consistent. (We earlier sent an up event for the modifier
when the special key went down.).
We remember if the modifier key we are resending the down for is the Alt
key. If it is, when it is really released, we send a null through the
system to keep menus from activating. Otherwise, menus would see this
down followed directly by an Alt up and so would activate.
--*/
void
KeybdSendKeyUpToUser(
UINT32 VirtualKey,
KEY_STATE_FLAGS KeyStateFlags
)
{
UINT32 vkUp;
UINT32 vkDown = 0;
BOOL fSendUp = TRUE;
BOOL fSendNull = FALSE;
UINT32 vkOnly = VirtualKey & 0xff; // Just the vkey
UINT32 vkOther = VirtualKey & ~0xff; // Just the other stuff
// The key up we send is usually this.
vkUp = vkOnly;
if ( vkOnly == VK_LSHIFT )
{
vkUp = v_LShiftVKeySent; // Whatever we sent out is what goes up.
v_LShiftVKeySent = 0;
v_fLShiftDown = FALSE;
if ( v_fRShiftDown ) // Modifier key is still down.
{
vkDown = v_RShiftVKeySent = VK_RSHIFT;
}
}
else if ( vkOnly == VK_RSHIFT ) // etc.
{
vkUp = v_RShiftVKeySent; // Whatever we sent out is what goes up.
v_RShiftVKeySent = 0;
v_fRShiftDown = FALSE;
if ( v_fLShiftDown )
{
vkDown = v_LShiftVKeySent = VK_LSHIFT;
}
}
else if ( vkOnly == VK_BACK )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -