如何为分配有 `VK_NUMPAD0` 的菜单项快捷方式显示 "NUMERIC KEYPAD"?
How to show "NUMERIC KEYPAD" for menu item shortcut assigned with `VK_NUMPAD0`?
在 Delphi 10.4.2 Win32 VCL 应用程序中,在 Windows10 X64(德语)上,我以编程方式设置了一些菜单项的快捷方式:
mRasterizedDoubleSize.Shortcut := VK_ADD;
mRasterizedHalveSize.Shortcut := VK_SUBTRACT;
mRasterizedResetToOriginalSVGSize.Shortcut := VK_NUMPAD0;
这会在 运行 时产生以下菜单:
(“ZEHNERTASTATUR”是德语数字键盘)
为什么第三个菜单项没有显示“Zehnertastatur”(数字小键盘)?
如何为分配给 VK_NUMPAD0
的菜单项快捷方式显示“ZEHNERTASTATUR”(数字键盘)?
我已在 Vcl.Menus 中针对此错误提交质量报告:https://quality.embarcadero.com/browse/RSP-33296
请为它投票!
编辑:我已经尝试过 Andreas 的建议,但它确实只在 运行 时以编程方式工作,而不是在对象检查器的设计时工作:
mRasterizedResetToOriginalSVGSize.Caption := mRasterizedResetToOriginalSVGSize.Caption + #9 + '0 (NUMPAD) ';
难道没有在-运行-时间将单词“NUMPAD”翻译成当前系统语言的功能吗?
EDIT2:我试过这个来获取 VK_NUMPAD0
快捷方式的单词,但它只返回没有“NUMPAD”后缀的相同“0” :
var s: TShortCut;
s := ShortCut(VK_NUMPAD0, []);
CodeSite.Send('TformMain.FormCreate: ShortCutToText(s)', ShortCutToText(s));
EDIT3:我现在已经调试了 Vcl.Menus
:错误似乎在 Vcl.Menus.ShortCutToText
:而 VK_ADD
($6B) 是GetSpecialName(ShortCut)
正确翻译,VK_NUMPAD0
($60) 未被 GetSpecialName(ShortCut)
!
翻译
EDIT4:我找到了解决方案:
function MyGetSpecialName(ShortCut: TShortCut): string;
var
ScanCode: Integer;
KeyName: array[0..255] of Char;
begin
Result := '';
ScanCode := Winapi.Windows.MapVirtualKey(LoByte(Word(ShortCut)), 0) shl 16;
if ScanCode <> 0 then
begin
if Winapi.Windows.GetKeyNameText(ScanCode, KeyName, Length(KeyName)) <> 0 then
Result := KeyName;
end;
end;
var s: System.Classes.TShortCut;
s := ShortCut(VK_NUMPAD0, []);
CodeSite.Send('ShortCutToText', MyGetSpecialName(s));
一种方法是这样的:
使用 TActionList
。这是一般的好习惯。在此列表中定义您的操作,然后简单地将它们映射到菜单项、按钮、复选框等。操作列表功能是 VCL 恕我直言的最佳部分之一。
现在,创建一个名为 aResetZoom
且 Caption = 'Reset zoom'#9'Numpad 0'
且没有 ShortCut
的操作。把它放在菜单栏上。
然后,创建一个名为 aResetZoomShortcut
的 new 操作,具有相同的 OnExecute
(也可能相同的 OnUpdate
)和快捷方式 Num 0
(在设计时设置或在 运行 时以编程方式设置)。不要把它放在主菜单上。
结果:
当我按下小键盘 0(而不是 alpha 0)时触发操作。
这种方法有很多变体。也许您可以通过没有 ShortCut
但在其 SecondaryShortCuts
列表中使用 Num 0 的单个操作来使其工作。或者您可以使用表单的 KeyPreview
和 OnKeyPress
属性来代替“虚拟”操作。
多种选择。选择最适合您的特定场景的一种。
奖金备注
请注意,完全有可能在设计时使用 Object 检查器设置带制表符的标题。参见 example video。
您或许可以使用 Win32 GetKeyNameText
功能进行本地化。以下代码改编自 VCL:
var
name: array[0..128] of Char;
begin
FillChar(name, SizeOf(name), 0);
GetKeyNameText(MapVirtualKey(VK_NUMPAD0, 0) shl 16, @name[0], Length(name));
// string(name) now is 'NUM 0' on my system
话虽如此,我个人并不介意快捷方式描述是 non-localized 还是手动本地化——就像应用程序的其余部分一样。
更新
关于如何使用本地化代码的说明:
procedure TForm5.FormCreate(Sender: TObject);
var
name: array[0..128] of Char;
NameAsANormalString: string;
begin
FillChar(name, SizeOf(name), 0);
GetKeyNameText(MapVirtualKey(VK_NUMPAD0, 0) shl 16, @name[0], Length(name));
NameAsANormalString := name;
ShowMessage(name);
end;
产生
在我的系统上。
在 Delphi 10.4.2 Win32 VCL 应用程序中,在 Windows10 X64(德语)上,我以编程方式设置了一些菜单项的快捷方式:
mRasterizedDoubleSize.Shortcut := VK_ADD;
mRasterizedHalveSize.Shortcut := VK_SUBTRACT;
mRasterizedResetToOriginalSVGSize.Shortcut := VK_NUMPAD0;
这会在 运行 时产生以下菜单:
(“ZEHNERTASTATUR”是德语数字键盘)
为什么第三个菜单项没有显示“Zehnertastatur”(数字小键盘)?
如何为分配给 VK_NUMPAD0
的菜单项快捷方式显示“ZEHNERTASTATUR”(数字键盘)?
我已在 Vcl.Menus 中针对此错误提交质量报告:https://quality.embarcadero.com/browse/RSP-33296 请为它投票!
编辑:我已经尝试过 Andreas 的建议,但它确实只在 运行 时以编程方式工作,而不是在对象检查器的设计时工作:
mRasterizedResetToOriginalSVGSize.Caption := mRasterizedResetToOriginalSVGSize.Caption + #9 + '0 (NUMPAD) ';
难道没有在-运行-时间将单词“NUMPAD”翻译成当前系统语言的功能吗?
EDIT2:我试过这个来获取 VK_NUMPAD0
快捷方式的单词,但它只返回没有“NUMPAD”后缀的相同“0” :
var s: TShortCut;
s := ShortCut(VK_NUMPAD0, []);
CodeSite.Send('TformMain.FormCreate: ShortCutToText(s)', ShortCutToText(s));
EDIT3:我现在已经调试了 Vcl.Menus
:错误似乎在 Vcl.Menus.ShortCutToText
:而 VK_ADD
($6B) 是GetSpecialName(ShortCut)
正确翻译,VK_NUMPAD0
($60) 未被 GetSpecialName(ShortCut)
!
EDIT4:我找到了解决方案:
function MyGetSpecialName(ShortCut: TShortCut): string;
var
ScanCode: Integer;
KeyName: array[0..255] of Char;
begin
Result := '';
ScanCode := Winapi.Windows.MapVirtualKey(LoByte(Word(ShortCut)), 0) shl 16;
if ScanCode <> 0 then
begin
if Winapi.Windows.GetKeyNameText(ScanCode, KeyName, Length(KeyName)) <> 0 then
Result := KeyName;
end;
end;
var s: System.Classes.TShortCut;
s := ShortCut(VK_NUMPAD0, []);
CodeSite.Send('ShortCutToText', MyGetSpecialName(s));
一种方法是这样的:
使用 TActionList
。这是一般的好习惯。在此列表中定义您的操作,然后简单地将它们映射到菜单项、按钮、复选框等。操作列表功能是 VCL 恕我直言的最佳部分之一。
现在,创建一个名为 aResetZoom
且 Caption = 'Reset zoom'#9'Numpad 0'
且没有 ShortCut
的操作。把它放在菜单栏上。
然后,创建一个名为 aResetZoomShortcut
的 new 操作,具有相同的 OnExecute
(也可能相同的 OnUpdate
)和快捷方式 Num 0
(在设计时设置或在 运行 时以编程方式设置)。不要把它放在主菜单上。
结果:
当我按下小键盘 0(而不是 alpha 0)时触发操作。
这种方法有很多变体。也许您可以通过没有 ShortCut
但在其 SecondaryShortCuts
列表中使用 Num 0 的单个操作来使其工作。或者您可以使用表单的 KeyPreview
和 OnKeyPress
属性来代替“虚拟”操作。
多种选择。选择最适合您的特定场景的一种。
奖金备注
请注意,完全有可能在设计时使用 Object 检查器设置带制表符的标题。参见 example video。
您或许可以使用 Win32 GetKeyNameText
功能进行本地化。以下代码改编自 VCL:
var
name: array[0..128] of Char;
begin
FillChar(name, SizeOf(name), 0);
GetKeyNameText(MapVirtualKey(VK_NUMPAD0, 0) shl 16, @name[0], Length(name));
// string(name) now is 'NUM 0' on my system
话虽如此,我个人并不介意快捷方式描述是 non-localized 还是手动本地化——就像应用程序的其余部分一样。
更新
关于如何使用本地化代码的说明:
procedure TForm5.FormCreate(Sender: TObject);
var
name: array[0..128] of Char;
NameAsANormalString: string;
begin
FillChar(name, SizeOf(name), 0);
GetKeyNameText(MapVirtualKey(VK_NUMPAD0, 0) shl 16, @name[0], Length(name));
NameAsANormalString := name;
ShowMessage(name);
end;
产生
在我的系统上。