LCL: ShortCutToText faster, with array. Issue #30992. Patch by AlexeyT

git-svn-id: trunk@57373 -
This commit is contained in:
michl 2018-02-25 14:13:12 +00:00
parent ca33175c5f
commit 193932300b

View File

@ -415,10 +415,278 @@ var
MenuKeyCaps: array[TMenuKeyCap] of string;
MenuKeyCapsInited: boolean = false;
const
// MS documentation:
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
//
// Note: ShortcutToText must ignore single key Ctrl, Alt, Shift, Win,
// so these items have empty str here
//
KeyCodeStrings: array[1..$FF] of string = (
'Mouse_Left', // 0x1 - VK_LBUTTON
'Mouse_Right', // 0x2 - VK_RBUTTON
'Cancel', // 0x3 - VK_CANCEL - generated by Ctrl+Break
'Mouse_Middle', // 0x4 - VK_MBUTTON
'Mouse_X1', // 0x5 - VK_XBUTTON1
'Mouse_X2', // 0x6 - VK_XBUTTON2
'', // 0x7
'Backspace', // 0x8 - VK_BACK
'Tab', // 0x9 - VK_TAB
'', // 0xa
'', // 0xb
'NumClear', // 0xc - VK_CLEAR - generated by Num5 (NumLock off)
'Enter', // 0xd - VK_RETURN
'', // 0xe
'', // 0xf
'', //'Shift', // 0x10 - VK_SHIFT
'', //'Ctrl', // 0x11 - VK_CONTROL
'', //'Alt', // 0x12 - VK_MENU
'Break', // 0x13 - VK_PAUSE - Pause/Break key
'CapsLock', // 0x14 - VK_CAPITAL
'IME_Kana', // 0x15 - VK_KANA
'', // 0x16
'IME_Junja', // 0x17 - VK_JUNJA
'IME_final', // 0x18 - VK_FINAL
'IME_Hanja', // 0x19 - VK_HANJA
'', // 0x1a
'Esc', // 0x1b - VK_ESCAPE
'IME_convert', // 0x1c - VK_CONVERT
'IME_nonconvert', // 0x1d - VK_NONCONVERT
'IME_accept', // 0x1e - VK_ACCEPT
'IME_mode_change', // 0x1f - VK_MODECHANGE
'Space', // 0x20 - VK_SPACE
'PgUp', // 0x21 - VK_PRIOR
'PgDown', // 0x22 - VK_NEXT
'End', // 0x23 - VK_END
'Home', // 0x24 - VK_HOME
'Left', // 0x25 - VK_LEFT
'Up', // 0x26 - VK_UP
'Right', // 0x27 - VK_RIGHT
'Down', // 0x28 - VK_DOWN
'Select', // 0x29 - VK_SELECT
'Print', // 0x2a - VK_PRINT
'Execute', // 0x2b - VK_EXECUTE
'PrintScreen', // 0x2c - VK_SNAPSHOT
'Ins', // 0x2d - VK_INSERT
'Del', // 0x2e - VK_DELETE
'Help', // 0x2f - VK_HELP
'0', // 0x30
'1', // 0x31
'2', // 0x32
'3', // 0x33
'4', // 0x34
'5', // 0x35
'6', // 0x36
'7', // 0x37
'8', // 0x38
'9', // 0x39
'', // 0x3a
'', // 0x3b
'', // 0x3c
'', // 0x3d
'', // 0x3e
'', // 0x3f
'', // 0x40
'A', // 0x41
'B', // 0x42
'C', // 0x43
'D', // 0x44
'E', // 0x45
'F', // 0x46
'G', // 0x47
'H', // 0x48
'I', // 0x49
'J', // 0x4a
'K', // 0x4b
'L', // 0x4c
'M', // 0x4d
'N', // 0x4e
'O', // 0x4f
'P', // 0x50
'Q', // 0x51
'R', // 0x52
'S', // 0x53
'T', // 0x54
'U', // 0x55
'V', // 0x56
'W', // 0x57
'X', // 0x58
'Y', // 0x59
'Z', // 0x5a
'', //'LWindows', // 0x5b - VK_LWIN
'', //'RWindows', // 0x5c - VK_RWIN
'PopUp', // 0x5d - VK_APPS - PC, key near right Ctrl
'', // 0x5e
'Sleep', // 0x5f - VK_SLEEP
'Num0', // 0x60 - VK_NUMPAD0
'Num1', // 0x61
'Num2', // 0x62
'Num3', // 0x63
'Num4', // 0x64
'Num5', // 0x65
'Num6', // 0x66
'Num7', // 0x67
'Num8', // 0x68
'Num9', // 0x69 - VK_NUMPAD9
'NumMul', // 0x6a - VK_MULTIPLY
'NumPlus', // 0x6b - VK_ADD
'NumSepar', // 0x6c - VK_SEPARATOR
'NumMinus', // 0x6d - VK_SUBTRACT
'NumDot', // 0x6e - VK_DECIMAL
'NumDiv', // 0x6f - VK_DIVIDE
'F1', // 0x70 - VK_F1
'F2', // 0x71
'F3', // 0x72
'F4', // 0x73
'F5', // 0x74
'F6', // 0x75
'F7', // 0x76
'F8', // 0x77
'F9', // 0x78
'F10', // 0x79
'F11', // 0x7a
'F12', // 0x7b
'F13', // 0x7c
'F14', // 0x7d
'F15', // 0x7e
'F16', // 0x7f
'F17', // 0x80
'F18', // 0x81
'F19', // 0x82
'F20', // 0x83
'F21', // 0x84
'F22', // 0x85
'F23', // 0x86
'F24', // 0x87 - VK_F24
'', // 0x88
'', // 0x89
'', // 0x8a
'', // 0x8b
'', // 0x8c
'', // 0x8d
'', // 0x8e
'', // 0x8f
'NumLock', // 0x90 - VK_NUMLOCK
'ScrollLock', // 0x91 - VK_SCROLL
'OEM_0x92', // 0x92
'OEM_0x93', // 0x93
'OEM_0x94', // 0x94
'OEM_0x95', // 0x95
'OEM_0x96', // 0x96
'', // 0x97
'', // 0x98
'', // 0x99
'', // 0x9a
'', // 0x9b
'', // 0x9c
'', // 0x9d
'', // 0x9e
'', // 0x9f
'', //'LShift', // 0xa0 - VK_LSHIFT
'', //'RShift', // 0xa1 - VK_RSHIFT
'', //'LCtrl', // 0xa2 - VK_LCONTROL
'', //'RCtrl', // 0xa3 - VK_RCONTROL
'', //'LAlt', // 0xa4 - VK_LMENU
'', //'RAlt', // 0xa5 - VK_RMENU
'BrowserBack', // 0xa6 - VK_BROWSER_BACK
'BrowserForward', // 0xa7 - VK_BROWSER_FORWARD
'BrowserRefresh', // 0xa8 - VK_BROWSER_REFRESH
'BrowserStop', // 0xa9 - VK_BROWSER_STOP
'BrowserSearch', // 0xaa - VK_BROWSER_SEARCH
'BrowserFav', // 0xab - VK_BROWSER_FAVORITES
'BrowserHome', // 0xac - VK_BROWSER_HOME
'VolumeMute', // 0xad - VK_VOLUME_MUTE
'VolumeDown', // 0xae - VK_VOLUME_DOWN
'VolumeUp', // 0xaf - VK_VOLUME_UP
'MediaNext', // 0xb0 - VK_MEDIA_NEXT_TRACK
'MediaPrev', // 0xb1 - VK_MEDIA_PREV_TRACK
'MediaStop', // 0xb2 - VK_MEDIA_STOP
'MediaPlayPause', // 0xb3 - VK_MEDIA_PLAY_PAUSE
'LaunchMail', // 0xb4 - VK_LAUNCH_MAIL
'LaunchMedia', // 0xb5 - VK_LAUNCH_MEDIA_SELECT
'LaunchApp1', // 0xb6 - VK_LAUNCH_APP1
'LaunchApp2', // 0xb7 - VK_LAUNCH_APP2
'', // 0xb8
'', // 0xb9
';', // 0xba - VK_OEM_1 - Can vary by keyboard, US keyboard, the ';:' key
'+', // 0xbb - VK_OEM_PLUS - For any country/region, the '+' key
',', // 0xbc - VK_OEM_COMMA - For any country/region, the ',' key
'-', // 0xbd - VK_OEM_MINUS - For any country/region, the '-' key
'.', // 0xbe - VK_OEM_PERIOD - For any country/region, the '.' key
'/', // 0xbf - VK_OEM_2 - Can vary by keyboard, US keyboard, the '/?' key
'`', // 0xc0 - VK_OEM_3 - Can vary by keyboard, US keyboard, the '`~' key
'', // 0xc1
'', // 0xc2
'', // 0xc3
'', // 0xc4
'', // 0xc5
'', // 0xc6
'', // 0xc7
'', // 0xc8
'', // 0xc9
'', // 0xca
'', // 0xcb
'', // 0xcc
'', // 0xcd
'', // 0xce
'', // 0xcf
'', // 0xd0
'', // 0xd1
'', // 0xd2
'', // 0xd3
'', // 0xd4
'', // 0xd5
'', // 0xd6
'', // 0xd7
'', // 0xd8
'', // 0xd9
'', // 0xda
'[', // 0xdb - VK_OEM_4 - Can vary by keyboard, US keyboard, the '[{' key
'\', // 0xdc - VK_OEM_5 - Can vary by keyboard, US keyboard, the '\|' key
']', // 0xdd - VK_OEM_6 - Can vary by keyboard, US keyboard, the ']}' key
'''', // 0xde - VK_OEM_7 - Can vary by keyboard, US keyboard, the 'single-quote/double-quote' key
'OEM_8', // 0xdf - VK_OEM_8
'', // 0xe0
'OEM_0xE1', // 0xe1
'\', // 0xe2 - VK_OEM_102 - Either the angle bracket key or the backslash key on the RT 102-key keyboard
'OEM_0xE3', // 0xe3
'OEM_0xE4', // 0xe4
'IME_process', // 0xe5 - VK_PROCESSKEY
'OEM_0xE6', // 0xe6
'UnicodePacket', // 0xe7 - VK_PACKET
'', // 0xe8
'OEM_0xE9', // 0xe9
'OEM_0xEA', // 0xea
'OEM_0xEB', // 0xeb
'OEM_0xEC', // 0xec
'OEM_0xED', // 0xed
'OEM_0xEE', // 0xee
'OEM_0xEF', // 0xef
'OEM_0xF0', // 0xf0
'OEM_0xF1', // 0xf1
'OEM_0xF2', // 0xf2
'OEM_0xF3', // 0xf3
'OEM_0xF4', // 0xf4
'OEM_0xF5', // 0xf5
'Attn', // 0xf6 - VK_ATTN
'CrSel', // 0xf7 - VK_CRSEL
'ExSel', // 0xf8 - VK_EXSEL
'EraseEOF', // 0xf9 - VK_EREOF
'Play', // 0xfa - VK_PLAY
'Zoom', // 0xfb - VK_ZOOM
'', // 0xfc
'PA1', // 0xfd - VK_PA1
'OEM_Clear', // 0xfe - VK_OEM_CLEAR
'' // 0xff
);
procedure InitializeMenuKeyCaps;
begin
if MenuKeyCapsInited=false then
if not MenuKeyCapsInited then
begin
MenuKeyCapsInited:=true;
MenuKeyCaps[mkcBkSp]:=SmkcBkSp;
MenuKeyCaps[mkcTab]:=SmkcTab;
MenuKeyCaps[mkcEsc]:=SmkcEsc;
@ -438,58 +706,26 @@ begin
MenuKeyCaps[mkcCtrl]:=SmkcCtrl;
MenuKeyCaps[mkcAlt]:=SmkcAlt;
MenuKeyCaps[mkcMeta]:=SmkcMeta;
MenuKeyCapsInited:=true;
end;
end;
function GetSpecialShortCutName(Key: integer): string;
begin
Result := '';
case Key of
VK_CANCEL: Result := 'Cancel'; //generated by Ctrl+Break
VK_CLEAR: Result := 'NumClear'; //generated by Num5 (NumLock off)
VK_PAUSE: Result := 'Break';
VK_CAPITAL: Result := 'CapsLock';
VK_APPS: Result := 'PopUp'; //PC, near right Ctrl
VK_MULTIPLY: Result := 'NumMul';
VK_ADD: Result := 'NumPlus';
VK_SUBTRACT: Result := 'NumMinus';
VK_DECIMAL: Result := 'NumDot';
VK_DIVIDE: Result := 'NumDiv';
VK_NUMLOCK: Result := 'NumLock';
VK_SCROLL: Result := 'ScrollLock';
VK_OEM_1: Result := ';'; // Can vary by keyboard, US keyboard, the ';:' key
VK_OEM_PLUS: Result := '+'; // For any country/region, the '+' key
VK_OEM_COMMA: Result := ','; // For any country/region, the ',' key
VK_OEM_MINUS: Result := '-'; // For any country/region, the '-' key
VK_OEM_PERIOD: Result := '.'; // For any country/region, the '.' key
VK_OEM_2: Result := '/'; // Can vary by keyboard, US keyboard, the '/?' key
VK_OEM_3: Result := '`'; // Can vary by keyboard, US keyboard, the '`~' key
VK_OEM_4: Result := '['; // Can vary by keyboard, US keyboard, the '[{' key
VK_OEM_5: Result := '\'; // Can vary by keyboard, US keyboard, the '\|' key
VK_OEM_6: Result := ']'; // Can vary by keyboard, US keyboard, the ']}' key
VK_OEM_7: Result := ''''; // Can vary by keyboard, US keyboard, the 'single-quote/double-quote' key
VK_OEM_102: Result := '\'; // Either the angle bracket key or the backslash key on the RT 102-key keyboard
//Windows keyboard special:
$A6: Result := 'BrowserBack';
$A7: Result := 'BrowserForward';
$A8: Result := 'BrowserRefresh';
$A9: Result := 'BrowserStop';
$AA: Result := 'BrowserSearch';
$AB: Result := 'BrowserFav';
$AC: Result := 'BrowserHome';
$AD: Result := 'VolumeMute';
$AE: Result := 'VolumeDown';
$AF: Result := 'VolumeUp';
$B0: Result := 'MediaNext';
$B1: Result := 'MediaPrev';
$B2: Result := 'MediaStop';
$B3: Result := 'MediaPlay';
$B4: Result := 'LaunchMail';
$B5: Result := 'LaunchMedia';
$B6: Result := 'LaunchApp1';
$B7: Result := 'LaunchApp2';
KeyCodeStrings[VK_BACK]:=SmkcBkSp;
KeyCodeStrings[VK_TAB]:=SmkcTab;
KeyCodeStrings[VK_ESCAPE]:=SmkcEsc;
KeyCodeStrings[VK_RETURN]:=SmkcEnter;
KeyCodeStrings[VK_SPACE]:=SmkcSpace;
KeyCodeStrings[VK_PRIOR]:=SmkcPgUp;
KeyCodeStrings[VK_NEXT]:=SmkcPgDn;
KeyCodeStrings[VK_END]:=SmkcEnd;
KeyCodeStrings[VK_HOME]:=SmkcHome;
KeyCodeStrings[VK_LEFT]:=SmkcLeft;
KeyCodeStrings[VK_UP]:=SmkcUp;
KeyCodeStrings[VK_RIGHT]:=SmkcRight;
KeyCodeStrings[VK_DOWN]:=SmkcDown;
KeyCodeStrings[VK_INSERT]:=SmkcIns;
KeyCodeStrings[VK_DELETE]:=SmkcDel;
// must ignore single Shift, Alt, Ctrl in KeyCodeStrings
//KeyCodeStrings[VK_SHIFT]:=SmkcShift;
//KeyCodeStrings[VK_CONTROL]:=SmkcCtrl;
//KeyCodeStrings[VK_MENU]:=SmkcAlt;
end;
end;
@ -523,6 +759,14 @@ begin
Result:=DefaultValue;
end;
function KeyCodeToKeyString(Key: integer): string;
begin
if (Key >= Low(KeyCodeStrings)) and (Key <= High(KeyCodeStrings)) then
Result := KeyCodeStrings[Key]
else
Result := '';
end;
// Used also by TWidgetSet.GetAcceleratorString
function KeyAndShiftStateToKeyString(Key: word; ShiftState: TShiftState): String;
@ -533,79 +777,8 @@ function KeyAndShiftStateToKeyString(Key: word; ShiftState: TShiftState): String
Result := Result + APart;
end;
// Tricky routine. This only works for western languages
procedure AddKey;
begin
case Key of
VK_UNKNOWN :AddPart(ifsVK_UNKNOWN);
VK_LBUTTON :AddPart(ifsVK_LBUTTON);
VK_RBUTTON :AddPart(ifsVK_RBUTTON);
VK_CANCEL :AddPart(ifsVK_CANCEL);
VK_MBUTTON :AddPart(ifsVK_MBUTTON);
VK_BACK :AddPart(ifsVK_BACK);
VK_TAB :AddPart(ifsVK_TAB);
VK_CLEAR :AddPart(ifsVK_CLEAR);
VK_RETURN :AddPart(ifsVK_RETURN);
VK_SHIFT :AddPart(ifsVK_SHIFT);
VK_CONTROL :AddPart(ifsVK_CONTROL);
VK_MENU :AddPart(ifsVK_MENU);
VK_PAUSE :AddPart(ifsVK_PAUSE);
VK_CAPITAL :AddPart(ifsVK_CAPITAL);
VK_KANA :AddPart(ifsVK_KANA);
// VK_HANGUL :AddPart('Hangul');
VK_JUNJA :AddPart(ifsVK_JUNJA);
VK_FINAL :AddPart(ifsVK_FINAL);
VK_HANJA :AddPart(ifsVK_HANJA );
// VK_KANJI :AddPart('Kanji');
VK_ESCAPE :AddPart(ifsVK_ESCAPE);
VK_CONVERT :AddPart(ifsVK_CONVERT);
VK_NONCONVERT :AddPart(ifsVK_NONCONVERT);
VK_ACCEPT :AddPart(ifsVK_ACCEPT);
VK_MODECHANGE :AddPart(ifsVK_MODECHANGE);
VK_SPACE :AddPart(ifsVK_SPACE);
VK_PRIOR :AddPart(ifsVK_PRIOR);
VK_NEXT :AddPart(ifsVK_NEXT);
VK_END :AddPart(ifsVK_END);
VK_HOME :AddPart(ifsVK_HOME);
VK_LEFT :AddPart(ifsVK_LEFT);
VK_UP :AddPart(ifsVK_UP);
VK_RIGHT :AddPart(ifsVK_RIGHT);
VK_DOWN :AddPart(ifsVK_DOWN);
VK_SELECT :AddPart(ifsVK_SELECT);
VK_PRINT :AddPart(ifsVK_PRINT);
VK_EXECUTE :AddPart(ifsVK_EXECUTE);
VK_SNAPSHOT :AddPart(ifsVK_SNAPSHOT);
VK_INSERT :AddPart(ifsVK_INSERT);
VK_DELETE :AddPart(ifsVK_DELETE);
VK_HELP :AddPart(ifsVK_HELP);
VK_0..VK_9 :AddPart(chr(ord('0')+Key-VK_0));
VK_A..VK_Z :AddPart(chr(ord('A')+Key-VK_A));
VK_LWIN :AddPart(ifsVK_LWIN);
VK_RWIN :AddPart(ifsVK_RWIN);
VK_APPS :AddPart(ifsVK_APPS);
VK_NUMPAD0..VK_NUMPAD9: AddPart(Format(ifsVK_NUMPAD,[Key-VK_NUMPAD0]));
VK_MULTIPLY :AddPart('*');
VK_ADD :AddPart('+');
VK_OEM_PLUS :AddPart('+');
VK_SEPARATOR :AddPart('|');
VK_SUBTRACT :AddPart('-');
VK_OEM_MINUS :AddPart('-');
VK_DECIMAL :AddPart('.');
VK_OEM_PERIOD :AddPart('.');
VK_OEM_COMMA :AddPart(',');
VK_DIVIDE :AddPart('/');
VK_F1..VK_F24: AddPart('F'+IntToStr(Key-VK_F1+1));
VK_NUMLOCK :AddPart(ifsVK_NUMLOCK);
VK_SCROLL :AddPart(ifsVK_SCROLL);
VK_OEM_2 :AddPart('OEM2');
VK_OEM_3 :AddPart('OEM3');
// VK_EQUAL :AddPart('=');
// VK_AT :AddPart('@');
else
AddPart(UNKNOWN_VK_PREFIX + IntToStr(Key) + UNKNOWN_VK_POSTFIX);
end;
end;
var
s: string;
begin
Result := '';
if ssCtrl in ShiftState then AddPart(ifsCtrl);
@ -618,7 +791,12 @@ begin
AddPart(ifsVK_META);
{$ENDIF}
if ssSuper in ShiftState then AddPart(ifsVK_SUPER);
AddKey;
s := KeyCodeToKeyString(Key);
// function returned "Word(nnn)" previously, keep this
if s = '' then
s := UNKNOWN_VK_PREFIX + IntToStr(Key) + UNKNOWN_VK_POSTFIX;
AddPart(s);
end;
function KeyStringIsIrregular(const s: string): boolean;
@ -627,36 +805,6 @@ begin
(AnsiStrLComp(PChar(s),PChar(UNKNOWN_VK_PREFIX),length(UNKNOWN_VK_PREFIX))=0);
end;
function KeyCodeToKeyString(Key: integer): string;
begin
case Key of
VK_BACK:
Result := MenuKeyCaps[mkcBkSp];
VK_TAB:
Result := MenuKeyCaps[mkcTab];
VK_RETURN:
Result := MenuKeyCaps[mkcEnter];
VK_ESCAPE:
Result := MenuKeyCaps[mkcEsc];
VK_SPACE..VK_SPACE+8:
Result := MenuKeyCaps[TMenuKeyCap(Key - VK_SPACE + Ord(mkcSpace))];
VK_INSERT:
Result := MenuKeyCaps[mkcIns];
VK_DELETE:
Result := MenuKeyCaps[mkcDel];
VK_0..VK_9:
Result := Chr(Key - VK_0 + Ord('0'));
VK_A..VK_Z:
Result := Chr(Key - VK_A + Ord('A'));
VK_NUMPAD0..VK_NUMPAD9:
Result := 'Num' + Chr(Key - VK_NUMPAD0 + Ord('0')); // Delphi differs it from 0..9
VK_F1..VK_F24:
Result := 'F' + IntToStr(Key - (VK_F1-1));
else
Result := GetSpecialShortCutName(Key);
end;
end;
function ShortCutToText(ShortCut: TShortCut): string;
var
Name: string;
@ -713,8 +861,10 @@ begin
else
Break;
end;
for Key := $08 to $FF do begin { Copy range from table in ShortCutToText }
Name := ShortCutToText(Key);
for Key := Low(KeyCodeStrings) to High(KeyCodeStrings) do
begin
Name := KeyCodeToKeyString(Key);
if (Name<>'') and (length(Name)=length(ShortCutText)-StartPos+1)
and (AnsiStrLIComp(@ShortCutText[StartPos], PChar(Name), length(Name)) = 0)
then begin