protected IntPtr CombineRgn(IntPtr hrgnSrc1, IntPtr hrgnSrc2, int fnCombineMode) { IntPtr hRegion = Gdi32.CreateRectRgn(Rectangle.Empty); Gdi32.CombineRgn(hRegion, hrgnSrc1, hrgnSrc2, fnCombineMode); return(hRegion); }
/// <summary> /// This code is required to set the correct window region during the resize of the Form at design time. /// There is case when the form contains a MainMenu and also has IsMdiContainer property set, in which, the MdiClient fails to /// resize and hence draw the correct backcolor. /// </summary> private void SetWindowRgn() { IntPtr rgn1 = IntPtr.Zero; IntPtr rgn2 = IntPtr.Zero; RECT rect = new RECT(); CreateParams cp = CreateParams; AdjustWindowRectEx(ref rect, cp.Style, false, cp.ExStyle); Rectangle bounds = Bounds; rgn1 = Gdi32.CreateRectRgn(0, 0, bounds.Width, bounds.Height); try { rgn2 = Gdi32.CreateRectRgn( -rect.left, -rect.top, bounds.Width - rect.right, bounds.Height - rect.bottom); try { if (rgn1 == IntPtr.Zero || rgn2 == IntPtr.Zero) { throw new InvalidOperationException(SR.ErrorSettingWindowRegion); } if (Gdi32.CombineRgn(rgn1, rgn1, rgn2, Gdi32.CombineMode.RGN_DIFF) == 0) { throw new InvalidOperationException(SR.ErrorSettingWindowRegion); } if (UnsafeNativeMethods.SetWindowRgn(new HandleRef(this, Handle), new HandleRef(null, rgn1), true) == 0) { throw new InvalidOperationException(SR.ErrorSettingWindowRegion); } else { // The hwnd now owns the region. rgn1 = IntPtr.Zero; } } finally { if (rgn2 != IntPtr.Zero) { Gdi32.DeleteObject(rgn2); } } } finally { if (rgn1 != IntPtr.Zero) { Gdi32.DeleteObject(rgn1); } } }
public static void DrawDragRectangles(Rectangle[] newRects, int indent) { if (newRects.Length > 0) { // Create the first region IntPtr newRegion = CreateRectangleRegion(newRects[0], indent); for (int index = 1; index < newRects.Length; index++) { // Create the extra region IntPtr extraRegion = CreateRectangleRegion(newRects[index], indent); // Remove the intersection of the existing and extra regions Gdi32.CombineRgn(newRegion, newRegion, extraRegion, (int)Win32.CombineFlags.RGN_XOR); // Remove unwanted intermediate objects Gdi32.DeleteObject(extraRegion); } // Get hold of the DC for the desktop IntPtr hDC = User32.GetDC(IntPtr.Zero); // Define the area we are allowed to draw into Gdi32.SelectClipRgn(hDC, newRegion); Win32.RECT rectBox = new Win32.RECT(); // Get the smallest rectangle that encloses region Gdi32.GetClipBox(hDC, ref rectBox); IntPtr brushHandler = GetHalfToneBrush(); // Select brush into the device context IntPtr oldHandle = Gdi32.SelectObject(hDC, brushHandler); // Blit to screen using provided pattern brush and invert with existing screen contents Gdi32.PatBlt(hDC, rectBox.left, rectBox.top, rectBox.right - rectBox.left, rectBox.bottom - rectBox.top, (uint)RasterOperations.PATINVERT); // Put old handle back again Gdi32.SelectObject(hDC, oldHandle); // Reset the clipping region Gdi32.SelectClipRgn(hDC, IntPtr.Zero); // Remove unwanted region object Gdi32.DeleteObject(newRegion); // Must remember to release the HDC resource! User32.ReleaseDC(IntPtr.Zero, hDC); } }
/// <summary> /// Draw a themed background element. /// </summary> /// <param name="g">Graphics object reference.</param> /// <param name="draw">Rectangle for drawing.</param> /// <param name="exclude">Rectangle to exclude from drawing.</param> /// <param name="part">Theme part.</param> /// <param name="state">Theme state of part.</param> public void DrawThemeBackground(Graphics g, Rectangle draw, Rectangle exclude, int part, int state) { if (IsControlThemed) { // Create a Win32 version of the drawing Rectangle Win32.RECT drawWin32 = new Win32.RECT(); drawWin32.left = draw.X; drawWin32.top = draw.Y; drawWin32.right = draw.Right; drawWin32.bottom = draw.Bottom; // Create a Win32 version of the clipping Rectangle Win32.RECT excludeWin32 = new Win32.RECT(); excludeWin32.left = exclude.X; excludeWin32.top = exclude.Y; excludeWin32.right = exclude.Right; excludeWin32.bottom = exclude.Bottom; // Get access to the underlying HDC IntPtr hDC = g.GetHdc(); // Make a note of the original clipping region IntPtr hOldClipRgn = IntPtr.Zero; Gdi32.GetClipRgn(hDC, ref hOldClipRgn); // Create region that excludes area from drawing rectangle IntPtr hDrawRgn = Gdi32.CreateRectRgnIndirect(ref drawWin32); IntPtr hExcludeRgn = Gdi32.CreateRectRgnIndirect(ref excludeWin32); Gdi32.CombineRgn(hExcludeRgn, hDrawRgn, hExcludeRgn, (int)CombineFlags.RGN_DIFF); // Define required clipping rectangle Gdi32.SelectClipRgn(hDC, hExcludeRgn); // Perform actual drawing work Uxtheme.DrawThemeBackground(_hTheme, hDC, part, state, ref drawWin32, IntPtr.Zero); // Put clipping region back again Gdi32.SelectClipRgn(hDC, hOldClipRgn); // Delete objects no longer needed Gdi32.DeleteObject(hDrawRgn); Gdi32.DeleteObject(hExcludeRgn); // Must release the resource to prevent leaks! g.ReleaseHdc(hDC); } }
protected static IntPtr CreateRectangleRegion(Rectangle rect, int indent) { Win32.RECT newWinRect = new Win32.RECT(); newWinRect.left = rect.Left; newWinRect.top = rect.Top; newWinRect.right = rect.Right; newWinRect.bottom = rect.Bottom; // Create region for whole of the new rectangle IntPtr newOuter = Gdi32.CreateRectRgnIndirect(ref newWinRect); // If the rectangle is to small to make an inner object from, then just use the outer if ((indent <= 0) || (rect.Width <= indent) || (rect.Height <= indent)) { return(newOuter); } newWinRect.left += indent; newWinRect.top += indent; newWinRect.right -= indent; newWinRect.bottom -= indent; // Create region for the unwanted inside of the new rectangle IntPtr newInner = Gdi32.CreateRectRgnIndirect(ref newWinRect); Win32.RECT emptyWinRect = new Win32.RECT(); emptyWinRect.left = 0; emptyWinRect.top = 0; emptyWinRect.right = 0; emptyWinRect.bottom = 0; // Create a destination region IntPtr newRegion = Gdi32.CreateRectRgnIndirect(ref emptyWinRect); // Remove the intersection of the outer and inner Gdi32.CombineRgn(newRegion, newOuter, newInner, (int)Win32.CombineFlags.RGN_XOR); // Remove unwanted intermediate objects Gdi32.DeleteObject(newOuter); Gdi32.DeleteObject(newInner); // Return the resultant region object return(newRegion); }
public unsafe DCMapping(IntPtr hDC, Rectangle bounds) { if (hDC == IntPtr.Zero) { throw new ArgumentNullException(nameof(hDC)); } bool success; IntPtr hOriginalClippingRegion = IntPtr.Zero; _translatedBounds = bounds; _graphics = null; _dc = DeviceContext.FromHdc(hDC); _dc.SaveHdc(); // Retrieve the x-coordinates and y-coordinates of the viewport origin for the specified device context. success = Gdi32.GetViewportOrgEx(hDC, out Point viewportOrg).IsTrue(); Debug.Assert(success, "GetViewportOrgEx() failed."); // Create a new rectangular clipping region based off of the bounds specified, shifted over by the x & y specified in the viewport origin. IntPtr hClippingRegion = Gdi32.CreateRectRgn(viewportOrg.X + bounds.Left, viewportOrg.Y + bounds.Top, viewportOrg.X + bounds.Right, viewportOrg.Y + bounds.Bottom); Debug.Assert(hClippingRegion != IntPtr.Zero, "CreateRectRgn() failed."); try { // Create an empty region oriented at 0,0 so we can populate it with the original clipping region of the hDC passed in. hOriginalClippingRegion = Gdi32.CreateRectRgn(0, 0, 0, 0); Debug.Assert(hOriginalClippingRegion != IntPtr.Zero, "CreateRectRgn() failed."); // Get the clipping region from the hDC: result = {-1 = error, 0 = no region, 1 = success} per MSDN int result = Gdi32.GetClipRgn(hDC, hOriginalClippingRegion); Debug.Assert(result != -1, "GetClipRgn() failed."); // Shift the viewpoint origint by coordinates specified in "bounds". var lastViewPort = new Point(); success = Gdi32.SetViewportOrgEx(hDC, viewportOrg.X + bounds.Left, viewportOrg.Y + bounds.Top, &lastViewPort).IsTrue(); Debug.Assert(success, "SetViewportOrgEx() failed."); RegionType originalRegionType; if (result != 0) { // Get the origninal clipping region so we can determine its type (we'll check later if we've restored the region back properly.) RECT originalClipRect = new RECT(); originalRegionType = Gdi32.GetRgnBox(hOriginalClippingRegion, ref originalClipRect); Debug.Assert(originalRegionType != RegionType.ERROR, "ERROR returned from SelectClipRgn while selecting the original clipping region.."); if (originalRegionType == RegionType.SIMPLEREGION) { // Find the intersection of our clipping region and the current clipping region (our parent's) // Returns a NULLREGION, the two didn't intersect. // Returns a SIMPLEREGION, the two intersected // Resulting region (stuff that was in hOriginalClippingRegion AND hClippingRegion is placed in hClippingRegion RegionType combineResult = Gdi32.CombineRgn(hClippingRegion, hClippingRegion, hOriginalClippingRegion, Gdi32.CombineMode.RGN_AND); Debug.Assert((combineResult == RegionType.SIMPLEREGION) || (combineResult == RegionType.NULLREGION), "SIMPLEREGION or NULLREGION expected."); } } else { // If there was no clipping region, then the result is a simple region. // We don't need to keep track of the original now, since it is empty. Gdi32.DeleteObject(hOriginalClippingRegion); hOriginalClippingRegion = IntPtr.Zero; originalRegionType = RegionType.SIMPLEREGION; } // Select the new clipping region; make sure it's a SIMPLEREGION or NULLREGION RegionType selectResult = Gdi32.SelectClipRgn(hDC, hClippingRegion); Debug.Assert((selectResult == RegionType.SIMPLEREGION || selectResult == RegionType.NULLREGION), "SIMPLEREGION or NULLLREGION expected."); } catch (Exception ex) when(!ClientUtils.IsSecurityOrCriticalException(ex)) { _dc.RestoreHdc(); _dc.Dispose(); } finally { // Delete the new clipping region, as the clipping region for the HDC is now set // to this rectangle. Hold on to hOriginalClippingRegion, as we'll need to restore // it when this object is disposed. success = Gdi32.DeleteObject(hClippingRegion).IsTrue(); Debug.Assert(success, "DeleteObject(hClippingRegion) failed."); if (hOriginalClippingRegion != IntPtr.Zero) { success = Gdi32.DeleteObject(hOriginalClippingRegion).IsTrue(); Debug.Assert(success, "DeleteObject(hOriginalClippingRegion) failed."); } } }
public unsafe DCMapping(Gdi32.HDC hdc, Rectangle bounds) { ArgumentNullException.ThrowIfNull(hdc); bool success; _hdc = hdc; _savedState = Gdi32.SaveDC(hdc); // Retrieve the x-coordinates and y-coordinates of the viewport origin for the specified device context. success = Gdi32.GetViewportOrgEx(hdc, out Point viewportOrg).IsTrue(); Debug.Assert(success, "GetViewportOrgEx() failed."); // Create a new rectangular clipping region based off of the bounds specified, shifted over by the x & y specified in the viewport origin. var hClippingRegion = new Gdi32.RegionScope( viewportOrg.X + bounds.Left, viewportOrg.Y + bounds.Top, viewportOrg.X + bounds.Right, viewportOrg.Y + bounds.Bottom); Debug.Assert(!hClippingRegion.IsNull, "CreateRectRgn() failed."); try { var hOriginalClippingRegion = new Gdi32.RegionScope(hdc); // Shift the viewpoint origin by coordinates specified in "bounds". var lastViewPort = new Point(); success = Gdi32.SetViewportOrgEx( hdc, viewportOrg.X + bounds.Left, viewportOrg.Y + bounds.Top, &lastViewPort).IsTrue(); Debug.Assert(success, "SetViewportOrgEx() failed."); RegionType originalRegionType; if (!hOriginalClippingRegion.IsNull) { // Get the original clipping region so we can determine its type (we'll check later if we've restored the region back properly.) RECT originalClipRect = new RECT(); originalRegionType = Gdi32.GetRgnBox(hOriginalClippingRegion, ref originalClipRect); Debug.Assert( originalRegionType != RegionType.ERROR, "ERROR returned from SelectClipRgn while selecting the original clipping region.."); if (originalRegionType == RegionType.SIMPLEREGION) { // Find the intersection of our clipping region and the current clipping region (our parent's) RegionType combineResult = Gdi32.CombineRgn( hClippingRegion, hClippingRegion, hOriginalClippingRegion, Gdi32.RGN.AND); Debug.Assert( (combineResult == RegionType.SIMPLEREGION) || (combineResult == RegionType.NULLREGION), "SIMPLEREGION or NULLREGION expected."); } } else { // If there was no clipping region, then the result is a simple region. originalRegionType = RegionType.SIMPLEREGION; } // Select the new clipping region; make sure it's a SIMPLEREGION or NULLREGION RegionType selectResult = Gdi32.SelectClipRgn(hdc, hClippingRegion); Debug.Assert( selectResult == RegionType.SIMPLEREGION || selectResult == RegionType.NULLREGION, "SIMPLEREGION or NULLLREGION expected."); } catch (Exception ex) when(!ClientUtils.IsCriticalException(ex)) { } }
public RegionType CombineRegion(WindowsRegion region1, WindowsRegion region2, Gdi32.CombineMode mode) { return(Gdi32.CombineRgn(new HandleRef(this, HRegion), new HandleRef(region1, region1.HRegion), new HandleRef(region2, region2.HRegion), mode)); }