独自に作成したカーソルを使いたい
Tip
VCL にはあらかじめ 21個のカーソルが用意されていて Screen 変数の Cursors
プロパティ に登録されています。これ以外のカーソルを使いたい場合は、Cursors
プロパティ にカーソルを登録すれば OKです。例えば、フォームのカーソルを独自に定義したカーソルに変えたい場合は、まずリソースファイル(例えば
NewCursor.res) を Image Editor で作り、その中にカーソルリソース(例えば FORMCORSOR)を定義します。そして、ユニットファイルやプロジェクトソースの適当なところに
{$R NewCursor.res}
を挿入し、フォームの OnCreate ハンドラなどで
Procedure TForm1.FormCreate(Sender: TObject);
begin
Screen.Cursors[1] := LoadCursor(MainInstance, 'FORMCUSUR');
Self.Cursor := 1;
end;
とすれば、カーソルをフォーム上に持ってくると、カーソルの形状が独自に定義したものに変わります。
解説
上の説明は教科書通りなので、さらにヘルプやマニュアルに書いてないことを追加説明します。
まず、 Cursor プロパティ の値 crDefault の意味ですが、これは実はデフォルトのカーソルを表します。これはクラスカーソルなど、コントロール自身が持っているカーソルを表します。例えばメモコントロールでは I-Beam です。Cursor
プロパティ を crDefault 以外に変更すると Cursor プロパティ の指示するカーソルが優先されます。
次に、表示されるカーソルが決定されるアルゴリズムを説明します。以下のようになります。
- もし、Screen 変数の Cursor プロパティ が crDefault ではないなら、Screen.Cursor が採用される。
- もし、Screen.Cursor が crDefault で、カーソル位置に有るコントロールが ウィンドウコントロールなら、その Cursor
プロパティ が採用される。
- もし、Screen.Cursor が crDefault で、カーソル位置に有るコントロールが グラフィックコントロール(ウィンドウハンドルを持たないコントロール)なら、その Cursor
プロパティ が crDefalt でないなら グラフィックコントロールの Cursor
プロパティ が採用される。そうでないなら、親のウィンドウコントロールの Cursor
プロパティ が採用される。
以上の処理の結果、カーソルが crDefault なら、クラスカーソルが表示されます。
結構複雑で変な規則であることがお判りかと思います。例えばフォームのカーソルを Tip のように変えて、フォーム上のボタンとイメージコントロールの Cursor
プロパティ を共に crDefault のままにしておくと、イメージコントロール上ではフォームの Cursor
プロパティ で指定したカーソルが使われるのに、ボタン上ではクラスカーソル(通常矢印)になってしまいます。明らかに規則のバランスが取れていないので、多分ロジックを入れ忘れたんだと思います
最後に Screen 変数のカーソル配列の使い方を説明します。これも結構変わっています。
| Screen.Cursors[0](つまり Screen.Cursors[crDefault])への代入はデフォルトのカーソルハンドルの指定を意味します。つまり、Cursors
プロパティ を参照する時、カーソルが未登録のインデックスを指定すると、このカーソルハンドルが返ります。Screen.Cursor[crDefalt] にカーソルハンドルを代入しても、表示されるカーソルが変わらないことに注意してください。crDefault は上記のようにクラスカーソルを表します。
| Screen.Cursor[-1] から ScreenCursors[-17] 、つまり、インデックス値が crNone から crSQLWait の部分は VCL があらかじめ用意してくれているカーソルですが、実はこれも入れ替えることが出来ます。例えば砂時計カーソルを独自のものにしたいのなら
Screen.Cursors[crHourGlass] にユーザ定義のカーソルハンドルを代入すればOKです。
| Screen.Cursors の要素にカーソルハンドルを代入すると、そこに有った古いカーソルは破棄されます。但し、0を代入するとその要素が未登録状態に戻るのではなく、矢印のカーソル(crArrow と同じ物)がそこに登録されます。
| Screen.Cursors 配列は実は配列ではなくリンクトリストとして実装されています。従って、Screen.Cursors[10000] :=
LoadCursor(HInstance, 'MyCursor'); などとしてもメモリの消費はほとんどありません。またインデックス値は TCursor = -32768..32767 なので、6万個以上のカーソルを登録できます。但し、あまりたくさん登録すると、TScreen はカーソルのインデックスをリニアに探索するので、カーソルの表示に非常に時間がかかるようになってしまいます。数10個程度にしておいた方が良いでしょう。
| Screen.Cursors に登録されたカーソルは VCL が破棄します。アプリケーション側で破棄する必要はありません。
| | | | |
|