首頁  >  文章  >  後端開發  >  golang怎麼實作一個可取得和顯示螢幕頂層視窗的程序

golang怎麼實作一個可取得和顯示螢幕頂層視窗的程序

PHPz
PHPz原創
2023-04-25 09:11:381429瀏覽

在目前的電腦作業系統中,螢幕頂層是指目前正在顯示的視窗或應用程式。在Windows系統中,透過Win32 API可以取得和管理頂層視窗。在本文中,我們將介紹如何使用golang實作一個可以取得和顯示螢幕頂層視窗的程式。

  1. 取得頂層視窗清單

在golang中,使用syscall套件可以呼叫系統級函數。我們可以使用FindWindowEx函數來取得頂層視窗的句柄列表。例如:

hwnd := uintptr(0)
var list []uintptr
for {
    hwnd = uintptr(C.FindWindowEx(
        0,
        hwnd,
        nil,
        nil,
    ))
    if hwnd == 0 {
        break
    }
    list = append(list, hwnd)
}

其中,FindWindowEx函數的參數意義如下:

  • 第一個參數是尋找開始的父視窗句柄,如果為0,則從桌面開始尋找。
  • 第二個參數是上一個視窗的句柄,如果為0,則從第一個視窗開始尋找。
  • 第三個參數是視窗類別名,nil表示不限制視窗類別名稱。
  • 第四個參數是視窗標題,nil表示不限制視窗標題。

傳回值為找到的視窗句柄,如果沒有找到,則傳回0。

  1. 取得頂層視窗資訊

取得到視窗句柄之後,我們可以呼叫GetWindowRect函數來取得視窗的位置和大小資訊。例如:

var rect syscall.Rect
C.GetWindowRect(
    C.HWND(hwnd),
    (*C.RECT)(unsafe.Pointer(&rect)),
)

其中,GetWindowRect函數的參數意義如下:

  • 第一個參數是視窗句柄。
  • 第二個參數是指向視窗位置和大小資訊的指標。
  1. 顯示頂層視窗資訊

透過取得到的視窗位置和大小信息,我們可以使用golang的圖形庫顯示該視窗的縮圖。例如:

thumb, err := goscreenshot.CaptureWindowRect(rect)
if err != nil {
    log.Println(err)
    continue
}
screen, err := png.Decode(bytes.NewReader(thumb))
if err != nil {
    log.Println(err)
    continue
}
win := Window{
    Title:   title,
    X:       rect.Left,
    Y:       rect.Top,
    Width:   rect.Right - rect.Left,
    Height:  rect.Bottom - rect.Top,
    Picture: screen,
}
viewer.Show(win)

其中,CaptureWindowRect函數透過golang的screenshot套件實現了視窗截圖的功能。然後用golang的image/png套件讀取影像數據,並將其顯示在視窗中。最後定義了Window結構並使用viewer.Show方法來顯示視窗資訊。

  1. 完整程式碼

完整的程式碼如下:

package main

import (
    "bytes"
    "image/png"
    "log"
    "unsafe"

    "github.com/lxn/walk"
    . "github.com/lxn/walk/declarative"
    "golang.org/x/sys/windows"
)

var (
    C = windows.NewLazySystemDLL("user32.dll")
)

// 窗口信息结构
type Window struct {
    Title   string      // 窗口标题
    X       int32       // 窗口左上角X坐标
    Y       int32       // 窗口左上角Y坐标
    Width   int32       // 窗口宽度
    Height  int32       // 窗口高度
    Picture image.Image // 窗口截图
}

func main() {

    // 创建窗口
    var mw *walk.MainWindow
    var tv *walk.TableView
    var viewer *walk.ImageView
    MainWindow{
        Title:   "Screen Viewer",
        MinSize: Size{640, 480},
        Layout:  VBox{},
        Children: []Widget{
            TableView{
                AssignTo:         &tv,
                AlternatingRowBG: true,
                Columns: []TableViewColumn{
                    {Title: "Title"},
                    {Title: "X"},
                    {Title: "Y"},
                    {Title: "Width"},
                    {Title: "Height"},
                },
            },
            ImageView{
                AssignTo: &viewer,
            },
        },
    }.Create(&mw)

    // 获取顶层窗口列表
    hwnd := uintptr(0)
    var list []uintptr
    for {
        hwnd = uintptr(C.FindWindowEx(
            0,
            hwnd,
            nil,
            nil,
        ))
        if hwnd == 0 {
            break
        }
        list = append(list, hwnd)
    }

    // 遍历窗口列表并显示窗口信息
    var data []Window
    for _, hwnd := range list {
        var rect syscall.Rect
        C.GetWindowRect(
            C.HWND(hwnd),
            (*C.RECT)(unsafe.Pointer(&rect)),
        )
        title := getWindowText(hwnd)
        if title == "" {
            continue
        }
        thumb, err := goscreenshot.CaptureWindowRect(rect)
        if err != nil {
            log.Println(err)
            continue
        }
        screen, err := png.Decode(bytes.NewReader(thumb))
        if err != nil {
            log.Println(err)
            continue
        }
        win := Window{
            Title:   title,
            X:       rect.Left,
            Y:       rect.Top,
            Width:   rect.Right - rect.Left,
            Height:  rect.Bottom - rect.Top,
            Picture: screen,
        }
        data = append(data, win)
        tv.PublishRowsReset()
    }

    // 设置模型
    model, _ := NewWindowModel(data)
    tv.SetModel(model)

    // 开始消息循环
    mw.Run()
}

// 获取窗口标题
func getWindowText(hwnd uintptr) string {
    var buf [256]uint16
    C.GetWindowText(
        C.HWND(hwnd),
        (*C.CHAR)(unsafe.Pointer(&buf)),
        256,
    )
    return syscall.UTF16ToString(buf[:])
}

// 窗口模型
type WindowModel struct {
    walk.TableModelBase
    items []Window
}

func NewWindowModel(items []Window) (*WindowModel, error) {
    m := new(WindowModel)

    m.items = items

    return m, nil
}

func (m *WindowModel) RowCount() int {
    return len(m.items)
}

func (m *WindowModel) Value(row, col int) interface{} {
    item := m.items[row]

    switch col {
    case 0:
        return item.Title

    case 1:
        return item.X

    case 2:
        return item.Y

    case 3:
        return item.Width

    case 4:
        return item.Height

    }

    panic("unexpected col")
}
  1. 總結
##本文介紹如何使用golang實作取得和顯示螢幕頂層視窗的程式。透過呼叫Windows API函數、實作視窗截圖和影像顯示等操作,我們可以很方便得編寫一個簡單的螢幕截圖工具。同時,在golang的圖形庫和Windows API的配合下,我們可以寫出跨平台的應用程式。

以上是golang怎麼實作一個可取得和顯示螢幕頂層視窗的程序的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn