static AWnd _WindowFromRect(WICResult r) { Thread.Sleep(25); //after the form is closed, sometimes need several ms until OS sets correct Z order. Until that may get different w1 and w2. AWnd w1 = AWnd.FromXY((r.rect.left, r.rect.top)); AWnd w2 = (r.image == null) ? w1 : AWnd.FromXY((r.rect.right - 1, r.rect.bottom - 1)); if (w2 != w1 || !_IsInClientArea(w1)) { AWnd w3 = w1.Window, w4 = w2.Window; w1 = (w4 == w3 && _IsInClientArea(w3)) ? w3 : default; } return(w1); bool _IsInClientArea(AWnd w) => w.GetClientRect(out var rc, true) && rc.Contains(r.rect); }
//Use r on Capture. Use image on Open. void _SetImage(WICResult r = null, Bitmap image = null) { if (r != null) //on Capture { var wnd = r.wnd.Window; if (wnd.Is0) { return; } _SetWndCon(wnd, r.wnd, true, false); if (_isColor = (r.image == null)) { using (var g = Graphics.FromImage(r.image = new Bitmap(16, 16))) g.Clear((Color)r.color); } _color = r.color.color & 0xffffff; _image = r.image; _rect = r.rect; } else //on Open { _color = 0; _image = image; _rect = new RECT(0, 0, image.Width, image.Height); } //set _pict var oldImage = _pict.Image; _pict.Image = _image; oldImage?.Dispose(); //set _code _FormatCode(); _bTest.Enabled = true; _bOK.Enabled = true; if (_MultiIsActive && ADialog.ShowYesNo("Add to array?", owner: this)) { _MultiAdd(); } _errorProvider.Clear(); }
protected override void OnMouseDown(MouseEventArgs e) { if (e.Button != MouseButtons.Left) { return; } bool isColor = false, isAnyShape = false; var ic = _flags & (WICFlags.Image | WICFlags.Color | WICFlags.Rectangle); if (ic == WICFlags.Color) { isColor = true; } else { var mod = ModifierKeys; if (mod != 0 && ic == WICFlags.Rectangle) { return; } switch (mod) { case Keys.None: break; case Keys.Shift: isAnyShape = true; break; case Keys.Control when ic != WICFlags.Image: isColor = true; break; default: return; } } Result = new WICResult(); POINT p0 = e.Location; if (isColor) { Result.color = _img.GetPixel(p0.x, p0.y).ToArgb(); Result.rect = new RECT(p0.x, p0.y, 1, 1); } else { var r = new RECT(p0.x, p0.y, 0, 0); var a = isAnyShape ? new List <POINT>() { p0 } : null; var pen = Pens.Red; bool notFirstMove = false; _capturing = true; try { if (!ADragDrop.SimpleDragDrop(this, MButtons.Left, m => { if (m.Msg.message != Api.WM_MOUSEMOVE) { return; } POINT p = m.Msg.pt; p.x -= Left; p.y -= Top; //screen to client using var g = this.CreateGraphics(); if (isAnyShape) { a.Add(p); g.DrawLine(pen, p0, p); p0 = p; } else { if (notFirstMove) //erase prev rect { r.right++; r.bottom++; g.DrawImage(_img, r, r, GraphicsUnit.Pixel); //FUTURE: prevent flickering. Also don't draw under magnifier. } else { notFirstMove = true; } r = new RECT(p0.x, p0.y, p.x, p.y, false); r.Normalize(true); g.DrawRectangle(pen, r); } })) //Esc key etc { this.Invalidate(); return; } } finally { _capturing = false; } GraphicsPath path = null; if (isAnyShape && a.Count > 1) { path = _CreatePath(a); r = (RECT)path.GetBounds(); } else { r.right++; r.bottom++; } if (r.IsEmpty) { this.Close(); return; } if (ic != WICFlags.Rectangle) { var b = _img.Clone(r, PixelFormat.Format32bppArgb); var d = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, b.PixelFormat); try { _SetAlpha(d, r, path); } finally { b.UnlockBits(d); path?.Dispose(); } Result.image = b; } r.Offset(Left, Top); //client to screen Result.rect = r; } this.DialogResult = DialogResult.OK; this.Close(); }
/// <summary> /// Creates image from a user-selected area of screen pixels. Or gets single pixel color, or just rectangle. /// Returns false if cancelled. /// </summary> /// <param name="result">Receives results.</param> /// <param name="flags"></param> /// <param name="toolWindow">Owner window. Temporarily hides it and its owner windows.</param> /// <remarks> /// Gets all screen pixels and shows in a full-screen topmost window, where the user can select an area. /// </remarks> public static bool CaptureUI(out WICResult result, WICFlags flags = 0, AnyWnd toolWindow = default) { result = default; switch (flags & (WICFlags.Image | WICFlags.Color | WICFlags.Rectangle)) { case 0: case WICFlags.Image: case WICFlags.Color: case WICFlags.Rectangle: break; default: throw new ArgumentException(); } AWnd[] aw = null; AWnd wTool = default; try { if (!toolWindow.IsEmpty) { wTool = toolWindow.Wnd; aw = wTool.Get.OwnersAndThis(true); foreach (var w in aw) { w.ShowLL(false); } using (new AInputBlocker(BIEvents.MouseClicks)) ATime.SleepDoEvents(300); //time for animations } g1: RECT rs = SystemInformation.VirtualScreen; //RECT rs = AScreen.Primary.Bounds; //for testing, to see Write output in other screen Bitmap bs; bool windowPixels = flags.HasAny(WICFlags.WindowDC | WICFlags.PrintWindow); if (windowPixels) { if (!_WaitForHotkey("Press F3 to select window from mouse pointer.")) { return(false); } var w = AWnd.FromMouse(WXYFlags.NeedWindow); w.GetClientRect(out var rc, inScreen: true); using var bw = Capture(w, w.ClientRect, flags.Has(WICFlags.PrintWindow)); bs = new Bitmap(rs.Width, rs.Height); using var g = Graphics.FromImage(bs); g.Clear(Color.Black); g.DrawImage(bw, rc.left, rc.top); } else { bs = Capture(rs); } var f = new _Form(bs, flags); f.Bounds = rs; switch (f.ShowDialog()) { case DialogResult.OK: break; case DialogResult.Retry: if (!windowPixels && !_WaitForHotkey("Press F3 when ready for new screenshot.")) { return(false); } goto g1; default: return(false); } var r = f.Result; r.wnd = _WindowFromRect(r); result = r; } finally { if (aw != null) { foreach (var w in aw) { w.ShowLL(true); } if (wTool.IsAlive) { wTool.ShowNotMinimized(); wTool.ActivateLL(); } } } return(true); }