package main import ( "bytes" "fmt" "image" "image/draw" "image/png" "os" "time" "github.com/go-vgo/robotgo" qt "github.com/mappu/miqt/qt6" ) var ( mw *MainWindowUi ) func doScreencap(onGotNewScreenshot func(string, int64, int64)) { mw.MainWindow.Hide() time.Sleep(200 * time.Millisecond) 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 { panic(err) } pixm := qt.NewQPixmap() ok := pixm.LoadFromData2(&pngBuff.Bytes()[0], uint(pngBuff.Len()), "png") if !ok { panic("not ok") } 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()), int64(clickPos.Y())) scWnd.ScreenCaptureDialog.Close() }) scWnd.ScreenCaptureDialog.ShowMaximized() } func main() { qt.NewQApplication(os.Args) mw = NewMainWindowUi() onGotNewScreenshot := func(filepath string, click_x, click_y int64) { // Newline is added automatically // TODO if this was the default/center position, get default coordinates appendCode := fmt.Sprintf(`Click("%s", {X: %d, Y: %d});`, filepath, click_x, click_y) mw.textEdit.Append(appendCode) } mw.actionScreenshot.OnTriggered(func() { doScreencap(onGotNewScreenshot) }) mw.actionE_xit.OnTriggered(func() { // TODO check for unsaved file changes os.Exit(0) }) mw.MainWindow.Show() qt.QApplication_Exec() }