forked from adamk33n3r/GoBorderless
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwinapi.go
More file actions
155 lines (131 loc) · 4.28 KB
/
winapi.go
File metadata and controls
155 lines (131 loc) · 4.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package main
import (
"fmt"
"syscall"
"unsafe"
"github.com/lxn/win"
"golang.org/x/sys/windows"
)
const (
maxPath = 260 // Maximum path length for Windows file paths
)
var (
user32 = windows.NewLazySystemDLL("user32.dll")
shell32 = windows.NewLazySystemDLL("shell32.dll")
procGetWindowTextW = user32.NewProc("GetWindowTextW")
procGetWindowTextLengthW = user32.NewProc("GetWindowTextLengthW")
procEnumDisplayMonitors = user32.NewProc("EnumDisplayMonitors")
procGetKnownFolderPath = shell32.NewProc("SHGetKnownFolderPath")
)
func enumWindows(callback func(hwnd uintptr, lparam uintptr) uintptr, extra unsafe.Pointer) {
windows.EnumWindows(windows.NewCallback(callback), extra)
}
func isVisible(hwnd uintptr) bool {
return win.IsWindowVisible(win.HWND(hwnd))
}
func getWindowTitle(hwnd uintptr) string {
textLen, _, _ := procGetWindowTextLengthW.Call(hwnd)
if textLen == 0 {
return ""
}
textBuf := make([]uint16, textLen+1)
procGetWindowTextW.Call(hwnd, uintptr(unsafe.Pointer(&textBuf[0])), uintptr(len(textBuf)))
return windows.UTF16ToString(textBuf)
}
func getProcessPath(pid uint32) (string, error) {
handle, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION|windows.PROCESS_VM_READ, false, pid)
if err != nil {
return "", err
}
defer windows.CloseHandle(handle) // Ensure handle is closed after use
processPathBuf := make([]uint16, maxPath)
processPathBufLen := uint32(maxPath)
err = windows.QueryFullProcessImageName(handle, 0, &processPathBuf[0], &processPathBufLen)
if err != nil {
return "", err
}
processPath := windows.UTF16ToString(processPathBuf)
return processPath, nil
}
func moveWindow(hwnd win.HWND, x, y, width, height int32) {
win.MoveWindow(hwnd, x, y, width, height, true)
}
func setWindowPos(hwnd win.HWND, x, y, width, height int32) {
win.SetWindowPos(hwnd, 0, x, y, width, height, win.SWP_NOZORDER)
}
func getWindowRect(hwnd win.HWND) win.RECT {
rect := win.RECT{}
win.GetWindowRect(hwnd, &rect)
return rect
}
func getWindowStyle(hwnd win.HWND) int32 {
return win.GetWindowLong(hwnd, win.GWL_STYLE)
}
func setWindowStyle(hwnd win.HWND, style int32) {
win.SetWindowLong(hwnd, win.GWL_STYLE, style)
win.SetWindowPos(hwnd, 0, 0, 0, 0, 0, win.SWP_NOMOVE|win.SWP_NOSIZE|win.SWP_NOZORDER|win.SWP_FRAMECHANGED)
}
type Monitor struct {
number int
isPrimary bool
width int32
height int32
left int32
top int32
}
func (m Monitor) String() string {
str := fmt.Sprintf("Display %d", m.number)
if m.isPrimary {
str += " (Primary)"
}
return str
}
func getMonitors() []Monitor {
var monitors []Monitor
index := 0
cb := syscall.NewCallback(func(hMonitor win.HMONITOR, hdcMonitor win.HDC, lprcMonitor *win.RECT, dwData uintptr) uintptr {
var info win.MONITORINFO
info.CbSize = uint32(unsafe.Sizeof(info))
if win.GetMonitorInfo(hMonitor, &info) {
index++
monitors = append(monitors, Monitor{
number: index,
isPrimary: info.DwFlags&win.MONITORINFOF_PRIMARY != 0,
width: info.RcMonitor.Right - info.RcMonitor.Left,
height: info.RcMonitor.Bottom - info.RcMonitor.Top,
left: info.RcMonitor.Left,
top: info.RcMonitor.Top,
})
}
return 1
})
procEnumDisplayMonitors.Call(0, 0, cb, 0)
return monitors
}
func getDocumentsFolder() string {
var buf uintptr
hr, _, _ := procGetKnownFolderPath.Call(uintptr(unsafe.Pointer(windows.FOLDERID_Documents)), 0, 0, uintptr(unsafe.Pointer(&buf)))
if hr != 0 {
return ""
}
defer windows.CoTaskMemFree(unsafe.Pointer(buf)) //nolint:govet
return windows.UTF16PtrToString((*uint16)(unsafe.Pointer(buf))) //nolint:govet
}
func createMutex(name string) (windows.Handle, error) {
if namePtr, err := windows.UTF16PtrFromString(name); err == nil {
return windows.CreateMutex(nil, false, namePtr)
}
return windows.Handle(0), fmt.Errorf("failed to create mutex")
}
func openMutex(name string) (windows.Handle, error) {
if namePtr, err := windows.UTF16PtrFromString(name); err == nil {
return windows.OpenMutex(windows.SYNCHRONIZE, false, namePtr)
}
return windows.Handle(0), fmt.Errorf("failed to open mutex")
}
func closeMutex(mutex windows.Handle) error {
return windows.CloseHandle(mutex)
}
// func waitForSingleObject(mutex *windows.Mutex) error {
// return windows.WaitForSingleObject(windows.Handle(mutex), windows.INFINITE)
// }