6

これは可能ですか?たとえば、Notepad++ はそれを行いますが、単にアクションやメニュー項目などのコンポーネントに割り当てようとしても機能しません。割り当てられているイベントは単にトリガーしません。

そこで、Google に質問しました。なだ。次に、さまざまなショートカット関数 (この場合は TextToShortCut と ShortCutToText) をステップ実行してみました。

最初の TextToShortCut は、'Ctrl+A' (文字列) などを次の 16 ビット値に変換します。

(uint)A | (uint)Ctrl

ほとんどの場合、正常に動作します。ただし、次の奇妙なことに気付きました。

// Try converting back and forward...
TextToShortCut('Ctrl+/') = 16495

// That's incorrect. It should be:
Ord('/') or scCtrl = 16431

// Incorrect too
ShortCutToText(16495) = 'Ctrl+/'

// This is the shortcut the first line actually creates (Ctrl+o)
Ord('o') or scCtrl = 16495 // wut?

// Which is invalid, cause only caps are used
ShortCutToText(16431) = ''

何が起きてる?今のところ、エラーは TextToShortCut の最後の部分にあると思います: + 記号 (この場合は「Ctrl」) の前の部分を処理した後、残りの部分 (「/」) のショートカットを見つけようとします。ただし、現在の形式では、 + の後の部分もそれ自体で有効なショートカットである必要があります。

for Key := $08 to $255 do { Copy range from table in ShortCutToText }
  if AnsiCompareText(Text, ShortCutToText(Key)) = 0 then
  begin
    Result := Key or Shift;
    Exit;
  end;

その理由は次のとおりです。

ShortCutToText('/') = 0 (failure)
MapVirtualKey('/',MAPVK_VK_TO_VSC) = 0 (failure)

...ループは「/」を有効なショートカットとして検出できません。

これは VCL のバグですか、それとも何か不足していますか?

概念実証は次のとおりです (はい、コードのスクリーンショットを撮っていますが、これをコンポーネント パレットと組み合わせた方が、このコードを直接使用するよりも高速です)。

編集1:

ここに画像の説明を入力

編集2:

メニュー項目に 16431 を手動で割り当てても機能しません。

4

2 に答える 2

12

OnShortCutメニューの親にイベント ハンドラーを割り当てると、+TFormを押すとから 16575の値が返されることがわかります。これは、ショートカット処理のためにキーストロークをディスパッチするときに VCL が内部的に使用する関数です。Ctrl/TShortCutMenus.ShortCutFromMessage()

ShortCutToText(16495)ShortCutToText(16575)returnの両方'Ctrl+/'なので、分解してみましょう。

scCtrl = $4000
16495 = $406F
16575 = $40BF

どちらのショートカットにもscCtrlフラグが存在します。

ShortCutToText($6F)両方とShortCutToText($BF)も戻り'/'ます。これは、仮想キー( ) と( - US キーボードのキー)MapVirtualKey()の両方に対して同じスキャン コード ($350000) を返すためです。$6FVK_DIVIDE$BFVK_OEM_2/?

ショートカットをディスパッチするとき、VCL はTShortCut値の正確な比較を行います。そのため、ショートカットとして 16495 が割り当てられている場合、システムは代わりに 16575 のショートカットを報告しているため、それらは両方とも にマップされますが、トリガーされませんCtrl+/

またはのShortCutプロパティに 16575 を割り当てると、期待どおり、 +を押すとアイテムがトリガーされます。TMenuItemTActionCtrl/

トリックは、システムが のVK_OEM_2仮想キーを使用するショートカットを報告していることですが、代わりに仮想キー/を使用することを期待しています。VK_DIVIDE

于 2013-09-10T17:23:25.823 に答える
7

Keyイベント ハンドラーからの簡単な調査では、 OnKeyDown2 種類のスラッシュが示されます。

  • /テンキー上の = ( =111と組み合わせて使用​​)CTRL16575
  • /シフトキー = の横( =191と組み合わせて)CTRL16495

両方に応答する単一のショートカットを作成することはできません。

ただし、me​​mu アイテムにショートカットを設定する代わりに、SecondaryShortCutsプロパティを持つアクションをアタッチできます。次に使用します。

procedure TForm1.FormCreate(Sender: TObject);
begin
  Action1.ShortCut := 16575;
  Action1.SecondaryShortCuts.Add('Ctrl+/');
end;
于 2013-09-10T17:40:20.323 に答える