-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmonitor.go
114 lines (98 loc) · 2.88 KB
/
monitor.go
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
package displayController
import (
"fmt"
"syscall"
"unsafe"
)
type CompositeMonitorInfo struct {
PhysicalInfo PhysicalMonitorInfo
SysInfo SystemMonitorInfo
}
type SystemMonitorInfo struct {
Handle syscall.Handle
DeviceContext syscall.Handle
RectAngle RECT
}
type PhysicalMonitorInfo struct {
Handle syscall.Handle
Description string
}
type RECT struct {
Left int32
Top int32
Right int32
Bottom int32
}
// GetCompositeMonitors 获取复合显示器信息
func GetCompositeMonitors() (monitors []CompositeMonitorInfo, err error) {
// 获取系统显示器信息
systemMonitors, err := GetSystemMonitors()
if err != nil {
return nil, err
}
for _, sysMonitor := range systemMonitors {
// 获取物理显示器信息
physicalMonitor, err := GetPhysicalMonitor(sysMonitor.Handle)
if err != nil {
continue
}
// 拼接复合显示器信息
monitors = append(monitors, CompositeMonitorInfo{
PhysicalInfo: physicalMonitor,
SysInfo: sysMonitor,
})
}
return monitors, nil
}
// GetSystemMonitors 获取所有屏幕设备信息
func GetSystemMonitors() (info []SystemMonitorInfo, err error) {
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-monitorenumproc
var fnCallback = func(hMonitor syscall.Handle, hdc syscall.Handle, rect *RECT, lParam uintptr) int {
info = append(info, SystemMonitorInfo{Handle: hMonitor, DeviceContext: hdc, RectAngle: *rect})
// 继续枚举下一个显示器,1代表true
return 1
}
// 两者结果一致 uintptr(unsafe.Pointer(nil)) or uintptr(syscall.Handle(0))
_, _, callErr := syscall.SyscallN(procEnumDisplayMonitors,
uintptr(unsafe.Pointer(nil)),
uintptr(unsafe.Pointer(nil)),
syscall.NewCallback(fnCallback),
uintptr(unsafe.Pointer(nil)),
)
if callErr != 0 {
return info, fmt.Errorf(callErr.Error())
}
return info, nil
}
// GetMonitorNumberFromHandle 获取显示器句柄下的显示器数量
func GetMonitorNumberFromHandle(hMonitor syscall.Handle) (number int32, err error) {
_, _, callErr := syscall.SyscallN(procGetNumberOfPhysicalMonitorsFromHMONITOR,
uintptr(hMonitor),
uintptr(number),
)
if callErr != 0 {
return 0, fmt.Errorf(callErr.Error())
}
return number, nil
}
// GetPhysicalMonitor 获取物理显示器信息
func GetPhysicalMonitor(hMonitor syscall.Handle) (info PhysicalMonitorInfo, err error) {
bytes := make([]byte, 256)
_, _, callErr := syscall.SyscallN(procGetPhysicalMonitorsFromHMONITOR,
uintptr(hMonitor),
uintptr(1),
uintptr(unsafe.Pointer(&bytes[0])),
)
if callErr != 0 {
return PhysicalMonitorInfo{}, fmt.Errorf(callErr.Error())
}
// 第8位以后才是显示器描述信息
// 每个字母用0隔开,需要重新整理
var newBytes []byte
for _, b := range bytes[8:] {
if b != 0 {
newBytes = append(newBytes, b)
}
}
return PhysicalMonitorInfo{Handle: syscall.Handle(bytes[0]), Description: string(newBytes)}, nil
}