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; } }
/// <summary> /// Creates Bitmap from a GDI bitmap. /// </summary> /// <param name="hbitmap">GDI bitmap handle. This function makes its copy.</param> /// <remarks> /// How this function is different from <see cref="Image.FromHbitmap"/>: /// 1. Image.FromHbitmap usually creates bottom-up bitmap, which is incompatible with <see cref="Find"/>. This function creates normal top-down bitmap, like <c>new Bitmap(...)</c>, <c>Bitmap.FromFile(...)</c> etc do. /// 2. This function always creates bitmap of PixelFormat Format32bppRgb. /// </remarks> /// <exception cref="AuException">Failed. For example hbitmap is default(IntPtr).</exception> /// <exception cref="Exception">Exceptions of Bitmap(int, int, PixelFormat) constructor.</exception> public static unsafe Bitmap BitmapFromHbitmap(IntPtr hbitmap) { var bh = new Api.BITMAPINFOHEADER() { biSize = sizeof(Api.BITMAPINFOHEADER) }; using (var dcs = new ScreenDC_(0)) { if (0 == Api.GetDIBits(dcs, hbitmap, 0, 0, null, &bh, 0)) { goto ge; } int wid = bh.biWidth, hei = bh.biHeight; if (hei > 0) { bh.biHeight = -bh.biHeight; } else { hei = -hei; } bh.biBitCount = 32; var R = new Bitmap(wid, hei, PixelFormat.Format32bppRgb); var d = R.LockBits(new Rectangle(0, 0, wid, hei), ImageLockMode.ReadWrite, R.PixelFormat); bool ok = hei == Api.GetDIBits(dcs, hbitmap, 0, hei, (void *)d.Scan0, &bh, 0); R.UnlockBits(d); if (!ok) { R.Dispose(); goto ge; } return(R); } ge: throw new AuException(); }