フォームにTSpeedButton配置×2
キャプションをそれぞれ、以下として
Caption := hoge1(&1)
Caption := hoge2(&2)
ボタンクリックイベントで、キャプションを表示するようにする
ShowMessage(TSpeedButton(Sender).Caption);
これで、テンキーとかで「1」「2」を叩けば、「hoge1(&1)」「hoge2(&2)」が
メッセージで表示されます。
この機能はOKとして、特定のコンテナクラス(TPanelとか)に乗っている
コンポーネントは、反応しないようにするには、どうしたらいいのでしょう?
無反応にしたいパネルで、何かのメッセージを無効化しておけばいいんでしょうか?
もっとラクチンな方法があれば、教えてください。
特定のコンテナに乗っているものだけ
&1を解除する。
とかいうのではだめでしょうか…
文字列置き換えが楽じゃなさそうか。
そもそもアクセラレータキーを必要としないのに &1 とかを設定する
理由はなんですか?
ActionList に設定すればそちらが優先されるので ActionList に設定したらどうですか?
話は変わるけど・・・
ここの人かな?
http://okapony.hp.infoseek.co.jp/
> 特定のコンテナに乗っているものだけ
> &1を解除する。
それ、めんどくさそうだから、最終手段で(^^ゞ
> そもそもアクセラレータキーを必要としないのに &1 とかを設定する
> 理由はなんですか?
TActionで作成していて、TMenuItemでもそのまま使うから。
というのも、TAction の実行履歴を10個のTSpeedButtonで実現していて、
それらは、Actionを割り当てるだけにしているから。
TActionのCaptionを(&A)抜きにして、TMenuItemでは手動でつけてもいいけど、
ちょっと多すぎて、イヤになってます。
> ここの人かな?
???なぜに???
んまぁ・・・確かに私は、KHE00221さんのPas2HTMLを使っています。
ありがとうございます。
便利に使わせていただきました。
・・・と、こんなところでお礼申し上げます。
方法1:カスタムコンポをつくって、そこに乗せる
TMyPanel=class(TPanel)
procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
end;
procedure TMyPanel.CMDialogChar(var Message: TCMDialogChar);
begin
//もみ消し
end;
方法2:コンテナクラス(今回の場合 TPanel)のメッセージをフックして
やっぱり、CM_DIALOGCHAR をもみ消す
方法3:Captionを変更する(Fusaさんの方法)
今回、10件程度の履歴を表示するコントロールなので、
それほどめんどくさくなかったです。
めんどくさいなんて言ってすいません >Fusaさん
Menus.pas の宣言を利用する
> cHotkeyPrefix := '&';
各履歴用SpeedButtonは、配列に格納済みとして
for i := 0 to 9 do begin
SpeedButton[i].Action := 履歴のAction[i];
SpeedButton[i].Caption := 自作cHotkeyPrefixを取り除く関数(SpeedButton[i].Caption);
end;
KeyDownとかを、もっと追いかけたら、もっと少しいい方法があるかもしれないけど
とりあえずは、これだけしか思いつかない。
方法1、2は、他に影響でるかもしれないので、とりあえず方法3で乗り切ってみます。
KHE00221 さんが、すばらしい技を披露してくれそうな予感がしますが、
とりあえずは、〆ます。
それではみなさん、ごきげんよう
コンポーネント化しなくても
TPanel = class(ExtCtrls.TPanel)
procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
end;
TForm1 = class(TForm1)
end;
var
Form1 : TForm1;
implementation
procedure TPanel.CMDialogChar(var Message: TCMDialogChar);
begin
if Handle <> Form1.Panel1.Handle then inherited;
end;
とやれば Panel1 に メッセージは届かなくなるよ?
> それほどめんどくさくなかったです。
> めんどくさいなんて言ってすいません >Fusaさん
いや、俺もたぶんめんどくさく感じてしまうので
あやまんなくてもいいっす。
質問せずに誰にも聞かずに、めんどくさい方法を選択するよりも
聞いてエレガントな解決方法を探るなんて、いいことじゃないですか。
CMDialogCharが流れるのですね。
勉強になってます。
方法2のTPanelのメッセージフックって、どうやるんでしたっけ?
Formのwndproc置き換えならよくやったのですが。
自分だったら
再利用考えなければ、ApplicationOnMessageで処理する
手もあるかな、と思います。
CM_系のメッセージは流れるのかな?
KHE00221さん
IDEにはPanel1 TPanelとして扱わせて
コード上ではキャストしてメッセージ横取り...
あいかわらずの冴えっぷり。すごいですね。
KHE00221さん
> コンポーネント化しなくても
毎度毎度、KHE00221さんのレスは、お勉強になります。
数枚のパネルが乗っているフォームなので、特定のパネルに対してのみ
継承したコンポーネントとして利用できないのは、いまいちなんですが、
まとめてコンポーネントの動作を差し替えしたいような場合に使える
とても便利な技かと思います。
いつか使える日がくると信じて、メモしておきました。
Fusaさん
> 方法2のTPanelのメッセージフックって、どうやるんでしたっけ?
> Formのwndproc置き換えならよくやったのですが。
Delphi2の頃からのコンポーネントをそのまま使っているだけなのですが、
このようにメッセージ処理を差し替えています。
OldWndProc := GetWindowLong(Panel1.Handle, GWL_WNDPROC);
SetWindowLong(Panel1.Handle, GWL_WNDPROC, Longint(NewWndProc));
今、Delphi5を使っており、TControl.WindowProc を差し替えるだけで
同じコトが実現できますが、まぁ、コンポーネントを書き換えるのも
めんどくさくて(めんどくさいばっかり)、これをそのまま使ってます。
んで、方法2を今風に書いてみるとこんな感じ
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
OldWndProc: TWndMethod;
procedure NewWndProc(var Message: TMessage);
end;
procedure TForm1.NewWndProc(var Message: TMessage);
begin
if Message.Msg <> CM_DIALOGCHAR then begin
OldWndProc(Message);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
OldWndProc := Panel1.WindowProc;
Panel1.WindowProc := NewWndProc;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Panel1.WindowProc := OldWndProc;
end;
cHotkeyPrefixを取り除く関数を作るのと、どっちが楽かっていうと、
ホントは、こっちが楽だったりする。
ツイート | ![]() |