マウスカーソルを変更してみる ACT-2

今回はアプリケーションのマウスカーソルの変更をしてみます。ウィンドウクラスで設定されているマウスカーソルを別のものに置きかえることによって、アプリケーション固有のマウスカーソルを使用できるようにしてみます。

マウスカーソルの変更

前回説明したように、ただ単に SetCursor 関数でマウスカーソルを変更しただけでは、 waitawaitstop が実行されたときにマウスカーソルがウィンドウクラスで設定されているものに戻ってしまうため、これだけではアプリケーション固有のカーソルを実現することはできませんでした。そこで、今回はウィンドウクラスの設定そのものを書き換えて、マウスカーソルを変更してみます。

また、前回はシステム定義のマウスカーソルだけでしたが、今回はカーソルファイル(.cur や .ani)を使ってみましょう。

今回の手順は以下のようになります。

  1. LoadCursorFromFile 関数でカーソルファイルからカーソルをロードする。
  2. SetClassLong 関数でウィンドウクラスの設定を書きかえる。
  3. SetCursor 関数でマウスカーソルを変更する。

カーソルファイルからのロード

前回やったようなシステム定義カーソルを使用することもできますが、今回使用するマウスカーソルは、カーソルファイルとして準備したものを使用することにします。カーソルをファイルから取得するためには、 LoadCursorFromFile 関数を呼び出します。

HCURSOR LoadCursorFromFileA(
    PCSTR pFileName  // カーソルファイル名
);

pFileName パラメータには、カーソルファイルのファイル名を表す文字列のアドレスを指定します。このファイルは .cur ファイル形式か、.ani ファイル形式でなくてはなりません。この関数は戻り値として、ロードしたカーソルのハンドルを返します。

前回と同じく、この関数で取得されたカーソルも共有カーソルです。したがって、明示的に破棄する必要はありません。

ウィンドウクラスのカーソル設定の変更

次に、ウィンドウクラスのマウスカーソルに関する設定を変更します。そのためには SetClassLong 関数を呼び出します。

LONG SetClassLongA(
    HWND  hWnd,      // ウィンドウハンドル
    int   nIndex,    // 変更するデータの指定
    LONG  dwNewLong  // 新しい値
);

hwnd パラメータにはウィンドウハンドルを指定します。ここで指定したウィンドウが属するウィンドウクラスのデータを書き換えます。

マウスカーソルの設定書きかえるためには、 nIndex パラメータに -12 (GCL_HCURSOR) を指定し、 dwNewLong パラメータに新しいカーソルのハンドルを指定します。

マウスカーソル変更

以上の方法でウィンドウクラスのカーソルが変更されましたが、このままでは次に WM_SETCURSOR メッセージが送られてこれが処理されるまでマウスカーソルの変更が反映されません。したがって、直ちにマウスカーソルを反映させるために、前回と同じく SetCursor 関数でマウスカーソルを変更しておきます。

以上でマウスカーソルが変更されます。

サンプルスクリプト

さて、実際にスクリプトを書いてみます。

サンプルスクリプト main.as

    #include "llmod.as"

    #module ;############ カーソル変更モジュール ####################

    ;===============================================================
    ; アプリケーションカーソルを指定されたファイルのカーソルに変更
    ; SetAppCursor  s1
    ;     s1 : カーソルファイル名(.cur または .ani)
    ;   stat : 0:成功, 1:ファイルからのロードに失敗
    ;===============================================================
    #deffunc SetAppCursor str
    mref setfilename, 32    ; カーソルファイル名
    mref bmscr, 67          ; BMSCR構造体
    mref stt, 64            ; stat

    sdim filename, 260
    filename = setfilename      ; いったん別の変数に移す

    ; カーソルファイルからロード
    getptr pm, filename
    dllproc "LoadCursorFromFileA", pm, 2, D_USER@
    hCursor = stat          ; カーソルハンドル
    if hCursor == 0 : stt = 1 : return

    ; ウィンドウクラスのデータ変更
    pm.0 = bmscr.13         ; ウィンドウハンドル
    pm.1 = -12              ; GCL_HCURSOR
    pm.2 = hCursor          ; カーソルハンドル
    dllproc "SetClassLongA", pm, 3, D_USER@

    ; カーソル変更
    dllproc "SetCursor", hCursor, 1, D_USER@
    stt = 0
    return

    #global ;############# モジュール終わり ########################

    objsize winx
    button "カーソル変更", *lb_change_cursor
    stop

*lb_change_cursor
    dialog "cur;*.ani", 16, "カーソルファイル"
    if stat == 0 : stop

    ; マウスカーソルを変更
    SetAppCursor refstr
    stop