golang对win窗口的操作有哪些

发布时间:2024-11-21 20:58:15

Golang是一种目前非常流行的编程语言,也被广泛应用于Windows应用程序开发。在Golang中,我们可以使用一系列的库和方法来操作Win窗口,从而实现各种功能和交互。本文将介绍一些常用的Golang对Win窗口的操作方式。

获取窗口句柄

要操作窗口,首先需要获取其句柄,即handle。在Golang中,我们可以使用`user32`库中的`FindWindow`函数来获取指定窗口标题或类名的句柄。

import (
    "fmt"
    "syscall"
    "unsafe"
)

const (
    MAX_PATH = 260
)

var (
    kernel32       = syscall.MustLoadDLL("kernel32.dll")
    procGetModuleHandle = kernel32.MustFindProc("GetModuleHandleW")
    user32         = syscall.MustLoadDLL("user32.dll")
    procFindWindow     = user32.MustFindProc("FindWindowW")
)

func GetWindowHandle(windowTitle string) (syscall.Handle, error) {
    ret, _, err := procFindWindow.Call(0, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(windowTitle))), 0)
    if ret == 0 {
        return 0, fmt.Errorf("failed to find window: %v", err)
    }
    return syscall.Handle(ret), nil
}

func main() {
    hwnd, err := GetWindowHandle("Notepad")
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("Window handle: %v\n", hwnd)
}

发送消息

获取窗口句柄后,我们就可以使用`user32`库中的`SendMessage`函数向窗口发送消息。通过指定不同的消息类型和参数,我们可以实现对窗口的不同操作。

const (
    WM_GETTEXT     = 0x000D
    WM_SETTEXT     = 0x000C
    WM_CLOSE       = 0x0010
)

func SendMessage(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) {
    user32.MustFindProc("SendMessageW").Call(
        uintptr(hwnd),
        uintptr(msg),
        wParam,
        lParam)
}

func GetWindowText(hwnd syscall.Handle) string {
    buffer := make([]uint16, MAX_PATH)
    user32.MustFindProc("GetWindowTextW").Call(
        uintptr(hwnd),
        uintptr(unsafe.Pointer(&buffer[0])),
        uintptr(MAX_PATH))
    return syscall.UTF16ToString(buffer)
}

func SetWindowText(hwnd syscall.Handle, text string) {
    user32.MustFindProc("SetWindowTextW").Call(
        uintptr(hwnd),
        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text))))
}

func main() {
    hwnd, err := GetWindowHandle("Notepad")
    if err != nil {
        fmt.Println(err)
        return
    }
    SendMessage(hwnd, WM_SETTEXT, 0, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Hello World"))))
    text := GetWindowText(hwnd)
    fmt.Printf("Window text: %s\n", text)
    SendMessage(hwnd, WM_CLOSE, 0, 0)
}

枚举窗口

除了直接指定窗口句柄,我们还可以使用`user32`库中的`EnumWindows`函数来枚举系统中所有的顶级窗口。配合`GetWindowText`函数和`SetWindowText`函数,我们可以对枚举的窗口进行更加灵活的操作。

type EnumInfo struct {
    hwnds []syscall.Handle
    keyword string
}

func EnumProc(hwnd syscall.Handle, lParam uintptr) uintptr {
    enumInfo := (*EnumInfo)(unsafe.Pointer(lParam))
    buffer := make([]uint16, MAX_PATH)
    user32.MustFindProc("GetWindowTextW").Call(
        uintptr(hwnd),
        uintptr(unsafe.Pointer(&buffer[0])),
        uintptr(MAX_PATH))
    text := syscall.UTF16ToString(buffer)
    if strings.Contains(text, enumInfo.keyword) {
        enumInfo.hwnds = append(enumInfo.hwnds, hwnd)
    }
    return 1
}

func EnumWindowsWithKeyword(keyword string) ([]syscall.Handle, error) {
    var enumInfo EnumInfo
    enumInfo.keyword = keyword
    user32.MustFindProc("EnumWindows").Call(
        uintptr(syscall.NewCallback(EnumProc)),
        uintptr(unsafe.Pointer(&enumInfo)))
    if len(enumInfo.hwnds) == 0 {
        return nil, fmt.Errorf("failed to find windows with keyword: %s", keyword)
    }
    return enumInfo.hwnds, nil
}

func main() {
    hwnds, err := EnumWindowsWithKeyword("Notepad")
    if err != nil {
        fmt.Println(err)
        return
    }
    for _, hwnd := range hwnds {
        fmt.Printf("Window handle: %v\n", hwnd)
        SetWindowText(hwnd, "Hello World")
        text := GetWindowText(hwnd)
        fmt.Printf("Window text: %s\n", text)
        SendMessage(hwnd, WM_CLOSE, 0, 0)
    }
}

通过以上操作,我们可以在Golang中对Windows窗口进行各种操作,包括获取窗口句柄、发送消息以及枚举窗口等。这些操作使得我们可以灵活地控制和交互Windows应用程序,从而提高了开发效率和用户体验。

相关推荐