delphi - 以编程方式为 DELETE 键创建快捷方式字符串?
问题描述
在 Windows 10 x64 中的 Delphi 10.4.2 Win32 VCL 应用程序中,我使用此代码以编程方式为弹出菜单项上的 DELETE 键创建快捷方式字符串:
mGalleryDeleteSelected.Caption := mGalleryDeleteSelected.Caption + #9 + MyShortcutToString(VK_DELETE, []) + ' ';
这是源代码:
function MyGetKeyName(AKey: Integer): string;
var
name: array[0..128] of Char;
begin
FillChar(name, SizeOf(name), 0);
GetKeyNameText(MapVirtualKey(AKey, 0) shl 16, @name[0], Length(name));
Result := name;
end;
function MyModifierVirtualKey(AModifier: Integer): Integer;
begin
case AModifier of
Ord(ssShift):
Result := VK_SHIFT;
Ord(ssCtrl):
Result := VK_CONTROL;
Ord(ssAlt):
Result := VK_MENU;
else
Result := 0;
end;
end;
function MyShortcutToString(AKey: Integer; AShiftState: TShiftState = []): string;
begin
Result := '';
for var Modifier in AShiftState do
begin
var ModifierKey := MyModifierVirtualKey(Ord(Modifier));
if ModifierKey <> 0 then
Result := Result + IfThen(not Result.IsEmpty, '+') + MyGetKeyName(ModifierKey);
end;
Result := Result + IfThen(not Result.IsEmpty, '+') + MyGetKeyName(AKey);
end;
但是,我没有获得普通 DELETE 键的快捷方式字符串,而是获得了数字键盘上(辅助?)逗号/删除键的快捷方式字符串:
因为我有德语 Windows,所以这里是翻译:
KOMMA = 逗号
ZEHNERTASTATUR = 数字键盘
德语键盘上的默认 Delete 键带有标签“entf”(“Entfernen”的缩写)
如果数字小键盘设置为用于导航命令,则按数字小键盘上的逗号键确实可以用作删除命令。但是,我需要获取 NORMAL DELETE 键的字符串。我怎样才能做到这一点?
解决方案
从文档中GetKeyNameText
:
24 扩展键标志。区分增强型键盘上的一些键。
这表示它使用 LPARAM 样式参数中的第 24 位作为扩展键标志。
然后,在About Keyboard Input中:
扩展键标志
扩展键标志指示击键消息是否源自增强键盘上的附加键之一。扩展键由键盘右侧的 ALT 和 CTRL 键组成;INS、DEL、HOME、END、PAGE UP、PAGE DOWN 和数字键盘左侧集群中的箭头键;数字锁定键;BREAK (CTRL+PAUSE) 键;打印 SCRN 键;以及数字键盘中的除 (/) 和 ENTER 键。如果密钥是扩展密钥,则设置扩展密钥标志。
(正文强调我的)。
因此,我得出结论,您可以使用
function MyGetKeyName(AKey: Integer): string;
var
name: array[0..128] of Char;
begin
FillChar(name, SizeOf(name), 0); // ADD THIS!
GetKeyNameText(MapVirtualKey(AKey, 0) shl 16 or 1 shl 24, @name[0], Length(name));
Result := name;
end;
获取Del
键盘字母和数字部分之间的键名。
当然,您可能不想为其他键设置此位,因此您需要重构您的代码。不幸的是,它似乎VK_DELETE
可以映射到两个物理键。
这是一种方法:
function MyGetKeyName(AKey: Integer; AExtended: Boolean = False): string;
var
name: array[0..128] of Char;
begin
FillChar(name, SizeOf(name), 0);
if // ADD THIS!
GetKeyNameText(MapVirtualKey(AKey, 0) shl 16 or Cardinal(Ord(AExtended)) shl 24,
@name[0], Length(name)) <> 0
then
Result := name
else
Result := '';
end;
并将此参数也添加到您MyShortcutToString
的(只需将其传递给MyGetKeyName
):
function MyShortcutToString(AKey: Integer; AShiftState: TShiftState = [];
AExtended: Boolean = False): string;
begin
Result := '';
for var Modifier in AShiftState do
begin
var ModifierKey := MyModifierVirtualKey(Ord(Modifier));
if ModifierKey <> 0 then
Result := Result + IfThen(not Result.IsEmpty, '+') + MyGetKeyName(ModifierKey);
end;
Result := Result + IfThen(not Result.IsEmpty, '+') + MyGetKeyName(AKey, AExtended);
end;
推荐阅读
- mysql - 使用 zcat 日志时间脚本导入 MySQL 完成
- java - 构造函数是否同步直到完全完成?
- html - 为什么设置为使用 CSS 变量继承的显示属性不起作用?
- python - R to Python:将一列(在数据框中)分成数据框中的几列
- shell - Makefile 如何在删除所有其他目标文件和可执行文件时不删除一个特定的目标文件?
- python - 将字符串的某些部分转换为 int python 的问题
- io - 从文件读取期间的 Fortran 运行时错误
- sql-server - 从 SQLOLEDB.1 更改为 SQLNCLI 的性能问题?
- javascript - javascript typeof Object.create !== '函数'
- python - 如何通过不需要 sudo 密码的 python 脚本停止和启动 systemd 服务