187 lines
4.1 KiB
Go
187 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"image"
|
|
"image/draw"
|
|
"image/png"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/go-vgo/robotgo"
|
|
qt "github.com/mappu/miqt/qt6"
|
|
)
|
|
|
|
// doScreencap starts a new screen capture workflow.
|
|
func doScreencap(onGotNewScreenshot func(string, int64, int64)) {
|
|
|
|
mw.MainWindow.Hide()
|
|
|
|
time.Sleep(DefaultWait)
|
|
|
|
bmp := robotgo.CaptureScreen(0)
|
|
img := robotgo.ToImage(bmp)
|
|
robotgo.FreeBitmap(bmp)
|
|
|
|
mw.MainWindow.Show()
|
|
|
|
// load image into Qt
|
|
|
|
pngBuff := bytes.Buffer{}
|
|
fastPnger := png.Encoder{
|
|
CompressionLevel: png.NoCompression,
|
|
}
|
|
err := fastPnger.Encode(&pngBuff, img)
|
|
if err != nil {
|
|
qt.QMessageBox_Critical(mw.MainWindow.QWidget, "Screen capture error", err.Error())
|
|
return
|
|
}
|
|
|
|
pixm := qt.NewQPixmap()
|
|
ok := pixm.LoadFromData2(&pngBuff.Bytes()[0], uint(pngBuff.Len()), "png")
|
|
if !ok {
|
|
qt.QMessageBox_Critical(mw.MainWindow.QWidget, "Screen capture error", "PNG parse failure")
|
|
return
|
|
}
|
|
|
|
pngBuff.Reset()
|
|
|
|
//
|
|
|
|
scWnd := NewScreenCaptureDialogUi()
|
|
scWnd.ScreenCaptureDialog.SetModal(true)
|
|
|
|
currentZoom := 60
|
|
scWnd.gv.Scale(0.6, 0.6)
|
|
|
|
scene := qt.NewQGraphicsScene6(0, 0, float64(img.Bounds().Dx()), float64(img.Bounds().Dy()), nil)
|
|
scWnd.gv.SetScene(scene)
|
|
|
|
scene.AddPixmap(pixm)
|
|
|
|
rect := scene.AddRect2(0, 0, 200, 100)
|
|
|
|
crosshair1 := scene.AddLine2(-8, -8, 8, 8)
|
|
crosshair2 := scene.AddLine2(8, -8, -8, 8)
|
|
|
|
isMousedown := false
|
|
|
|
var nextStartPos *qt.QPointF
|
|
|
|
refreshCaption := func() {
|
|
curRect := rect.Rect()
|
|
curPos := crosshair1.Pos()
|
|
|
|
statusText := fmt.Sprintf("Image selection: (X=%.2f Y=%.2f W=%.2f H=%.2f) - Click offset: (X=%.2f Y=%.2f) - Zoom: %d%%",
|
|
curRect.X(), curRect.Y(), curRect.Width(), curRect.Height(),
|
|
curPos.X()-curRect.X(), curPos.Y()-curRect.Y(),
|
|
currentZoom,
|
|
)
|
|
scWnd.lbStatus.SetText(statusText)
|
|
}
|
|
refreshCaption()
|
|
|
|
scWnd.gv.OnMousePressEvent(func(super func(event *qt.QMouseEvent), event *qt.QMouseEvent) {
|
|
pos := scWnd.gv.MapToScene(event.Pos())
|
|
nextStartPos = pos // we'll use this pos if there is mouse movement - otherwise only move the crosshair
|
|
isMousedown = true
|
|
|
|
if rect.Rect().ContainsWithQPointF(pos) {
|
|
crosshair1.SetPos(pos)
|
|
crosshair2.SetPos(pos)
|
|
refreshCaption()
|
|
}
|
|
|
|
super(event)
|
|
})
|
|
|
|
scWnd.gv.OnMouseMoveEvent(func(super func(event *qt.QMouseEvent), event *qt.QMouseEvent) {
|
|
|
|
if isMousedown {
|
|
pos := scWnd.gv.MapToScene(event.Pos())
|
|
curRect := qt.NewQRectF4(nextStartPos.X(), nextStartPos.Y(), pos.X()-nextStartPos.X(), pos.Y()-nextStartPos.Y())
|
|
rect.SetRect(curRect)
|
|
|
|
crosshair1.SetPos(curRect.Center())
|
|
crosshair2.SetPos(curRect.Center())
|
|
|
|
refreshCaption()
|
|
}
|
|
|
|
super(event)
|
|
})
|
|
|
|
scWnd.gv.OnMouseReleaseEvent(func(super func(event *qt.QMouseEvent), event *qt.QMouseEvent) {
|
|
isMousedown = false
|
|
super(event)
|
|
})
|
|
|
|
refreshZoom := func() {
|
|
scWnd.gv.ResetTransform()
|
|
zScale := float64(currentZoom) / 100
|
|
scWnd.gv.Scale(zScale, zScale)
|
|
refreshCaption()
|
|
}
|
|
|
|
scWnd.btZoomIn.OnClicked(func() {
|
|
currentZoom += 10
|
|
refreshZoom()
|
|
})
|
|
|
|
scWnd.btZoomOut.OnClicked(func() {
|
|
if currentZoom < 15 {
|
|
return
|
|
}
|
|
|
|
currentZoom -= 10
|
|
refreshZoom()
|
|
})
|
|
|
|
scWnd.btZoomFit.OnClicked(func() {
|
|
currentZoom = 60
|
|
refreshZoom()
|
|
})
|
|
|
|
scWnd.btCapture.OnClicked(func() {
|
|
|
|
// Create a new image cropped to target selection
|
|
|
|
curRect := rect.Rect()
|
|
clickPos := crosshair1.Pos()
|
|
|
|
imRect := image.Rectangle{
|
|
Min: image.Point{
|
|
X: int(curRect.X()),
|
|
Y: int(curRect.Y()),
|
|
},
|
|
Max: image.Point{
|
|
X: int(curRect.X() + curRect.Width()),
|
|
Y: int(curRect.Y() + curRect.Height()),
|
|
},
|
|
}
|
|
result := image.NewRGBA(imRect)
|
|
draw.Draw(result, imRect, img, imRect.Min, draw.Src)
|
|
|
|
// Encode and save as a file in the current directory
|
|
filepath := fmt.Sprintf("%d.png", time.Now().UnixMicro())
|
|
fh, err := os.OpenFile(filepath, os.O_CREATE|os.O_RDWR, 0644)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
err = png.Encode(fh, result)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
fh.Close()
|
|
|
|
// Finished - close dialog and signal back to parent
|
|
onGotNewScreenshot(filepath, int64(clickPos.X()-curRect.X()), int64(clickPos.Y()-curRect.Y()))
|
|
scWnd.ScreenCaptureDialog.Close()
|
|
})
|
|
|
|
scWnd.ScreenCaptureDialog.ShowMaximized()
|
|
}
|