internal static Bitmap MakeSnapshot(IntPtr parentWinHandle, bool isClientWnd, Win32Api.WindowShowStyle nCmdShow) { if (parentWinHandle == IntPtr.Zero || !Win32Api.IsWindow(parentWinHandle) || !Win32Api.IsWindowVisible(parentWinHandle)) { return(null); } if (Win32Api.IsIconic(parentWinHandle)) { Win32Api.ShowWindow(parentWinHandle, nCmdShow);//show it } if (!Win32Api.SetForegroundWindow(parentWinHandle)) { return(null);//can't bring it to front } Win32Api.ShowWindow(parentWinHandle, Win32Api.WindowShowStyle.ShowMinimized); Win32Api.ShowWindow(parentWinHandle, Win32Api.WindowShowStyle.Restore); var appWndHandle = parentWinHandle; System.Threading.Thread.Sleep(1000);//give it some time to redraw RECT appRect; bool res = Win32Api.GetWindowRect (appWndHandle, out appRect); if (!res || appRect.Height == 0 || appRect.Width == 0) { return(null);//some hidden window } // calculate the app rectangle //Intersect with the Desktop rectangle and get what's visible IntPtr DesktopHandle = Win32Api.GetDesktopWindow(); RECT desktopRect; Win32Api.GetWindowRect(DesktopHandle, out desktopRect); RECT visibleRect; if (!Win32Api.IntersectRect (out visibleRect, ref desktopRect, ref appRect)) { visibleRect = appRect; } if (Win32Api.IsRectEmpty(ref visibleRect)) { return(null); } int Width = visibleRect.Width; int Height = visibleRect.Height; IntPtr hdcTo = IntPtr.Zero; IntPtr hdcFrom = IntPtr.Zero; IntPtr hBitmap = IntPtr.Zero; try { Bitmap result = null; // get device context of the window... hdcFrom = Win32Api.GetDC(appWndHandle); // create dc that we can draw to... hdcTo = Win32Api.CreateCompatibleDC(hdcFrom); hBitmap = Win32Api.CreateCompatibleBitmap(hdcFrom, Width, Height); // validate if (hBitmap != IntPtr.Zero) { // adjust and copy int x = appRect.Left < 0 ? -appRect.Left : 0; int y = appRect.Top < 0 ? -appRect.Top : 0; IntPtr hLocalBitmap = Win32Api.SelectObject(hdcTo, hBitmap); Win32Api.BitBlt(hdcTo, 0, 0, Width, Height, hdcFrom, 0, 0, Win32Api.SRCCOPY); Win32Api.SelectObject(hdcTo, hLocalBitmap); // create bitmap for window image... using (var screenShot = Image.FromHbitmap(hBitmap)) { // For some reason, the area that was reserved for the screenshot is bigger than the actual // result. We remove the black borders to the right and bottom here result = CropBitmap(screenShot); } } return(result); } finally { // release the unmanaged resources if (hdcFrom != IntPtr.Zero) { Win32Api.ReleaseDC(appWndHandle, hdcFrom); } if (hdcTo != IntPtr.Zero) { Win32Api.DeleteDC(hdcTo); } if (hBitmap != IntPtr.Zero) { Win32Api.DeleteObject(hBitmap); } } }
/// <summary> /// Erzeugt einen Screenshot dieses Fensters. /// </summary> /// <param name="isClientWnd">Handelt es sich um das Handle eines Client-Fensters oder nícht.</param> /// <param name="nCmdShow">Der WindowShowStyle.</param> /// <param name="timeForRedrawing">Die Zeit, die gewartet werden soll, bis der Screenshot gemacht wird.</param> /// <returns>Der Screenshot oder <see langword="null" />, wenn nicht ermittelbar.</returns> public Bitmap MakeScreenshot(bool isClientWnd = false, Win32Api.WindowShowStyle nCmdShow = Win32Api.WindowShowStyle.Restore, TimeSpan?timeForRedrawing = null) { var appWndHandle = this.HWnd; if (appWndHandle == IntPtr.Zero || !Win32Api.IsWindow(appWndHandle) || !Win32Api.IsWindowVisible(appWndHandle)) { return(null); } if (Win32Api.IsIconic(appWndHandle)) { Win32Api.ShowWindow(appWndHandle, nCmdShow); // show it } if (!Win32Api.SetForegroundWindow(appWndHandle)) { return(null); // can't bring it to front } if (timeForRedrawing.HasValue) { // give it some time to redraw Thread.Sleep(timeForRedrawing.Value); } RECT appRect; var res = isClientWnd ? Win32Api.GetClientRect(appWndHandle, out appRect) : Win32Api.GetWindowRect(appWndHandle, out appRect); if (!res || appRect.Height == 0 || appRect.Width == 0) { return(null); // some hidden window } if (isClientWnd) { var lt = new Point(appRect.Left, appRect.Top); var rb = new Point(appRect.Right, appRect.Bottom); Win32Api.ClientToScreen(appWndHandle, ref lt); Win32Api.ClientToScreen(appWndHandle, ref rb); appRect.Left = lt.X; appRect.Top = lt.Y; appRect.Right = rb.X; appRect.Bottom = rb.Y; } // intersect with the Desktop rectangle and get what's visible var desktopHandle = Win32Api.GetDesktopWindow(); RECT desktopRect; Win32Api.GetWindowRect(desktopHandle, out desktopRect); RECT visibleRect; if (!Win32Api.IntersectRect(out visibleRect, ref desktopRect, ref appRect)) { visibleRect = appRect; } if (Win32Api.IsRectEmpty(ref visibleRect)) { return(null); } var width = visibleRect.Width; var height = visibleRect.Height; var hdcTo = IntPtr.Zero; var hdcFrom = IntPtr.Zero; var hBitmap = IntPtr.Zero; try { Bitmap clsRet = null; // get device context of the window... hdcFrom = isClientWnd ? Win32Api.GetDC(appWndHandle) : Win32Api.GetWindowDC(appWndHandle); // create dc that we can draw to... hdcTo = Win32Api.CreateCompatibleDC(hdcFrom); hBitmap = Win32Api.CreateCompatibleBitmap(hdcFrom, width, height); // validate... if (hBitmap != IntPtr.Zero) { // copy... var x = appRect.Left < 0 ? -appRect.Left : 0; var y = appRect.Top < 0 ? -appRect.Top : 0; var hLocalBitmap = Win32Api.SelectObject(hdcTo, hBitmap); Win32Api.BitBlt(hdcTo, 0, 0, width, height, hdcFrom, x, y, Win32Api.SRCCOPY); Win32Api.SelectObject(hdcTo, hLocalBitmap); // create bitmap for window image... clsRet = System.Drawing.Image.FromHbitmap(hBitmap); } return(clsRet); } finally { // release... if (hdcFrom != IntPtr.Zero) { Win32Api.ReleaseDC(appWndHandle, hdcFrom); } if (hdcTo != IntPtr.Zero) { Win32Api.DeleteDC(hdcTo); } if (hBitmap != IntPtr.Zero) { Win32Api.DeleteObject(hBitmap); } } }