« FireMonkey/OSX メニューアイテムのEnabled制御 | トップページ | FireMonkey TPopupを使いやすくする »

2011年10月 2日 (日)

FireMonkey/OSX メニューアイテムのショートカット

FireMonkey/OSX メニューアイテムの話題その3

FireMonkeyのメニューアイテム等にもVCLと同じShortCutを設定するプロパティがあるんですが、まだ色々と未完成です。(今回はOSXの話ですが、Winでもショートカットには不具合があります回避方法はまた別の機会に)
まず、ShortCutプロパティにプロパティエディタが適切に設定されていないので、Ctrl+A 等の文字列で設定できず数値を入れる必要があります。

次に、VCLの時と同じように修飾キー(scShiftなど)のコードがd15..12ビットに割り当てられていますが、OSXの場合は特殊キーの表現まで含めるとキーコードだけで16ビット必要になるためビットが重複してしまっています。 おかげでカーソルキー等をショートカットに設定することができません。

TShortCutのフォーマット自体を変えるか、TShortCutからOSX依存のコードに変換する部分(FMX.Platform.Mac.pasのShortCutToKey())を適切なものに変える必要があると思いますが、どちらもライブラリソースコードの修正なしで対応するのは難しいです。ShortCutToKey()がTPlatformMacのメンバーならRTTIでなんとかなったかも
追記:全力わはーの@lynatan さんがShortCutToKey()を置き換える方法を編み出してくださいました。http://d.hatena.ne.jp/tales/20111002/1317525163

なのでとりあえず自前のShortCutToKey()を作って、メニューを作った後でメニューアイテムのショートカットを置き換えていく方法をとりました。

以下、コード
procedure ShortCutToKey(ShortCut: TShortCut; var Key: Char; var ModifierMask: NSUInteger);
begin
  Key := Chr(Lo(ShortCut));
  ModifierMask := 0;
  case Key of
  'A'..'Z' : Key := Char(Ord(Key)+$20);
  #$08 : Key := Char(NSBackspaceCharacter);
  #$09 : Key := Char(NSTabCharacter);
  #$0d : Key := Char(NSEnterCharacter);
  #$21 : Key := Char(NSPageUpFunctionKey);
  #$22 : Key := Char(NSPageDownFunctionKey);
  #$23 : Key := Char(NSEndFunctionKey);
  #$24 : Key := Char(NSHomeFunctionKey);
  #$25 : Key := Char(NSLeftArrowFunctionKey);
  #$26 : Key := Char(NSUpArrowFunctionKey);
  #$27 : Key := Char(NSRightArrowFunctionKey);
  #$28 : Key := Char(NSDownArrowFunctionKey);
  #$2e : Key := Char(NSDeleteCharacter);
  #$70..#$87 : Key := Char(NSF1FunctionKey+Ord(Key)-$70);
  end;

  if ShortCut and scCommand <> 0 then ModifierMask := ModifierMask or NSCommandKeyMask;
  if ShortCut and scShift <> 0 then ModifierMask := ModifierMask or NSShiftKeyMask;
  if ShortCut and scCtrl <> 0 then ModifierMask := ModifierMask or NSControlKeyMask;
  if ShortCut and scAlt <> 0 then ModifierMask := ModifierMask or NSAlternateKeyMask;
end;


class procedure TMacHelper.UpdateMenuShortCut(menuitem : TMenuItem);
var
  nsmnuitem: NSMenuItem;
  Key: Char;
  ModMask: NSUInteger;
begin
  if menuitem.Handle <> 0 then
  begin
    if not (menuitem.Parent is TMainMenu) then
    begin
      nsmnuitem := GetNSMenuItem(menuitem);

      ShortCutToKey(menuitem.ShortCut, Key, ModMask);
      nsmnuitem.setKeyEquivalent(NSSTR(Key));
      nsmnuitem.setKeyEquivalentModifierMask(ModMask);
    end;
  end;
end;
※前回の記事に書いた GetNSMenuItem()も必要です。
ショートカット設定が必要なMenuItemすべてに対してUpdateMenuShortCut()を呼び出すとショートカットが修正されます。(ただしすべてのショートカットの組み合わせが上手く行くかはテストしてません)

|

« FireMonkey/OSX メニューアイテムのEnabled制御 | トップページ | FireMonkey TPopupを使いやすくする »

プログラミング」カテゴリの記事

Delphi」カテゴリの記事

FireMonkey/Delphi XE2」カテゴリの記事

コメント

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: FireMonkey/OSX メニューアイテムのショートカット:

« FireMonkey/OSX メニューアイテムのEnabled制御 | トップページ | FireMonkey TPopupを使いやすくする »