戻る ホーム 上へ 進む

独自に作成したカーソルを使いたい

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 プロパティ の指示するカーソルが優先されます。

次に、表示されるカーソルが決定されるアルゴリズムを説明します。以下のようになります。

  1. もし、Screen 変数の Cursor プロパティ が crDefault ではないなら、Screen.Cursor が採用される。
  2. もし、Screen.Cursor が crDefault で、カーソル位置に有るコントロールが ウィンドウコントロールなら、その Cursor プロパティ が採用される。
  3. もし、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 が破棄します。アプリケーション側で破棄する必要はありません。

 

戻る ホーム 上へ 進む

inserted by FC2 system