GoでWin32APIのMessageBoxを呼ぶ
直接呼ぶパターン
syscall と unsafe を使用すると user32.dll の MessageBoxW を直接呼べる
・・・があんまり登場シーンはなさそう
code:cmd/sample1/main.go
package main
import (
"fmt"
"syscall"
"unsafe"
)
func MessageBox(hwnd uintptr, text, caption string, flags uint) int {
ptrText, err := syscall.UTF16PtrFromString(text)
if err != nil {
return 0
}
ptrCaption, err := syscall.UTF16PtrFromString(caption)
if err != nil {
return 0
}
ret, _, _ := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW").Call(
uintptr(hwnd),
uintptr(unsafe.Pointer(ptrText)),
uintptr(unsafe.Pointer(ptrCaption)),
uintptr(flags),
)
return int(ret)
}
func main() {
text := "Hello, world!"
caption := "Sample"
if err := MessageBox(0, text, caption, 0); err != 0 {
fmt.Println(err)
}
}
ラッパーライブラリを使うパターン
いくつかラッパーが存在する。ここでは sys を使用する。
unsafe は表面上でなくなったが syscall で string の uint64 のポインタを取得する必要があるなどなど癖はある
code:cmd/sample2/main.go
package main
import (
"fmt"
"syscall"
"golang.org/x/sys/windows"
)
func MessageBox(hwnd uintptr, text, caption string, flags uint) int {
ptrText, err := syscall.UTF16PtrFromString(text)
if err != nil {
return 0
}
ptrCaption, err := syscall.UTF16PtrFromString(caption)
if err != nil {
return 0
}
ret, err := windows.MessageBox(0, ptrText, ptrCaption, 0)
if err != nil {
return 0
}
return int(ret)
}
func main() {
text := "Hello, world!"
caption := "Sample"
if err := MessageBox(0, text, caption, 0); err != 0 {
fmt.Println(err)
}
}
Wineで動作させる場合
https://gyazo.com/258ff1f2d177249ba17ee5415cd1193d
code:sh
# Wineのインストール
brew tap homebrew/cask-versions
brew install --cask --no-quarantine wine-stable
# go mod を初期化
go mod init <REPOURL>
# サンプルコードを記入
vim ./main.go
# モジュールを解決
go mod init
# PE 64bit を出力
GOOS=windows GOARCH=amd64 go build -o main.exe ./main.go
# PE 64bit を実行
wine64 ./main.exe
関連