history | TOP |
2003/07/26:作成
download | TOP |
memo | TOP |
※警告※ココの記述は「感じ」です。このとおりで無い可能性が十分にあります。
自分がアクティブで無い時でも、あるキーの組み合わせ(たとえばShift+Ctrl+F1とか)で呼び出したいときがあります。
これをホットキーと呼びます(多分)。
似た機能に、自分がアクティブな場合にメニューをいちいち選択せずに呼び出すキーの組み合わせがありますが、
これは、多分、アクセラレータキーとかショートカットキーと呼ぶと思っています。
で、ホットキーですが、まずWM_HOTKEYというウィンドウメッセージを捕まえる必要があります。
ところが、ウィンドウメッセージはウィンドウコントロールにしか飛んで来ないため、単純にTObjectから派生した
クラスを作ってもうまくいきません。そこで登場するのが
AllocateHWndです。
それから、キーの組み合わせをWindowsに登録するための関数が
RegisterHotKeyです。 この関数の使い方は、1ねんせいを参考にさせていただきました。
で、クラスの作成ですが、2つに分けようと思います。
1つは、あるキーの組み合わせとそのキーが押された時に実行する処理のを保持するクラス(TCoolKey)で、上の説明のRegisterHotKeyを実行します。
もう1つは、TCoolKeyを複数保持し、AllocateHWndを利用してWM_HOTKEYを捕まえ、適切なTCoolKeyを呼び出すクラス(TCoolKeys)です。
コードの重要ポイント(かなぁと思う所)は赤いボールドで示しています。
code-Call Test | TOP |
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, iCoolKey; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private Test : TCoolKeys; procedure ProcA(); procedure ProcB(); public end; var Form1: TForm1; implementation {$R *.dfm} // 登録するための関数 procedure TForm1.ProcA(); begin // タスクバーの表示名を変更する Application.Title := 'ProcA'; end; // 登録するための関数 procedure TForm1.ProcB(); begin // タスクバーの表示名を変更する Application.Title := 'ProcB'; end; // 初期化 procedure TForm1.FormCreate(Sender: TObject); begin Test := TCoolKeys.Create; // 保持クラスのインスタンス作成 Test.Add(ProcA, [ssShift], VK_F10); // Shift + F10 で ProcA 呼び出し Test.Add(ProcB, [ssShift], VK_F11); // Shift + F11 で ProcB 呼び出し end; // 後始末 procedure TForm1.FormDestroy(Sender: TObject); begin Test.Free; // 保持クラスのインスタンス破棄 end; end.
code-Class | TOP |
(* **************************************************************************** ホットキーをアプリケーションに比較的簡単に実装するための「ユニットファイル」 ---------------------------------------------------------------------------- 作成日 :2003/07/26 作成者 :fjtkt アドレス:http://www.geocities.jp/fjtkt/ (2003/07/26時点) **************************************************************************** *) unit iCoolKey; interface uses Windows, Messages, SysUtils, Classes; (* ======================================================= ホットキーで呼び出されるクラスメソッドの型宣言 ココでは、単なるprocedureを想定している。変更は可能。 ======================================================= *) type TCoolProc = procedure of object; // of object は、クラスメソッドの意味 // TCoolProc = procedure; // 単なる手続きならこちら (* ======================================================= ホットキーと呼び出す処理との組み合わせを保持するクラス ======================================================= *) type TCoolKeys = class private WndHandle : THandle; // ウィンドウの「ふり」をするためのハンドル Finder : TStringList; // 組み合わせを保持するリスト public function Add(AProc: TCoolProc; AModifier: TShiftState; AKey: Cardinal): integer; procedure Delete(AIndex: integer); procedure Clear(); procedure Execute(AId: integer); constructor Create(); destructor Destroy(); override; procedure WndProc(var Msg: TMessage); message WM_HOTKEY; end; implementation (* ########################################################################## *) (* ======================================================= TShiftState → Cardinal 変換 for RegisterHotKey API ======================================================= *) function ShiftStateToModifiers(AShift: TShiftState): Cardinal; begin Result := 0; if ssShift in AShift then Inc(Result, MOD_SHIFT); if ssAlt in AShift then Inc(Result, MOD_ALT); if ssCtrl in AShift then Inc(Result, MOD_CONTROL); // あきらめ Inc(Result, MOD_WIN); end; (* ======================================================= 単なるIntToStrだが... ======================================================= *) function IDtoStr(AId: integer): string; begin Result := Format('%8.8d', [Aid]); end; (* ########################################################################## *) (* ======================================================= クラス宣言 ======================================================= *) type TCoolKey = class private ID : integer; Modifier: Cardinal; VirtKey : Cardinal; Handle : THandle; Active : Boolean; CoolProc: TCoolProc; class function GetID(): integer; public constructor Create(AWndHandle: THandle; ACoolProc: TCoolProc; AShift: TShiftState; AKey: Cardinal); destructor Destroy(); override; procedure Execute(); end; (* ======================================================= ID用変数 ======================================================= *) var _ID: integer = 123; // 123 に意味は無い。なんとなく。 (* ======================================================= 一意のつもりのID作成関数 ======================================================= *) class function TCoolKey.GetID(): integer; begin Result := _ID; Inc(_ID); end; (* ================================================================= コンストラクタ http://plaza12.mbn.or.jp/~tsuboi/tips/tipsCMP05.htm ================================================================= *) constructor TCoolKey.Create(AWndHandle: THandle; ACoolProc: TCoolProc; AShift: TShiftState; AKey: Cardinal); begin //メッセージ受け取りフォーム Handle := AWndHandle; //関数割り当て CoolProc:= ACoolProc; //登録用ID ID := GetID(); //ホットキー用の修飾キー Modifier:= ShiftStateToModifiers(AShift); //ホットキー用の仮想キー VirtKey := AKey; //登録(および成功/失敗判定) Active := RegisterHotKey(Handle, ID, Modifier, VirtKey); end; (* ================================================================= デストラクタ ================================================================= *) destructor TCoolKey.Destroy(); begin //登録できている場合は ** 絶対 ** 解除 if Active then UnregisterHotKey(Handle, ID); end; (* ======================================================= 割り当て関数実行 ======================================================= *) procedure TCoolKey.Execute(); begin CoolProc(); end; (* ########################################################################## *) (* ================================================================= ウィンドウプロシージャ VCLリファレンス(AllocateHWnd) ================================================================= *) procedure TCoolKeys.WndProc(var Msg: TMessage); begin // メッセージが WM_HOTKEY なら if Msg.Msg = WM_HOTKEY then begin Execute(Msg.WParam); end else // そうでないなら begin // 元のやつ Msg.Result := DefWindowProc(WndHandle, Msg.Msg, Msg.wParam, Msg.lParam); end; end; (* ================================================================= コンストラクタ VCLリファレンス(AllocateHWnd) ================================================================= *) constructor TCoolKeys.Create(); begin inherited Create; //TCoolKey 保持・検索用リスト Finder := TStringList.Create; // ウィンドウメッセージの受け取り手続き WndHandle := AllocateHWnd(WndProc); end; (* ================================================================= デストラクタ VCLリファレンス(AllocateHWnd) ================================================================= *) destructor TCoolKeys.Destroy(); begin // ウィンドウメッセージの受け取り解除 DeallocateHWnd(WndHandle); //クリア Clear(); //解放 Finder.Free; inherited Destroy; end; (* ================================================================= ホットキーと呼び出す処理の組み合わせ追加 ================================================================= *) function TCoolKeys.Add(AProc: TCoolProc; AModifier: TShiftState; AKey: Cardinal): integer; var CoolKey : TCoolKey; begin Result := -1; // 作ってみる CoolKey := TCoolKey.Create(WndHandle, AProc, AModifier, Ord(AKey)); // 修飾キーが無い場合はやめておく。登録できていない場合もやめておく if (CoolKey.Modifier = 0) or (not CoolKey.Active) then begin CoolKey.Free; end else // 成功したらリストに保持しておく begin Result := Finder.AddObject(IDtoStr(CoolKey.ID), CoolKey); end; end; (* ================================================================= ホットキーと呼び出す処理の組み合わせ削除 ================================================================= *) procedure TCoolKeys.Delete(AIndex: integer); begin //有効範囲チェック if (AIndex < 0) or (Finder.Count <= AIndex) then Exit; //登録TCoolKey解放 Finder.Objects[AIndex].Free; //文字列削除 Finder.Delete(AIndex); end; (* ================================================================= ホットキーと呼び出す処理の組み合わせ全削除 ================================================================= *) procedure TCoolKeys.Clear(); begin //全アイテムを削除 while Finder.Count > 0 do Delete(0); //なんとなく Finder.Clear; end; (* ================================================================= IDによる実行 ================================================================= *) procedure TCoolKeys.Execute(AId: integer); var Index: integer; begin // WM_HOTKEY が教えてくれる情報は、ホットキーのIDだけ //そのIDを検索(IDは昇順に並んでいるとする) if Finder.Find(IDtoStr(AId), Index) then //あれば実行 TCoolKey(Finder.Objects[Index]).Execute(); end; end.
EOF | TOP |