WisdomSoft - for your serial experiences.

6.7 カーソル

マウスカーソルをプログラムから操作する方法を紹介します。プログラムからカーソルを変更したり、カーソルを画像として描画したりできます。

6.7.1 カーソルを変更する

マウスなどのポインティングデバイスで制御される座標を表しているのがカーソルです。一般的には、カーソルはシステムが用意した既定のカーソルを使いますが、何らかの処理をまっている間は砂時計カーソルに変更するなど、コントロールのアクションを連想させるようなカーソルを表示すると便利になります。

カーソルは、アイコンのように専用のツールを使って独自のカーソルを作成することができます。カーソルは .cur という拡張子をもつ小さな2色のイメージデータです。

図1 カーソルファイルの編集
図1 カーソルファイルの編集

カーソルは System.Windows.Forms.Cursor クラスで表されます。Icon クラスと同様に、カーソルはビットマップと同様のイメージデータですが Image クラスと継承関係はありません。

System.Windows.Forms.Cursor クラス
System.Object
    System.Windows.Forms.Cursor
[Serializable]
public sealed class Cursor : IDisposable, ISerializable

カーソルはアイコンに表によく似た性質の小さいイメージですが、ホットスポットと呼ばれるカーソルアイコン上の中心点を設定する情報が含まれている点でアイコンと異なります。カーソルイメージのサイズに関係なく、マウスクリックが行われる座標は1点のみです。クリックが行われたとき、カーソルアイコンのどの部分を入力座標として設定するのかを表す情報がホットスポットなのです。一般的な矢印アイコンの場合は、矢印の先がホットスポットとして設定されていますが、十字アイコンの場合は線が交差している中心がホットスポットとなります。

ディスク上の .cur カーソルファイルを読み込んで Cursor インスタンスを生成するには次の Cursor コンストラクタを使います。

Cursor クラスのコンストラクタ
public Cursor(string fileName)
public Cursor(Stream stream)

fileName パラメータにはカーソルファイルのパスを、stream パラメータにはカーソルファイルへのストリームを指定します。ここで指定するデータは .cur カーソルファイル形式のものでなければなりません。アニメーションカーソルと呼ばれる .ani 形式はサポートされていません。

システムで使われている現在のマウスカーソルは Cursor クラスの静的な Current プロパティで設定・取得することができます。GUI 上に表示されている(ユーザーが操作している)カーソルを任意の Cursor オブジェクトに変更するには Current プロパティに Cursor を設定します。

Cursor クラス Current プロパティ
public static Cursor Current { get; set; }

ただし、Current に別の Cursor オブジェクトを設定しても、その設定が永続的なものになると考えてはいけません。ユーザーがカーソルを移動させたり、何らかの入力イベントを発生させたり、別のウィンドウ上に移動した時点で、カーソルは他のプログラムやシステムによって変更されてしまいます。そのため、カーソルと任意のカーソルアイコンに変更するには、何らかのイベント発生に従って常に Current プロパティに目的の Cursor オブジェクトを設定してください。

コード1
using System.Drawing;
using System.Windows.Forms;

public class Test : Form
{
	private Cursor cursor;
	protected override void OnMouseMove(MouseEventArgs e)
	{
		base.OnMouseMove (e);
		if (cursor == null) cursor = new Cursor("test.cur");
		Cursor.Current = cursor;
	}

	static void Main() 
	{
		Application.Run(new Test());
	}
}
実行結果
コード1 実行結果

コード1は、実行ファイルと同じディレクトリに配置されている test.cur ファイルを実行時に読み込み Cursor インスタンスを生成しています。システムの現在のカーソルを、生成した Cursor オブジェクトのイメージに変更するには、Current プロパティに設定しなければなりません。ただし、これは一度設定しても、何らかのイベントが発生した時点ですぐに他のカーソルに変更されてしまいます。

マウスカーソルのイメージを一定期間維持するには、マウスカーソルを変更する必要のある何らかのイベントが発生している間、常に Current プロパティに任意の Cursor オブジェクトを設定し続ける必要があります。

6.7.2 コントロールのカーソルを設定

すべてのコントロールは、コントロール上にマウスカーソルが入ったときに表示するカーソルを設定することができます。カーソルを変更するには Control クラスの Cursor プロパティを設定します。

Control クラス Cursor プロパティ
public virtual Cursor Cursor { get; set; }

Cursor プロパティにカーソルを設定することで、そのコントロール上にマウスカーソルが移動した時点で自動的に設定しているカーソルに変更されます。コントロール上でカーソルを変更したいだけならば、Cursor クラスの Current プロパティを設定するのではなく、Control クラスの Cursor プロパティに任意のカーソルを設定するべきです。

コード2
using System.Drawing;
using System.Windows.Forms;

public class Test
{
	static void Main() 
	{
		Form form = new Form();
		form.Cursor = new Cursor("test.cur");
		Application.Run(form);
	}
}

コード2を実行して表示されたフォームにマウスカーソルを移動させると、ディスクから読み込んだカーソルイメージに変更されることが確認できます。

6.7.3 カーソルを描画する

カーソルは本来、ポインティングデバイスが操作しているシステムのマウスカーソルを制御するためのものですが、Graphics オブジェクトを使ってデバイスに出力することができます。カーソルをイメージとして描画するには Cursor クラスの Draw() メソッド、または DrawStretched() メソッドを使います。Draw() メソッドの場合は指定した矩形内にカーソルを描画しますが伸縮は行いません。これに対して、DrawStreatched() メソッドは領域に伸縮して描画します。

Cursor クラス Draw() メソッド
public void Draw(Graphics g, Rectangle targetRect)
Cursor クラス DrawStretched() メソッド
public void DrawStretched(Graphics g, Rectangle targetRect)

g には、描画対象のデバイスを参照している Graphics オブジェクトを指定します。targetRect に、カーソルを描画する領域を表す Rectangle オブジェクトを指定します。

領域を指定するときに、カーソルのサイズを動的に取得する必要あるでしょう。カーソルのサイズは Cursor クラスの Size プロパティから取得することができます。

Cursor クラス Size プロパティ
public Size Size { get; }

Size プロパティは、カーソルイメージの幅と高さを格納している Size オブジェクトです。通常、カーソルファイルは 32 × 32 ピクセルの2色ビットマップですが、それを前提として 32 という数値リテラルを与えるよりも、Size プロパティから動的に取得した方が柔軟性のある正しいプログラムです。

コード3
using System.Drawing;
using System.Windows.Forms;

public class Test : Form
{
	private Cursor cursor;
	protected override void OnPaint(PaintEventArgs e)
	{
		base.OnPaint (e);
		if (cursor == null) cursor = new Cursor("test.cur");

		int width = cursor.Size.Width;
		int height = cursor.Size.Height;
		cursor.Draw(
			e.Graphics,
			new Rectangle(0, 0,width, height)
		);
		cursor.DrawStretched(
			e.Graphics,
			new Rectangle(width, 0, 200, 200)
		);
	}

	static void Main() 
	{
		Application.Run(new Test());
	}
}
実行結果
コード3 実行結果

コード3は、読み込んだカーソルイメージをウィンドウに描画するプログラムです。最初の描画は Draw() メソッドは伸縮を行わず、単純にカーソルイメージをそのまま描画します。次の DrawStretched() メソッドでは、幅と高さを 200 ピクセルに指定した Rectangle オブジェクトを指定しているため、カーソルが領域に合わせて伸縮されて表示されます。