(AutoHotkey)(POINT構造体 の 値を取得してみる 編)
元々 AutoHotkeyには MouseGetPosがあるので マウスカーソルの位置を取得する術はあるわけですが
「あくまで シンプルな例を提示する」のが 今回の目的なので あえて API関数のGetCursorPosを使う事にします
API関数のGetCursorPos は 呼び出すと POINT構造体に 値をセットする仕様なわけですが
AutoHotkeyには 構造体を定義する方法がありませんので
他の言語で 一般的に行われているような 構造体へのアクセスの仕方は 今のバージョン(v1.0.47.05)では 出来ません
早く実装されればいいんですけどねぇ 笑)、 みんなで せかしまくるんだ!! 笑)
というワケなので 構造体のような 代替品を 用意してあげる必要があるわけなんですが
今回は 構造体のようなものを作るために AutoHotkey の VarSetCapacity関数を利用します
この関数は 固定長サイズの変数を作ったりするものです
具体的に説明すると 仕様は VarSetCapacity(<変数名>, <確保を希望するバイト数>, <変数を埋め尽くす値(0〜255)>) で
戻り値は 実際に確保できた領域のサイズになります
では 実際に POINT構造体のようなものを 作ってみるわけですが
まず POINT構造体 の構造を知る必要がありますね
いろんな所で 調べてみると POINT構造体の定義は 以下の感じですよね
よって 8バイトのサイズの 変数を用意してあげれば なんとかなるわけです
さっきの VarSetCapacity関数を使って 表現してみると
今度は GetCursorPosの定義を見てみると
戻り値 は BOOL型ですし 成功時 0以外 失敗時は 0 という 典型的なパターンでしょうね
ということで ここでの問題は 「どうやって アドレスを渡すのか?」ということですが
実は 変数のアドレスを渡すときは 変数名の前に & をつけてやるだけでOKです
とはいえ ちゃんと 書きこまれたにしても その値を利用できなければ 意味がありませんよね
そこで AutoHotkey で用意されている NumGet と NumPut という 関数を 利用する事にします
今回は 値を取得するわけなので NumGet関数を使います、 NumPut関数 については また後日にでも書きます
NumGet関数は 変数 と オフセット値 と データ型 を 指示する事によって
指定した変数のアドレス+オフセット値 から始まるデータを 指示したデータ型で 読み取ります
ん〜ちょっと混乱しそうですね 笑)、 まぁ 使い方を見れば なんとなく分かるでしょう
つづいて yメンバ のアドレスは bufPOINTのアドレスよりも 4バイト後(xメンバのサイズ分)なので 4 になります
「あくまで シンプルな例を提示する」のが 今回の目的なので あえて API関数のGetCursorPosを使う事にします
API関数のGetCursorPos は 呼び出すと POINT構造体に 値をセットする仕様なわけですが
AutoHotkeyには 構造体を定義する方法がありませんので
他の言語で 一般的に行われているような 構造体へのアクセスの仕方は 今のバージョン(v1.0.47.05)では 出来ません
早く実装されればいいんですけどねぇ 笑)、 みんなで せかしまくるんだ!! 笑)
というワケなので 構造体のような 代替品を 用意してあげる必要があるわけなんですが
今回は 構造体のようなものを作るために AutoHotkey の VarSetCapacity関数を利用します
この関数は 固定長サイズの変数を作ったりするものです
具体的に説明すると 仕様は VarSetCapacity(<変数名>, <確保を希望するバイト数>, <変数を埋め尽くす値(0〜255)>) で
戻り値は 実際に確保できた領域のサイズになります
では 実際に POINT構造体のようなものを 作ってみるわけですが
まず POINT構造体 の構造を知る必要がありますね
いろんな所で 調べてみると POINT構造体の定義は 以下の感じですよね
[]typedef struct tagPOINT {[] []LONG x;[] []LONG y;[] []} POINT;[]つまり POINT構造体とは 32ビット(4バイト)の x と y という 二つのメンバを持った 連続した 8バイトの変数という事になります
よって 8バイトのサイズの 変数を用意してあげれば なんとかなるわけです
さっきの VarSetCapacity関数を使って 表現してみると
[]VarSetCapacity(bufPOINT, 8, 0x00)[]これで 8バイト分の 0x00 で埋め尽くされた bufPOINT という 変数が用意された事になります
今度は GetCursorPosの定義を見てみると
[]BOOL GetCursorPos([] []LPPOINT lpPoint [] []);[]POINT構造体の アドレス を GetCursorPos に 渡してあげれば良さそうですね
戻り値 は BOOL型ですし 成功時 0以外 失敗時は 0 という 典型的なパターンでしょうね
ということで ここでの問題は 「どうやって アドレスを渡すのか?」ということですが
実は 変数のアドレスを渡すときは 変数名の前に & をつけてやるだけでOKです
[]DllCall("user32.dll\GetCursorPos", "UInt", &bufPOINT)[]これで ちゃんと bufPOINT に 座標が書き込まれたはずです
とはいえ ちゃんと 書きこまれたにしても その値を利用できなければ 意味がありませんよね
そこで AutoHotkey で用意されている NumGet と NumPut という 関数を 利用する事にします
今回は 値を取得するわけなので NumGet関数を使います、 NumPut関数 については また後日にでも書きます
NumGet関数は 変数 と オフセット値 と データ型 を 指示する事によって
指定した変数のアドレス+オフセット値 から始まるデータを 指示したデータ型で 読み取ります
ん〜ちょっと混乱しそうですね 笑)、 まぁ 使い方を見れば なんとなく分かるでしょう
[]BufX := NumGet(bufPOINT, 0, "Int")[] []BufY := NumGet(bufPOINT, 4, "Int")[] []MsgBox, x:%bufX% y:%bufY%[]まず bufPOINTのアドレス と xメンバ のアドレスは 同じなので オフセット値 は 0 です、 Int型で読み取らせます
つづいて yメンバ のアドレスは bufPOINTのアドレスよりも 4バイト後(xメンバのサイズ分)なので 4 になります
[]; POINT構造体もどきを作成[] []; MsgBoxで 実際に確保できたサイズを表示させます[] []; 8バイトくらいなら 別に何の問題も無く 成功するでしょう[] []MsgBox,% VarSetCapacity(bufPOINT, 8, 0x00)[] []; API関数に POINT構造体もどきの 変数の アドレスを渡します[] []DllCall("user32.dll\GetCursorPos", "UInt", &bufPOINT)[] []; x メンバの値を bufX に 代入[] []bufX := NumGet(bufPOINT, 0, "Int")[] []; y メンバの値を bufY に 代入[] []bufY := NumGet(bufPOINT, 4, "Int")[] []; MsgBox で マウスカーソルの 座標を表示[] []MsgBox, x:%bufX% y:%bufY%[]