今回はマウスカーソルの変更をしてみます。特に、時間のかかる計算などのために一時的にカーソルをビジー表示(デフォルトでは砂時計カーソル)にする場合の手順について説明することにします。
一時的にカーソルをビジー状態に変更するための手順は以下のようになります。
今回はあくまで一時的にマウスカーソルの表示を変更するだけです。アプリケーションの新しいマウスカーソルを設定するということはできません。これは、後で述べる理由により、マウスカーソル変更中に wait や await や stop を実行することができないためです。アプリケーション固有のマウスカーソルの設定や、カーソル変更中にスクリプトで wait や await や stop を実行したい場合の方法は、次回に説明します。
マウスカーソルは、アイコンの場合と同じく、Windowsユーザーオブジェクトの1つである『カーソルオブジェクト』として扱われることになります。したがって、マウスカーソルを操作するためには、カーソルオブジェクトを作成して、そのハンドルを取得しなければならないことになります。
今回使用するマウスカーソルは、システム定義のカーソルです。システム定義カーソルオブジェクトを作成して、そのハンドルを取得するためには、 LoadCursor 関数を呼び出します。
HCURSOR LoadCursorA(
HINSTANCE hInstance, // インスタンスハンドル
PCSTR pCursorName // リソース名/リソースID
);
hInstance パラメータに 0 (NULL) を、 pCursorName パラメータには決められた値を指定することでシステム定義カーソルをロードできます。砂時計カーソルをロードするには pCursorName パラメータに 32514 (IDC_WAIT) を指定します。
LoadCursor 関数は戻り値としてロードされたマウスカーソルのハンドルを返します。
ところで、この LoadCursor 関数によって作成されたカーソルオブジェクトは、前回作成されたアイコンオブジェクトなどとは少し性質が異なります。 LoadCursor 関数によって作成されたカーソルオブジェクトは『共有カーソル(shared cursor)』と呼ばれるもので、以前に作成したのと同じカーソルリソースからカーソルオブジェクトを作成しようとしたときに、新しくオブジェクトを作成するのではなく、以前に作成されたオブジェクトを共有するようにしているのです。したがって、 LoadCursor 関数からは以前のカーソルと同じハンドルが返されます。このような動作を行なうことにより、新しいオブジェクトのための余分なメモリ領域と、作成のためのオーバーヘッドを少なくしているのです。
共有カーソルは、1つのプロセスだけでなく、すべてのプロセスで共有されるようになっています。そのため、オブジェクトが必要なくなったとしても、明示的にオブジェクトを削除する必要がなくなるのです。前回作成されたアイコンは『共有アイコン』ではなかったため破棄していましたが、今回 LoadCursor 関数で取得されたカーソルは破棄する必要がありません。
マウスカーソルのハンドルを取得できたら、次に、マウスカーソルを変更します。 マウスカーソルを変更するためには SetCursor 関数を呼び出します。
HCURSOR SetCursor(
HCURSOR hCoursor // カーソルハンドル
);
hCoursor パラメータには、先ほど取得したカーソルのハンドルを指定します。
マウスカーソルを元に戻すには、先ほどの手順において、標準矢印カーソルをロードして指定することで行なうことができます。 LoadCursor 関数の pCursorName パラメータに 32512 (IDC_ARROW) を指定することで標準矢印カーソルのハンドルが取得できるので、これを SetCursor 関数で指定すれば元に戻ります。
今回説明した方法では wait や await 、 stop のいずれかの命令を実行することでマウスカーソルが元に戻ってしまいます。なぜこれらの命令を実行すると、カーソルが元に戻ってしまうのでしょう?
これは、 wait や await や stop を実行することによって、ウィンドウメッセージを処理する機会が与えられることによります。マウスカーソルの移動やシステム命令実行などを行なうとき、システムはウィンドウに WM_SETCURSOR メッセージを送ることになっています。このメッセージが送られると、メッセージを処理するデフォルトウィンドウプロシージャは、ウィンドウ作成時にHSP内部で登録されたウィンドウクラスで指定されているマウスカーソルに自動的に変更してしまうのです。これは、 wait や await や stop 命令によって WM_SETCURSOR メッセージが処理され、マウスカーソルが元に戻ってしまうことを意味します。
これによってマウスカーソルが元に戻らないようにするには、デフォルトウィンドウプロシージャに stop 命令によって WM_SETCURSOR メッセージを処理させないようにする方法と、ウィンドウクラスに設定されているマウスカーソルそのものを変更してしまう方法とが考えられます。前者はスクリプト上で行なうことはできませんが、後者(ウィンドウクラスのカーソル変更)は実現できます。これは次回に説明します。
さて、実際にスクリプトを書いてみます。
#include "llmod.as"
#module ;############ カーソル変更モジュール ####################
;===============================================================
; カーソルをシステム定義カーソルに変更
; SetSystemCursor n1
; n1 : カーソルの種類(32512:標準 32514:砂時計)
;===============================================================
#deffunc SetSystemCursor int
mref type, 0 ;カーソルの種類
; システム定義カーソルのハンドル取得
pm = 0, type
dllproc "LoadCursorA", pm, 2, D_USER@
hCursor = dllret@ ; カーソルハンドル
; カーソル変更
dllproc "SetCursor", hCursor, 1, D_USER@
return
#global ;############# モジュール終わり ########################
button "処理", *lb_work
stop
*lb_work
mes "処理中..."
; 砂時計カーソルに変更
SetSystemCursor 32514
; 時間のかかる処理
repeat 5000000 : a++ : loop
mes "終了"
; 元のカーソルに戻す
SetSystemCursor 32512
stop