inital commit
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
//go:build windows
|
||||
|
||||
package capture
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
cursorCaptureEnabled atomic.Bool
|
||||
)
|
||||
|
||||
func SetCursorCapture(enabled bool) {
|
||||
cursorCaptureEnabled.Store(enabled)
|
||||
}
|
||||
|
||||
var (
|
||||
procGetCursorPos = user32.NewProc("GetCursorPos")
|
||||
procGetCursorInfo = user32.NewProc("GetCursorInfo")
|
||||
procGetIconInfo = user32.NewProc("GetIconInfo")
|
||||
procDrawIconEx = user32.NewProc("DrawIconEx")
|
||||
)
|
||||
|
||||
const (
|
||||
CURSOR_SHOWING = 0x00000001
|
||||
DI_NORMAL = 0x0003
|
||||
DI_DEFAULTSIZE = 0x0008
|
||||
)
|
||||
|
||||
type point struct {
|
||||
x int32
|
||||
y int32
|
||||
}
|
||||
|
||||
type cursorInfo struct {
|
||||
cbSize uint32
|
||||
flags uint32
|
||||
hCursor uintptr
|
||||
ptScreenPos point
|
||||
}
|
||||
|
||||
type iconInfo struct {
|
||||
fIcon uint32
|
||||
xHotspot uint32
|
||||
yHotspot uint32
|
||||
hbmMask uintptr
|
||||
hbmColor uintptr
|
||||
}
|
||||
|
||||
func getCursorPosition() (x, y int32, visible bool) {
|
||||
var ci cursorInfo
|
||||
ci.cbSize = uint32(unsafe.Sizeof(ci))
|
||||
|
||||
ret, _, _ := procGetCursorInfo.Call(uintptr(unsafe.Pointer(&ci)))
|
||||
if ret == 0 {
|
||||
return 0, 0, false
|
||||
}
|
||||
|
||||
visible = (ci.flags & CURSOR_SHOWING) != 0
|
||||
return ci.ptScreenPos.x, ci.ptScreenPos.y, visible
|
||||
}
|
||||
|
||||
func drawCursor(img *image.RGBA, cursorX, cursorY int32, bounds image.Rectangle) {
|
||||
imgX := int(cursorX) - bounds.Min.X
|
||||
imgY := int(cursorY) - bounds.Min.Y
|
||||
|
||||
if imgX < 0 || imgY < 0 || imgX >= img.Bounds().Dx() || imgY >= img.Bounds().Dy() {
|
||||
return
|
||||
}
|
||||
|
||||
cursorPattern := []struct {
|
||||
x, y int
|
||||
c color.RGBA
|
||||
}{
|
||||
{0, 0, color.RGBA{0, 0, 0, 255}},
|
||||
{0, 1, color.RGBA{0, 0, 0, 255}},
|
||||
{0, 2, color.RGBA{0, 0, 0, 255}},
|
||||
{0, 3, color.RGBA{0, 0, 0, 255}},
|
||||
{0, 4, color.RGBA{0, 0, 0, 255}},
|
||||
{0, 5, color.RGBA{0, 0, 0, 255}},
|
||||
{0, 6, color.RGBA{0, 0, 0, 255}},
|
||||
{0, 7, color.RGBA{0, 0, 0, 255}},
|
||||
{0, 8, color.RGBA{0, 0, 0, 255}},
|
||||
{0, 9, color.RGBA{0, 0, 0, 255}},
|
||||
{0, 10, color.RGBA{0, 0, 0, 255}},
|
||||
{0, 11, color.RGBA{0, 0, 0, 255}},
|
||||
{1, 0, color.RGBA{0, 0, 0, 255}},
|
||||
{1, 10, color.RGBA{0, 0, 0, 255}},
|
||||
{2, 0, color.RGBA{0, 0, 0, 255}},
|
||||
{2, 9, color.RGBA{0, 0, 0, 255}},
|
||||
{3, 0, color.RGBA{0, 0, 0, 255}},
|
||||
{3, 8, color.RGBA{0, 0, 0, 255}},
|
||||
{3, 9, color.RGBA{0, 0, 0, 255}},
|
||||
{4, 0, color.RGBA{0, 0, 0, 255}},
|
||||
{4, 7, color.RGBA{0, 0, 0, 255}},
|
||||
{4, 8, color.RGBA{0, 0, 0, 255}},
|
||||
{5, 0, color.RGBA{0, 0, 0, 255}},
|
||||
{5, 6, color.RGBA{0, 0, 0, 255}},
|
||||
{5, 7, color.RGBA{0, 0, 0, 255}},
|
||||
{5, 13, color.RGBA{0, 0, 0, 255}},
|
||||
{6, 0, color.RGBA{0, 0, 0, 255}},
|
||||
{6, 5, color.RGBA{0, 0, 0, 255}},
|
||||
{6, 6, color.RGBA{0, 0, 0, 255}},
|
||||
{6, 12, color.RGBA{0, 0, 0, 255}},
|
||||
{6, 13, color.RGBA{0, 0, 0, 255}},
|
||||
{7, 0, color.RGBA{0, 0, 0, 255}},
|
||||
{7, 4, color.RGBA{0, 0, 0, 255}},
|
||||
{7, 5, color.RGBA{0, 0, 0, 255}},
|
||||
{7, 11, color.RGBA{0, 0, 0, 255}},
|
||||
{7, 12, color.RGBA{0, 0, 0, 255}},
|
||||
{8, 4, color.RGBA{0, 0, 0, 255}},
|
||||
{8, 10, color.RGBA{0, 0, 0, 255}},
|
||||
{8, 11, color.RGBA{0, 0, 0, 255}},
|
||||
{9, 4, color.RGBA{0, 0, 0, 255}},
|
||||
{9, 9, color.RGBA{0, 0, 0, 255}},
|
||||
{9, 10, color.RGBA{0, 0, 0, 255}},
|
||||
{10, 8, color.RGBA{0, 0, 0, 255}},
|
||||
{10, 9, color.RGBA{0, 0, 0, 255}},
|
||||
{11, 7, color.RGBA{0, 0, 0, 255}},
|
||||
{11, 8, color.RGBA{0, 0, 0, 255}},
|
||||
{12, 6, color.RGBA{0, 0, 0, 255}},
|
||||
{12, 7, color.RGBA{0, 0, 0, 255}},
|
||||
|
||||
{1, 1, color.RGBA{255, 255, 255, 255}},
|
||||
{1, 2, color.RGBA{255, 255, 255, 255}},
|
||||
{1, 3, color.RGBA{255, 255, 255, 255}},
|
||||
{1, 4, color.RGBA{255, 255, 255, 255}},
|
||||
{1, 5, color.RGBA{255, 255, 255, 255}},
|
||||
{1, 6, color.RGBA{255, 255, 255, 255}},
|
||||
{1, 7, color.RGBA{255, 255, 255, 255}},
|
||||
{1, 8, color.RGBA{255, 255, 255, 255}},
|
||||
{1, 9, color.RGBA{255, 255, 255, 255}},
|
||||
{2, 1, color.RGBA{255, 255, 255, 255}},
|
||||
{2, 2, color.RGBA{255, 255, 255, 255}},
|
||||
{2, 3, color.RGBA{255, 255, 255, 255}},
|
||||
{2, 4, color.RGBA{255, 255, 255, 255}},
|
||||
{2, 5, color.RGBA{255, 255, 255, 255}},
|
||||
{2, 6, color.RGBA{255, 255, 255, 255}},
|
||||
{2, 7, color.RGBA{255, 255, 255, 255}},
|
||||
{2, 8, color.RGBA{255, 255, 255, 255}},
|
||||
{3, 1, color.RGBA{255, 255, 255, 255}},
|
||||
{3, 2, color.RGBA{255, 255, 255, 255}},
|
||||
{3, 3, color.RGBA{255, 255, 255, 255}},
|
||||
{3, 4, color.RGBA{255, 255, 255, 255}},
|
||||
{3, 5, color.RGBA{255, 255, 255, 255}},
|
||||
{3, 6, color.RGBA{255, 255, 255, 255}},
|
||||
{3, 7, color.RGBA{255, 255, 255, 255}},
|
||||
{4, 1, color.RGBA{255, 255, 255, 255}},
|
||||
{4, 2, color.RGBA{255, 255, 255, 255}},
|
||||
{4, 3, color.RGBA{255, 255, 255, 255}},
|
||||
{4, 4, color.RGBA{255, 255, 255, 255}},
|
||||
{4, 5, color.RGBA{255, 255, 255, 255}},
|
||||
{4, 6, color.RGBA{255, 255, 255, 255}},
|
||||
{5, 1, color.RGBA{255, 255, 255, 255}},
|
||||
{5, 2, color.RGBA{255, 255, 255, 255}},
|
||||
{5, 3, color.RGBA{255, 255, 255, 255}},
|
||||
{5, 4, color.RGBA{255, 255, 255, 255}},
|
||||
{5, 5, color.RGBA{255, 255, 255, 255}},
|
||||
{5, 11, color.RGBA{255, 255, 255, 255}},
|
||||
{5, 12, color.RGBA{255, 255, 255, 255}},
|
||||
{6, 1, color.RGBA{255, 255, 255, 255}},
|
||||
{6, 2, color.RGBA{255, 255, 255, 255}},
|
||||
{6, 3, color.RGBA{255, 255, 255, 255}},
|
||||
{6, 4, color.RGBA{255, 255, 255, 255}},
|
||||
{6, 10, color.RGBA{255, 255, 255, 255}},
|
||||
{6, 11, color.RGBA{255, 255, 255, 255}},
|
||||
{7, 1, color.RGBA{255, 255, 255, 255}},
|
||||
{7, 2, color.RGBA{255, 255, 255, 255}},
|
||||
{7, 3, color.RGBA{255, 255, 255, 255}},
|
||||
{7, 9, color.RGBA{255, 255, 255, 255}},
|
||||
{7, 10, color.RGBA{255, 255, 255, 255}},
|
||||
{8, 5, color.RGBA{255, 255, 255, 255}},
|
||||
{8, 6, color.RGBA{255, 255, 255, 255}},
|
||||
{8, 7, color.RGBA{255, 255, 255, 255}},
|
||||
{8, 8, color.RGBA{255, 255, 255, 255}},
|
||||
{8, 9, color.RGBA{255, 255, 255, 255}},
|
||||
{9, 5, color.RGBA{255, 255, 255, 255}},
|
||||
{9, 6, color.RGBA{255, 255, 255, 255}},
|
||||
{9, 7, color.RGBA{255, 255, 255, 255}},
|
||||
{9, 8, color.RGBA{255, 255, 255, 255}},
|
||||
{10, 6, color.RGBA{255, 255, 255, 255}},
|
||||
{10, 7, color.RGBA{255, 255, 255, 255}},
|
||||
{11, 6, color.RGBA{255, 255, 255, 255}},
|
||||
}
|
||||
|
||||
for _, p := range cursorPattern {
|
||||
px := imgX + p.x
|
||||
py := imgY + p.y
|
||||
if px >= 0 && px < img.Bounds().Dx() && py >= 0 && py < img.Bounds().Dy() {
|
||||
img.SetRGBA(px, py, p.c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func DrawCursorOnDC(hdc uintptr, captureBounds image.Rectangle) bool {
|
||||
if !cursorCaptureEnabled.Load() || hdc == 0 {
|
||||
return false
|
||||
}
|
||||
var ci cursorInfo
|
||||
ci.cbSize = uint32(unsafe.Sizeof(ci))
|
||||
ret, _, _ := procGetCursorInfo.Call(uintptr(unsafe.Pointer(&ci)))
|
||||
if ret == 0 || (ci.flags&CURSOR_SHOWING) == 0 || ci.hCursor == 0 {
|
||||
return false
|
||||
}
|
||||
var icon iconInfo
|
||||
ret, _, _ = procGetIconInfo.Call(ci.hCursor, uintptr(unsafe.Pointer(&icon)))
|
||||
if ret == 0 {
|
||||
return false
|
||||
}
|
||||
if icon.hbmMask != 0 {
|
||||
defer deleteObject(icon.hbmMask)
|
||||
}
|
||||
if icon.hbmColor != 0 {
|
||||
defer deleteObject(icon.hbmColor)
|
||||
}
|
||||
|
||||
x := int32(ci.ptScreenPos.x) - int32(captureBounds.Min.X) - int32(icon.xHotspot)
|
||||
y := int32(ci.ptScreenPos.y) - int32(captureBounds.Min.Y) - int32(icon.yHotspot)
|
||||
ret, _, _ = procDrawIconEx.Call(
|
||||
hdc,
|
||||
uintptr(x),
|
||||
uintptr(y),
|
||||
ci.hCursor,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
uintptr(DI_NORMAL),
|
||||
)
|
||||
return ret != 0
|
||||
}
|
||||
|
||||
func DrawCursorOnImage(img *image.RGBA, captureBounds image.Rectangle) {
|
||||
if !cursorCaptureEnabled.Load() {
|
||||
return
|
||||
}
|
||||
|
||||
x, y, visible := getCursorPosition()
|
||||
if visible {
|
||||
drawCursor(img, x, y, captureBounds)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user