†Sibylのお部屋†

OnScan/OnKeyPressのないコントロールへのキー入力

作成開始日 2022.04.17
最終更新日 2022.04.17

【結論】PanelやGroupBox上でキー入力を処理するには、ダミーのLitBoxを利用する

PanelやGroupBoxにはOnScan/OnKeyPressがなく、これらのコントロール上で直接キー入力をフックすることは不可能。この場合、キー入力は大元のForm1が受け取ることになるのだが、Form1のOnScanはそんなに上手く機能してくれない。

例として、RadioGroupに相当する機能(複数の選択肢から1つを選ぶ)を、PanelとLabelで自作する場合を考える。RadioGroupと同等なら、何も自作する必要はないと思われるかも知れないが、RadioGroupやGroupBoxでは見栄え的にイマイチで、細かな制御も困難。たとえば、以下のような場合、RadioGrouopやGroupBox等では実現困難。MainMenu/PupupMenuでも@以外は無理。

@選択項目をラジオボタンではなく、文字色/背景色を変えて表示したい⇒
A↑↓キーだけでなく、Ctrl+E/Ctrl+Xでも項目を選択したい
B項目名とは無関係のキーをショートカットキーとして設定したい

RadioButton自体はキー入力をフックできるので、その気になれば@〜Bも実現不可能ではない。しかし、個別のRadioButtonごとにキー操作のイベントハンドラを設定するのはスマートとは言えない。たとえ1つのイベントハンドラにまとめたとしても、汎用性は著しく落ちる。特に、選択項目数が動的に変化する場合など、処理は相当に面倒臭くなる。やはり、個別項目よりも1つ上の次元でのキー入力処理が望ましい。また、RadioButtonもButtonも外観の変更はほぼ不可能で、これらを使用するのなら、デフォルトのデザインを受け入れざるをえない。

で、PanelとLabelを組み合わせて@〜Bを実現しようと思ったのだが、問題はキー入力のフック。前述のようにPanelやGropuBox、Bevelなどには、キー入力をフックする機能(OnKeyPress/OnScan)がないので、Form1のキー入力を利用する事になるのだが(Form1OnScan等)、それでは拾えないキーが存在する。たとえば、Panelをフォーカスした状態でカーソルキーを押すと、Form1OnScanは実行されず、フォーカスが別コントロールに移動してしまうorz この現象はちょっと回避できそうにない。

このような場合、キー入力をフックするためのダミーコントロールを使用すると良い。例えば、TListBox型のdmyBoxをフォーム上に配置し、「Visible:=False」で見えなくしておく。また、Panel上のキー入力処理はdmyBoxのOnScan/OnKeyPressイベントハンドラに書いておく。で、Panelの表示(選択項目の変更)をキーで操作するときは、「ActiveControl:=dmyBox」として、フォーカスをdmyBoxに移せばよい。dmyBoxがキー入力を受け取り、dmyBoxOnScan/dmyBoxOnKeyPressがPanel上の表示を制御する。

なお、ダミーコントロールは、OnScan/OnKeyPressさえあれば、TListBox以外でも良さそうなものだが、入力するキーによってOnScanが実行されないこともある。と言うか、TForm1でカーソルキーが拾えなかったのがそもそもの発端。恐らく、他のコントロールでも、特定キーを拾えない現象は発生するだろう。TLitBoxは比較的広くキーが拾えるコントロールとして重宝している。


【Sibylのお部屋目次】 【ホーム】