Skip to content

golang调用Windows API

Published: at 08:38 AM | 2 min read

golang还能调用Windows API非常有意思,下面写了一个golang换壁纸的demo。 准备了两张bmp格式的图片,没三秒钟换一下壁纸。

主要是先通过dll获取里面api,要注意api参数的写法,dll用完了要释放句柄,这里我用缓存把api缓存起来不必每次调用都去dll里加载。

代码:

package main

import (
	"log"
	"syscall"
	"time"
	"unsafe"
)

var ApiList = map[string][]string {
	"user32.dll": []string {
		"MessageBoxW",
		"SystemParametersInfoW",
	},
	"kernel32.dll": []string {

	},
}

var ProcCache map[string]*syscall.Proc

func init() {
	ProcCache = make(map[string]*syscall.Proc)
	for dllName, apiList := range ApiList {
		d, err := syscall.LoadDLL(dllName)
		if err != nil {
			panic(err)
		}

		for _, name := range apiList {
			api, err := d.FindProc(name)
			if err != nil {
				syscall.FreeLibrary(d.Handle)
				panic(err)
			}
			ProcCache[name] = api
		}
		syscall.FreeLibrary(d.Handle)
	}
}

func WinCall(name string, a ...uintptr) {
	if api, ok := ProcCache[name]; ok {
		_, _, err := api.Call(a...)
		if err != nil {
			log.Println(err)
		}
	} else {
		log.Println("api not found, name:", name)
	}
}

func IntPtr(n int) uintptr {
	return uintptr(n)
}

func StrPtr(s string) uintptr {
	p, _ := syscall.UTF16PtrFromString(s)
	return uintptr(unsafe.Pointer(p))
}

func ShowMessage(title, text string) {
	WinCall("MessageBoxW", IntPtr(0), StrPtr(text), StrPtr(title), IntPtr(0))
}

func SetWallpaper(bmpPath string) {
	WinCall("SystemParametersInfoW", IntPtr(20), IntPtr(0), StrPtr(bmpPath), IntPtr(3))
}

func main() {
	for i := 0; i < 10; i++ {
		SetWallpaper("E:\\CppProject\\WindowsProject1\\test.bmp")
		time.Sleep(3 * time.Second)
		SetWallpaper("E:\\CppProject\\WindowsProject1\\test2.bmp")
		time.Sleep(3 * time.Second)
	}
}