首页 > 解决方案 > 以编程方式为 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 键的字符串。我怎样才能做到这一点?

标签: delphikeyboard-shortcutsdelphi-10.4-sydney

解决方案


从文档中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;

推荐阅读