/// <summary> /// Highlights the specified window just like Spy++ /// </summary> /// <param name="hWnd"></param> public static void Highlight(IntPtr hWnd) { const float penWidth = 30; WinApi.User32.RECT clientRect = new WinApi.User32.RECT(); WinApi.User32.RECT windowRect = new WinApi.User32.RECT(); Point clientPoint = new Point(); WinApi.User32.GetClientRect(hWnd, ref clientRect); WinApi.User32.GetWindowRect(hWnd, ref windowRect); WinApi.User32.ClientToScreen(hWnd, ref clientPoint); clientRect.left = (int)clientPoint.X - windowRect.left; clientRect.top = (int)clientPoint.Y - windowRect.top; clientRect.right += clientRect.left; clientRect.bottom += clientRect.top; IntPtr hDC = WinApi.User32.GetWindowDC(hWnd); if (hDC != IntPtr.Zero) { using (Pen pen = new Pen(Color.Blue, penWidth)) { using (Graphics g = Graphics.FromHdc(hDC)) { g.DrawRectangle(pen, clientRect.left, clientRect.top, clientRect.Width, clientRect.Height); } } } WinApi.User32.ReleaseDC(hWnd, hDC); }
// TODO: Try http://msdn.microsoft.com/en-us/library/windows/desktop/dd144873%28v=vs.85%29.aspx public ImageData CaptureWindow(IntPtr windowHandle) { try { ImageData imageData = new ImageData {Data = null}; #region GetWindowRect var windowRect = new WinApi.User32.RECT(); WinApi.User32.GetWindowRect(windowHandle, ref windowRect); int width = windowRect.Width; int height = windowRect.Height; imageData.WindowRect = new CollabPacket.BoundingBox { Top = windowRect.top, Bottom = windowRect.bottom, Left = windowRect.left, Right = windowRect.right }; #endregion // Create and setup the bitmap IntPtr displayDc = WinApi.User32.GetWindowDC(windowHandle); // Setup the bitmap IntPtr bitmapDc = WinApi.Gdi32.CreateCompatibleDC(displayDc); IntPtr bitmap = WinApi.Gdi32.CreateCompatibleBitmap(displayDc, width, height); IntPtr nullBitmap = WinApi.Gdi32.SelectObject(bitmapDc, bitmap); IntPtr windowDc = WinApi.User32.GetWindowDC(windowHandle); // Copy data from the windowDC to the bitmapDC // startx, starty, endx, endy, cropx, cropy WinApi.Gdi32.BitBlt(bitmapDc, 0, 0, width, height, windowDc, 0, 0, WinApi.Gdi32.SRCCOPY /*| WinApi.Gdi32.CAPTUREBLT*/); WinApi.User32.ReleaseDC(windowHandle, windowDc); WinApi.Gdi32.SelectObject(bitmapDc, nullBitmap); WinApi.Gdi32.DeleteDC(bitmapDc); // Get a Bitmap object from the bitmap's handle _newImage = Image.FromHbitmap(bitmap); // Delete bitmap and release the Display DC WinApi.Gdi32.DeleteObject(bitmap); WinApi.User32.ReleaseDC(windowHandle, displayDc); if (_previousImage != null) { // Check if the window/source has been resized and call a PrintWindow to repaint the borders via forcing a WM_PAINT if (_previousImage.Width != _newImage.Width || _previousImage.Height != _newImage.Height ||_previousImage.PixelFormat != _newImage.PixelFormat) { WinApi.User32.PrintWindow(windowHandle, windowDc, 0); } imageData.BoundingBox = ImageManipulation.GetBoundingBoxForChanges(ref _previousImage, ref _newImage); if (imageData.BoundingBox == Rectangle.Empty) { return imageData; } Bitmap b = new Bitmap(imageData.BoundingBox.Width, imageData.BoundingBox.Height); using (var g = Graphics.FromImage(b)) { // TODO: try performance of both methods g.DrawImage(_newImage, 0, 0, imageData.BoundingBox, GraphicsUnit.Pixel); //g.DrawImage(_newImage, -_boundingBox.X, -_boundingBox.Y); } _previousImage = _newImage; using (var ms = new MemoryStream()) { b.Save(ms, ImageFormatSetting); b.Dispose(); imageData.Data = ms.ToArray(); return imageData; } } _previousImage = _newImage; imageData.BoundingBox = new Rectangle(0, 0, _newImage.Width, _newImage.Height); using (var ms = new MemoryStream()) { _newImage.Save(ms, ImageFormatSetting); imageData.Data = ms.ToArray(); return imageData; } } catch (Exception ex) { Globals.DebugConsole.Log("GDI Error: " + ex.Message); ImageData imageData = new ImageData {Data = Encoding.UTF8.GetBytes("ERROR")}; return imageData; } }
// This is something I've been working on reading WinApi docs.. it doesnt use BitBlt at all. Trying to get borders to show on Vista+ // This uses PrintWindow instead of BitBlt public byte[] CaptureWindowVista(IntPtr windowHandle, ImageFormat format) { try { // Initalize variables IntPtr displayDC; // IntPtr windowDC; // Get the window's size. var windowRect = new WinApi.User32.RECT(); WinApi.User32.GetWindowRect(windowHandle, ref windowRect); var width = windowRect.right - windowRect.left; var height = windowRect.bottom - windowRect.top; // Create and setup the bitmap displayDC = WinApi.User32.GetWindowDC(windowHandle); // Setup the bitmap var bitmapDC = WinApi.Gdi32.CreateCompatibleDC(displayDC); var bitmap = WinApi.Gdi32.CreateCompatibleBitmap(displayDC, width, height); var nullBitmap = WinApi.Gdi32.SelectObject(bitmapDC, bitmap); //windowDC = contentsOnly ? WinApi.User32.GetDC(windowHandle) : WinApi.User32.GetWindowDC(windowHandle); // Copy data from the windowDC to the bitmapDC // startx, starty, endx, endy, cropx, cropy WinApi.User32.PrintWindow(windowHandle, bitmapDC, 0); //WinApi.Gdi32.BitBlt(bitmapDC, 0, 0, width, height, windowDC, 0, 0, WinApi.Gdi32.SRCCOPY | WinApi.Gdi32.CAPTUREBLT); // Cleanup windowDC, bitmapDC //WinApi.User32.ReleaseDC(windowHandle, windowDC); WinApi.Gdi32.SelectObject(bitmapDC, nullBitmap); WinApi.Gdi32.DeleteDC(bitmapDC); // Get a Bitmap object from the bitmap's handle var img = Bitmap.FromHbitmap(bitmap); // Delete the bitmap and release the WinApi.Gdi32.DeleteObject(bitmap); WinApi.User32.ReleaseDC(windowHandle, displayDC); using (var ms = new MemoryStream()) { img.Save(ms, format); img.Dispose(); return ms.ToArray(); } } catch (Exception ex) { Globals.DebugConsole.Log("GDI Error: " + ex.Message); return null; } }