private DrawingGroup GetDrawingHelper() { DrawingGroup drawingGroup = null; if (_hwnd.Handle != IntPtr.Zero && UnsafeNativeMethods.IsWindow(_hwnd)) { NativeMethods.RECT rc = new NativeMethods.RECT(); SafeNativeMethods.GetWindowRect(_hwnd, ref rc); int width = rc.right - rc.left; int height = rc.bottom - rc.top; HandleRef hdcScreen = new HandleRef(this, UnsafeNativeMethods.GetDC(new HandleRef(this, IntPtr.Zero))); if (hdcScreen.Handle != IntPtr.Zero) { HandleRef hdcBitmap = new HandleRef(this, IntPtr.Zero); HandleRef hBitmap = new HandleRef(this, IntPtr.Zero); try { hdcBitmap = new HandleRef(this, UnsafeNativeMethods.CriticalCreateCompatibleDC(hdcScreen)); if (hdcBitmap.Handle != IntPtr.Zero) { hBitmap = new HandleRef(this, UnsafeNativeMethods.CriticalCreateCompatibleBitmap(hdcScreen, width, height)); if (hBitmap.Handle != IntPtr.Zero) { // Select the bitmap into the DC so that we draw to it. IntPtr hOldBitmap = UnsafeNativeMethods.CriticalSelectObject(hdcBitmap, hBitmap.Handle); try { // Clear the bitmap to white (so we don't waste toner printing a black bitmap something fails). NativeMethods.RECT rcPaint = new NativeMethods.RECT(0, 0, width, height); IntPtr hbrWhite = UnsafeNativeMethods.CriticalGetStockObject(NativeMethods.WHITE_BRUSH); UnsafeNativeMethods.CriticalFillRect(hdcBitmap.Handle, ref rcPaint, hbrWhite); // First try to use the PrintWindow API. bool result = UnsafeNativeMethods.CriticalPrintWindow(_hwnd, hdcBitmap, 0); if (result == false) { // Fall back to sending a WM_PRINT message to the window. // // Note: there are known cases where WM_PRINT is not implemented // to provide visual parity with WM_PAINT. However, since the // GetDrawing method is virtual, the derived class can override // this default implementation and provide a better implementation. UnsafeNativeMethods.SendMessage(_hwnd.Handle, WindowMessage.WM_PRINT, hdcBitmap.Handle, (IntPtr)(NativeMethods.PRF_CHILDREN | NativeMethods.PRF_CLIENT | NativeMethods.PRF_ERASEBKGND | NativeMethods.PRF_NONCLIENT)); } else { // There is a know issue where calling PrintWindow on a window will // clear all dirty regions (but since it is redirected, the screen // won't be updated). As a result we can leave unpainted pixels on // the screen if PrintWindow is called when the window was dirty. // // To fix this, we just force the child window to repaint. // UnsafeNativeMethods.CriticalRedrawWindow(_hwnd, IntPtr.Zero, IntPtr.Zero, NativeMethods.RDW_INVALIDATE | NativeMethods.RDW_ALLCHILDREN); } // Create a DrawingGroup that only contains an ImageDrawing that wraps the bitmap. drawingGroup = new DrawingGroup(); System.Windows.Media.Imaging.BitmapSource bitmapSource = Imaging.CriticalCreateBitmapSourceFromHBitmap(hBitmap.Handle, IntPtr.Zero, Int32Rect.Empty, null, WICBitmapAlphaChannelOption.WICBitmapIgnoreAlpha); Rect rectElement = new Rect(RenderSize); drawingGroup.Children.Add(new ImageDrawing(bitmapSource, rectElement)); drawingGroup.Freeze(); } finally { // Put the old bitmap back into the DC. UnsafeNativeMethods.CriticalSelectObject(hdcBitmap, hOldBitmap); } } } } finally { UnsafeNativeMethods.ReleaseDC(new HandleRef(this, IntPtr.Zero), hdcScreen); hdcScreen = new HandleRef(null, IntPtr.Zero); if (hBitmap.Handle != IntPtr.Zero) { UnsafeNativeMethods.DeleteObject(hBitmap); hBitmap = new HandleRef(this, IntPtr.Zero); } if (hdcBitmap.Handle != IntPtr.Zero) { UnsafeNativeMethods.CriticalDeleteDC(hdcBitmap); hdcBitmap = new HandleRef(this, IntPtr.Zero); } } } } return(drawingGroup); }
private DrawingGroup GetDrawingHelper() { SecurityHelper.DemandUIWindowPermission(); DrawingGroup drawingGroup = null; if (this._hwnd.Handle != IntPtr.Zero && UnsafeNativeMethods.IsWindow(this._hwnd)) { NativeMethods.RECT rect = default(NativeMethods.RECT); SafeNativeMethods.GetWindowRect(this._hwnd, ref rect); int num = rect.right - rect.left; int num2 = rect.bottom - rect.top; HandleRef hDC = new HandleRef(this, UnsafeNativeMethods.GetDC(new HandleRef(this, IntPtr.Zero))); if (hDC.Handle != IntPtr.Zero) { HandleRef handleRef = new HandleRef(this, IntPtr.Zero); HandleRef hObject = new HandleRef(this, IntPtr.Zero); try { handleRef = new HandleRef(this, UnsafeNativeMethods.CriticalCreateCompatibleDC(hDC)); if (handleRef.Handle != IntPtr.Zero) { hObject = new HandleRef(this, UnsafeNativeMethods.CriticalCreateCompatibleBitmap(hDC, num, num2)); if (hObject.Handle != IntPtr.Zero) { IntPtr obj = UnsafeNativeMethods.CriticalSelectObject(handleRef, hObject.Handle); try { NativeMethods.RECT rect2 = new NativeMethods.RECT(0, 0, num, num2); IntPtr brush = UnsafeNativeMethods.CriticalGetStockObject(0); UnsafeNativeMethods.CriticalFillRect(handleRef.Handle, ref rect2, brush); if (!UnsafeNativeMethods.CriticalPrintWindow(this._hwnd, handleRef, 0)) { UnsafeNativeMethods.SendMessage(this._hwnd.Handle, WindowMessage.WM_PRINT, handleRef.Handle, (IntPtr)30); } else { UnsafeNativeMethods.CriticalRedrawWindow(this._hwnd, IntPtr.Zero, IntPtr.Zero, 129); } drawingGroup = new DrawingGroup(); BitmapSource imageSource = Imaging.CriticalCreateBitmapSourceFromHBitmap(hObject.Handle, IntPtr.Zero, Int32Rect.Empty, null, WICBitmapAlphaChannelOption.WICBitmapIgnoreAlpha); Rect rect3 = new Rect(base.RenderSize); drawingGroup.Children.Add(new ImageDrawing(imageSource, rect3)); drawingGroup.Freeze(); } finally { UnsafeNativeMethods.CriticalSelectObject(handleRef, obj); } } } } finally { UnsafeNativeMethods.ReleaseDC(new HandleRef(this, IntPtr.Zero), hDC); hDC = new HandleRef(null, IntPtr.Zero); if (hObject.Handle != IntPtr.Zero) { UnsafeNativeMethods.DeleteObject(hObject); hObject = new HandleRef(this, IntPtr.Zero); } if (handleRef.Handle != IntPtr.Zero) { UnsafeNativeMethods.CriticalDeleteDC(handleRef); handleRef = new HandleRef(this, IntPtr.Zero); } } } } return(drawingGroup); }