dongnai8013 2017-07-02 17:11
浏览 98
已采纳

在Go for Windows中获取窗口几何

I want to create a tool with Go that lets me resize multiple windows on my screen. As an example lets assume that I want to find my Firefox window and my Atom (text editor) window and place them, so that they take up exactly half of my screen (FF left, Atom right).

So far I realized, that I need to use the Windows API for that. I created a method that gives me all handles and the titles of all windows, but I'm struggling with geometry information. I understand that the api call GetWindowRect will help, but how can I get the information out of a pointer to a rect?

Follow up question 1: what other information can I get about the windows? Follow up question 2: How do I resize the window so that it takes exactly half my screen size? I guess, I need another call to get the monitor dimensions.

What I have so far is the code below. The main program finds all handles and displays those containing 'Atom' in the title. The windows package contains the code accessing the windows API.

My current result is that I get 2 handles for atom (why not just 1?). I guess, I have to learn more about the Windows API, too. Are there good summaries to understand the basics?

main.go:

package main

import (
    "resizer/windows"
    "fmt"
    "log"
    "strings"
)

func main() {
    const title = "Atom"    
    m := windows.GetAllWindows()
    fmt.Printf("Map of windows: 
")
    for handle := range m {
        if strings.Contains(m[handle].Title(), title) {
            fmt.Printf("'%v'
", m[handle])
        }
    }
}

windows.go:

package windows

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

var (
    user32             = syscall.MustLoadDLL("user32.dll")
    procEnumWindows    = user32.MustFindProc("EnumWindows")
    procGetWindowTextW = user32.MustFindProc("GetWindowTextW")
)

// Window represents any Window that is opened in the Windows OS
type Window struct {
    handle syscall.Handle
    title  string
}

// Title returns the title of the window
func (w Window) Title() string {
    return w.title
}

// GetAllWindows finds all currently opened windows
func GetAllWindows() map[syscall.Handle]Window {
    m := make(map[syscall.Handle]Window)
    cb := syscall.NewCallback(func(h syscall.Handle, p uintptr) uintptr {
        bytes := make([]uint16, 200)
        _, err := GetWindowText(h, &bytes[0], int32(len(bytes)))
        title := "||| no title found |||"
        if err == nil {
            title = syscall.UTF16ToString(bytes)
        }
        m[h] = Window{h, title}
        return 1 // continue enumeration
    })
    EnumWindows(cb, 0)
    return m
}

// EnumWindows loops through all windows and calls a callback function on each
func EnumWindows(enumFunc uintptr, lparam uintptr) (err error) {
    r1, _, e1 := syscall.Syscall(procEnumWindows.Addr(), 2, uintptr(enumFunc), uintptr(lparam), 0)
    if r1 == 0 {
        if e1 != 0 {
            err = error(e1)
        } else {
            err = syscall.EINVAL
        }
    }
    return
}

// GetWindowText gets the title of a Window given by a certain handle
func GetWindowText(hwnd syscall.Handle, str *uint16, maxCount int32) (len int32, err error) {
    r0, _, e1 := syscall.Syscall(procGetWindowTextW.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(str)), uintptr(maxCount))
    len = int32(r0)
    if len == 0 {
        if e1 != 0 {
            err = error(e1)
        } else {
            err = syscall.EINVAL
        }
    }
    return
}
  • 写回答

1条回答 默认 最新

  • dongxia4880 2017-07-02 22:27
    关注

    GetWindowRect() writes the geometry to the RECT structure you pass the pointer to in. It operates exactly like the GetWindowText() call you already have; the difference is you have to provide the RECT structure yourself.

    You should be able to just get away with copying the structure verbatim. To substitute data types, use this page. The definition for RECT says all the fields are LONG, which that page says is "[a] 32-bit signed integer". So this should suffice:

    type RECT struct {
        left   int32 // or Left, Top, etc. if this type is to be exported
        top    int32
        right  int32
        bottom int32
    }
    

    (Most likely irrelevant, but it's worth pointing out that RECT operates identically to image.Rectangle, with left and top being Min and right and bottom being Max. They are not identical because image.Rectangle uses int, so you may want to consider providing conversion functions if you want to use image's geometry functions to manipulate rectangles instead of GDI's.)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 前置放大电路与功率放大电路相连放大倍数出现问题
  • ¥30 关于<main>标签页面跳转的问题
  • ¥80 部署运行web自动化项目
  • ¥15 腾讯云如何建立同一个项目中物模型之间的联系
  • ¥30 VMware 云桌面水印如何添加
  • ¥15 用ns3仿真出5G核心网网元
  • ¥15 matlab答疑 关于海上风电的爬坡事件检测
  • ¥88 python部署量化回测异常问题
  • ¥30 酬劳2w元求合作写文章
  • ¥15 在现有系统基础上增加功能