void _WmNcpaint() { using var dc = new WindowDC_(Api.GetWindowDC(_w), _w); RECT r = new(0, 0, _size.window.width, _size.window.height); for (int i = 0; i < _size.border; i++) { Api.FrameRect(dc, r, Api.GetSysColorBrush(i == 0 ? Api.COLOR_BTNSHADOW : Api.COLOR_BTNFACE)); r.Inflate(-1, -1); } }
static unsafe Bitmap _Capture(RECT r, AWnd w = default, bool usePrintWindow = false, GraphicsPath path = null) { //Transfer from screen/window DC to memory DC (does not work without this) and get pixels. //rejected: parameter includeNonClient (GetWindowDC). // Nothing good. If in background, captures incorrect caption etc. // If need nonclient part, better activate window and capture window rectangle from screen. //FUTURE: if w is DWM-scaled... using var mb = new AMemoryBitmap(r.Width, r.Height); if (usePrintWindow && Api.PrintWindow(w, mb.Hdc, Api.PW_CLIENTONLY | (AVersion.MinWin8_1 ? Api.PW_RENDERFULLCONTENT : 0))) { //AOutput.Write("PrintWindow OK"); } else { using (var dc = new WindowDC_(w)) { if (dc.Is0) { w.ThrowNoNative("Failed"); } uint rop = !w.Is0 ? Api.SRCCOPY : Api.SRCCOPY | Api.CAPTUREBLT; bool ok = Api.BitBlt(mb.Hdc, 0, 0, r.Width, r.Height, dc, r.left, r.top, rop); Debug.Assert(ok); //the API fails only if a HDC is invalid } } var R = new Bitmap(r.Width, r.Height, PixelFormat.Format32bppRgb); try { var bh = new Api.BITMAPINFOHEADER() { biSize = sizeof(Api.BITMAPINFOHEADER), biWidth = r.Width, biHeight = -r.Height, //use -height for top-down biPlanes = 1, biBitCount = 32, //biCompression = 0, //BI_RGB }; var d = R.LockBits(new Rectangle(0, 0, r.Width, r.Height), ImageLockMode.ReadWrite, R.PixelFormat); //tested: fast, no copy try { var apiResult = Api.GetDIBits(mb.Hdc, mb.Hbitmap, 0, r.Height, (void *)d.Scan0, &bh, 0); //DIB_RGB_COLORS if (apiResult != r.Height) { throw new AuException("GetDIBits"); } _SetAlpha(d, r, path); } finally { R.UnlockBits(d); } //tested: fast, no copy return(R); } catch { R.Dispose(); throw; } }
static void _CaptureToDC(MemoryBitmap mb, RECT r, wnd w = default, bool printWindow = false) { if (printWindow) { if (!Api.PrintWindow(w, mb.Hdc, Api.PW_CLIENTONLY | (osVersion.minWin8_1 ? Api.PW_RENDERFULLCONTENT : 0))) { w.ThrowNoNative("Failed to get pixels"); } } else { using var dc = new WindowDC_(w); if (dc.Is0) { w.ThrowNoNative("Failed to get pixels"); } uint rop = !w.Is0 ? Api.SRCCOPY : Api.SRCCOPY | Api.CAPTUREBLT; bool ok = Api.BitBlt(mb.Hdc, 0, 0, r.Width, r.Height, dc, r.left, r.top, rop); Debug.Assert(ok); //the API fails only if a HDC is invalid } }
void _WmMousemove(POINT pc) { if (!_paintedOnce) { return; } //format text to draw below magnifier string text; using (new StringBuilder_(out var s)) { var ic = _flags & (ICFlags.Image | ICFlags.Color | ICFlags.Rectangle); if (ic == 0) { ic = ICFlags.Image | ICFlags.Color; } bool canColor = ic.Has(ICFlags.Color); if (canColor) { var color = _img.GetPixel(pc.x, pc.y).ToArgb() & 0xffffff; s.Append("Color #").Append(color.ToString("X6")).Append('\n'); } if (ic == ICFlags.Color) { s.Append("Click to capture color.\n"); } else if (ic == ICFlags.Rectangle) { s.Append("Mouse-drag to capture rectangle.\n"); } else if (!canColor) { s.Append("Mouse-drag to capture image.\n"); } else { s.Append("Mouse-drag to capture image,\nor Ctrl+click to capture color.\n"); } s.Append("More: right-click"); //" cancel: key Esc\n retry: key F3 ... F3" text = s.ToString(); } var font = NativeFont_.RegularCached(_dpi); int magnWH = Dpi.Scale(200, _dpi) / 10 * 10; //width and height of the magnified image without borders etc if (_textSize == default) { using (var tr = new FontDC_(font)) _textSize = tr.MeasureDT(text, TFFlags.NOPREFIX); } int width = Math.Max(magnWH, _textSize.width) + 2, height = magnWH + 4 + _textSize.height; using var mb = new MemoryBitmap(width, height); var dc = mb.Hdc; using var wdc = new WindowDC_(_w); //draw frames and color background. Also erase magnifier, need when near screen edges. Api.FillRect(dc, (0, 0, width, height), Api.GetStockObject(4)); //BLACK_BRUSH //copy from captured screen image to magnifier image. Magnify 5 times. int k = magnWH / 10; Api.StretchBlt(dc, 1, 1, magnWH, magnWH, wdc, pc.x - k, pc.y - k, k * 2, k * 2, Api.SRCCOPY); //draw red crosshair k = magnWH / 2; using (var pen = new Pen_(0xff)) { pen.DrawLine(dc, (k, 1), (k, magnWH + 1)); pen.DrawLine(dc, (1, k), (magnWH + 1, k)); } //draw text below magnifier var rc = new RECT(1, magnWH + 2, _textSize.width, _textSize.height); Api.SetTextColor(dc, 0x32CD9A); //Color.YellowGreen Api.SetBkMode(dc, 1); var oldFont = Api.SelectObject(dc, font); Api.DrawText(dc, text, ref rc, TFFlags.NOPREFIX); Api.SelectObject(dc, oldFont); //set magninifier position far from cursor var pm = new POINT(4, 4); _w.MapScreenToClient(ref pm); int xMove = magnWH * 3; if (_magnMoved) { pm.Offset(xMove, 0); } var rm = new RECT(pm.x, pm.y, width, height); rm.Inflate(magnWH / 2, magnWH / 2); if (rm.Contains(pc)) { Api.InvalidateRect(_w, (pm.x, pm.y, width, height)); _magnMoved ^= true; pm.Offset(_magnMoved ? xMove : -xMove, 0); } Api.BitBlt(wdc, pm.x, pm.y, width, height, dc, 0, 0, Api.SRCCOPY); }