Golang で winapi を叩く練習として GetWindowText を呼び出してみた
最初は AllenDang/w32 を検討していたが、手元の Windows 7 で動かなかった& なんか fork してる別ソース使わないとダメ(or 自分でソース直す)っぽかった、で面倒だったので、一度自分で書いてみることに。
ソース
package main import ( "fmt" "syscall" "unsafe" ) func main() { user32, err := syscall.LoadDLL("user32.dll") if err != nil { panic(err) } defer user32.Release() procGetForegroundWindow, err := user32.FindProc("GetForegroundWindow") if err != nil { panic(err) } hwnd, _, _ := procGetForegroundWindow.Call() procGetWindowTextLength, err := user32.FindProc("GetWindowTextLengthW") if err != nil { panic(err) } textLength, _, _ := procGetWindowTextLength.Call(hwnd) textLength = textLength + 1 procGetWindowText, err := user32.FindProc("GetWindowTextW") if err != nil { panic(err) } // LPTSTR が *uint16 buf := make([]uint16, textLength) procGetWindowText.Call(hwnd, uintptr(unsafe.Pointer(&buf[0])), textLength) text := syscall.UTF16ToString(buf) fmt.Println(text) }
解説
Golang 側で winapi を叩く仕組みがあるので、これに従う。
基本的には syscall モジュールを使って DLL ロードして、そっから Proc をロードして、んで Call するという流れ。
- winapi の構造体や型の軍団が猛威を奮う
- 自分で MSDN 見て書いてもいいが、 w32/typedef.go この辺を見るのが楽
- []int の string 化は
syscall.UTF16ToString(buf)
感想
- winapi 側の型とか構造体とか作り込むのだるそう。w32/typedef.go まるごとパクろうかなぁ。ライセンスは BSD
- まずは小さなツール作成(で使う Proc のみを最小限定義)するのがよさそうか。少しずつ作って慣れる作戦
- あまり外部には頼りたくない……(w32 含めあまり栄えてない感じだし)
参考
- goでWindows APIを実行する覚書 - Qiita
- windows - GoDoc
- 参考にできそうなソース: github.com/AllenDang/w32/