📄 laymgr.cpp
字号:
}
else if ( ( bAltNumInProgress ) &&
( VirtualKey == VK_X ) )
{
bAltNumHex = TRUE;
}
else if ( bAltNumInProgress )
{
// If we are in progress, ignore unknown keys.
}
else
{
// If we see a key we can't handle when not in progress, disarm
bAltNumAltDownTransition = FALSE;
}
}
if ( bAltNumInProgress )
{
ShiftFlags |= KeyShiftNoCharacterFlag;
}
*pShiftFlags = ShiftFlags;
return bAltNumInProgress || bGeneratedCharacter;
}
//----------------------------------------------------------------------------
//
// KeybdDriverVKeyToUnicode
//
// Convert a virtual key to unicode. Also set the shift state and keyboard
// LEDs.
//
// Return Value:
//
// Windows success code.
//
//----------------------------------------------------------------------------
UINT32
KeybdDriverVKeyToUnicode(
UINT32 VirtualKey,
KEY_STATE_FLAGS KeyEvent,
KEY_STATE KeyState,
void *pKeybdDriverToUnicodeState,
UINT32 cBufferSize, // Count of characters in pcCharacters array
UINT32 *pcCharacters,
KEY_STATE_FLAGS *pShiftStateBuffer,
UINT32 *pCharacterBuffer)
{
KEY_STATE_FLAGS ShiftFlags;
UINT32 VKeyCommon;
PINPUT_LANGUAGE pil;
UINT32 uiRet = ERROR_INVALID_PARAMETER;
SETFNAME(_T("KeybdDriverVKeyToUnicode"));
LockConfig();
// Check to make sure that an input language has been loaded.
if (g_ili.hkl == INVALID_HKL) {
ERRORMSG(1, (_T("KeybdDriverVKeyToUnicode: No input language installed\r\n")));
uiRet = ERROR_BAD_CONFIGURATION;
goto leave;
}
pil = &g_ili.il;
DEBUGCHK(ValidateInputLanguage(pil));
DEBUGCHK(pil->pCharModifiers != NULL);
DEBUGCHK(pil->pVkToWcharTable != NULL);
VirtualKey &= 0xff;
// Check pCharacterBuffer here because we may use it right away.
if ( pCharacterBuffer == NULL )
{
uiRet = ERROR_INVALID_PARAMETER;
goto leave;
}
// Do special case for MapVirtualKey here.
if ( KeyState == NULL )
{
UINT32 cChars = VKeyToUnicode(&g_ili, VirtualKey, 0, pCharacterBuffer, 1);
DEBUGCHK(cChars <= 1);
if (cChars != 0) {
// The character should already be lower case, but we'll make sure.
*pCharacterBuffer = towlower(*pCharacterBuffer);
}
else {
*pCharacterBuffer = 0;
}
uiRet = ERROR_SUCCESS;
goto leave;
}
DEBUGCHK(pKeybdDriverToUnicodeState == NULL); // No Unicode state
if ( ( cBufferSize != MAX_TO_UNICODE_CHARACTERS ) ||
( pShiftStateBuffer == NULL ) ||
( pcCharacters == NULL ) )
{
uiRet = ERROR_INVALID_PARAMETER;
goto leave;
}
// Update the virtual key state.
KeyState[VirtualKey] = NewKeyStateFlags(KeyState[VirtualKey], KeyEvent);
// Now check the duplicate keys.
VKeyCommon = MapLRVKeyToCommonVKey(VirtualKey);
if ( VKeyCommon != VirtualKey )
{
KeyState[VKeyCommon] = NewKeyStateFlags(KeyState[VKeyCommon], KeyEvent);
VirtualKey = VKeyCommon;
}
// Figure out the new shift state flags.
KeybdDriverKeyStateToShiftFlags(KeyState, VirtualKey,
g_ili.pVkToShiftState, g_ili.pVkToToggledState, &ShiftFlags);
if ( ( KeyEvent & KeyStateDownFlag ) &&
( ( VirtualKey == VK_CAPITAL ) ||
( VirtualKey == VK_NUMLOCK ) ||
( VirtualKey == VK_SCROLL ) ) )
{
DEBUGMSG(ZONE_PDD, (_T("%s: Changing light state for VKey %02x\r\n"),
pszFname, VirtualKey));
ToggleLights(ShiftFlags);
}
// Always return the shift state which counts for one entry.
*pcCharacters = 1;
// Note that ShiftFlags holds the current state of the keyboard when it is
// passed to the next routines. They will look at the current state and
// possibly update it depending on whether or not they generate a character.
if ( (g_ili.fGenerateNumPadChars == TRUE) &&
(AltNumKeyEvent(
VirtualKey,
KeyEvent,
&ShiftFlags,
pCharacterBuffer)) )
{
// If part of Alt+Num sequence, there is nothing else to do.
}
else if ( KeyEvent & KeyStateDownFlag )
{
UINT32 cwch = VKeyToUnicode(&g_ili, VirtualKey, ShiftFlags,
pCharacterBuffer, cBufferSize);
DEBUGCHK(cwch <= cBufferSize);
if (cwch == 0) {
ShiftFlags |= KeyShiftNoCharacterFlag;
}
else
{
*pcCharacters = cwch;
for (DWORD dwIdx = 0; dwIdx < cwch; ++dwIdx) {
DEBUGMSG(ZONE_INPUTLANG, (_T("%s: Mapped vkey %02x to char %04x %c\r\n"),
pszFname, VirtualKey, (WCHAR)pCharacterBuffer[dwIdx],
(WCHAR)pCharacterBuffer[dwIdx]));
pShiftStateBuffer[dwIdx] = ShiftFlags;
}
}
}
else {
ShiftFlags |= KeyShiftNoCharacterFlag;
}
*pShiftStateBuffer = ShiftFlags;
uiRet = ERROR_SUCCESS;
leave:
UnlockConfig();
if (uiRet != ERROR_SUCCESS) {
SetLastError(uiRet);
}
return uiRet;
}
#ifdef DEBUG
// Verify function declaration against the typedef.
static PFN_KEYBD_DRIVER_VKEY_TO_UNICODE v_pfnVKeyToUnicode =
KeybdDriverVKeyToUnicode;
#endif
//----------------------------------------------------------------------------
//
// KeybdDriverInitStates
//
// Set up the KeyState and ToUnicodeState.
//
// Return Value:
//
// TRUE, if success.
//
//----------------------------------------------------------------------------
BOOL
KeybdDriverInitStates(
INT iKeybdId,
KEY_STATE KeyState,
void *pKeybdDeviceToUnicodeState
)
{
memset(KeyState, 0, sizeof(KEY_STATE));
// We do not have a ToUnicodeState so ignore that parameter
return TRUE;
}
#ifdef DEBUG
// Verify function declaration against the typedef.
static PFN_KEYBD_DRIVER_INIT_STATES v_pfnInitStates = KeybdDriverInitStates;
#endif
//----------------------------------------------------------------------------
//
// KeybdDriverMapVirtualKey
//
// Performs a conversion to or from a virtual key
//
// Return Value:
//
// The converted value or 0 if failure.
//
//----------------------------------------------------------------------------
UINT32
KeybdDriverMapVirtualKey(
UINT32 uCode,
UINT32 uMapType
)
{
LockConfig();
UINT32 uRet = 0;
DWORD dwErr = ERROR_SUCCESS;
const KEYBD_PDD_INFO *pPddInfoDefault = pKeybdPddInfoFromId(0);
DEBUGCHK(pPddInfoDefault != NULL);
const DEVICE_LAYOUT_INFO *pdli = &pPddInfoDefault->dli;
if (g_ili.hkl == INVALID_HKL) {
ERRORMSG(1, (_T("MapVirtualKey: No input language installed\r\n")));
dwErr = ERROR_BAD_CONFIGURATION;
}
else if (pdli->hkl == INVALID_HKL) {
ERRORMSG(1, (_T("MapVirtualKey: No device layout installed\r\n")));
dwErr = ERROR_BAD_CONFIGURATION;
}
else {
// Get local pointers to layout data
const INPUT_LANGUAGE *pil = &g_ili.il;
DEBUGCHK(ValidateInputLanguage(pil));
const DEVICE_LAYOUT *pdl = &pdli->dl;
DEBUGCHK(ValidateDeviceLayout(pdl));
switch ( uMapType )
{
case 0:
uCode = MapCommonVKeyToLVKey(uCode);
uRet = VKeyToScanCode(uCode, pil->pVkToScanCodeTable);
break;
case 1:
ScanCodeToVKey(uCode, pdl->rgpscvk, pdl->cpscvk, &uRet);
if (uRet != 0) {
uRet = MapLRVKeyToCommonVKey(uRet);
}
break;
case 2:
KeybdDriverVKeyToUnicode(uCode, 0, NULL, NULL, 0, NULL, NULL, &uRet);
break;
case 3:
ScanCodeToVKey(uCode, pdl->rgpscvk, pdl->cpscvk, &uRet);
break;
default:
dwErr = ERROR_INVALID_PARAMETER;
break;
}
}
UnlockConfig();
if (dwErr != ERROR_SUCCESS) {
SetLastError(dwErr);
}
return uRet;
}
#ifdef DEBUG
// Verify function declaration against the typedef.
static PFN_KEYBD_DRIVER_MAP_VIRTUAL_KEY v_pfnMapVirtualKey =
KeybdDriverMapVirtualKey;
#endif
//-----------------------------------------------------
// Auto repeat #defines and state variables.
enum AutoRepeatState {
AR_WAIT_FOR_ANY = 0,
AR_INITIAL_DELAY,
AR_AUTOREPEATING,
AR_AUTO_PARTIAL, // Auto repeat was interrupted by real PDD event.
};
static int v_AutoRepeatState = AR_WAIT_FOR_ANY;
static DWORD v_AutoRepeatInitialDelay = KBD_AUTO_REPEAT_INITIAL_DELAY_DEFAULT;
static DWORD v_AutoRepeatKeysPerSec = KBD_AUTO_REPEAT_KEYS_PER_SEC_DEFAULT;
extern "C"
// @doc EXTERNAL DRIVERS
/* @func
Gives information about the keyboard and driver.
@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><c KBDI_VKEY_TO_UNICODE_INFO_ID><nl>
<tab><c KBDI_AUTOREPEAT_INFO_ID><nl>
<tab><c KBDI_AUTOREPEAT_SELECTIONS_INFO_ID>
@comm This function must be re-entrant since it is exposed by the input
system via the <f KeybdGetDeviceInfo> function and may be called by
multiple threads.
*/
BOOL KeybdDriverGetInfo(
INT iPddId, // @parm Id of the keyboard to get the information from.
INT iIndex, // @parm Id of info to retrieve.
LPVOID lpOutput // @parm Output buffer.
)
{
LockConfig();
BOOL fRet = FALSE;
if ( lpOutput == NULL )
{
SetLastError(ERROR_INVALID_PARAMETER);
goto leave;
}
switch ( iIndex )
{
case KBDI_VKEY_TO_UNICODE_INFO_ID:
VKeyToUnicodeInfo((struct KBDI_VKEY_TO_UNICODE_INFO*)lpOutput);
break;
case KBDI_AUTOREPEAT_INFO_ID:
{
struct KBDI_AUTOREPEAT_INFO *pInfo =
(struct KBDI_AUTOREPEAT_INFO*)lpOutput;
pInfo -> CurrentInitialDelay = v_AutoRepeatInitialDelay;
pInfo -> CurrentRepeatRate = v_AutoRepeatKeysPerSec;
pInfo -> cInitialDelaysSelectable = -1;
pInfo -> cRepeatRatesSelectable = -1;
}
break;
case KBDI_AUTOREPEAT_SELECTIONS_INFO_ID:
{
INT32 *pInfo = (INT32*)lpOutput;
*(pInfo) = KBD_AUTO_REPEAT_INITIAL_DELAY_MIN; // Min initial delay
*(pInfo+1) = KBD_AUTO_REPEAT_INITIAL_DELAY_MAX; // Max initial delay
*(pInfo+2) = KBD_AUTO_REPEAT_KEYS_PER_SEC_MIN; // Min repeat rate
*(pInfo+3) = KBD_AUTO_REPEAT_KEYS_PER_SEC_MAX; // Max repeat rate
}
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
goto leave;
}
fRet = TRUE;
leave:
UnlockConfig();
return fRet;
}
#ifdef DEBUG
// Verify function declaration against the typedef.
static PFN_KEYBD_DRIVER_GET_INFO v_pfnGetInfo = KeybdDriverGetInfo;
#endif
//----------------------------------------------------------------------------
//
// BroadcastToKeyboards
//
// Send an IOCTL to every external keyboard driver.
//
//----------------------------------------------------------------------------
static
void
BroadcastToKeyboards(
DWORD dwCode,
PVOID pInBuf,
DWORD cbInBuf
)
{
for (DWORD dwKbd = 0; dwKbd < dim(g_rghKbd); ++dwKbd) {
HANDLE hKbd = g_rghKbd[dwKbd];
if (hKbd) {
DeviceIoControl(hKbd, dwCode, pInBuf, cbInBuf, NULL, 0, NULL, NULL);
}
}
}
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>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -