예제 #1
0
        protected IntPtr CombineRgn(IntPtr hrgnSrc1, IntPtr hrgnSrc2, int fnCombineMode)
        {
            IntPtr hRegion = Gdi32.CreateRectRgn(Rectangle.Empty);

            Gdi32.CombineRgn(hRegion, hrgnSrc1, hrgnSrc2, fnCombineMode);
            return(hRegion);
        }
예제 #2
0
        /// <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);
                }
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        /// <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);
            }
        }
예제 #5
0
        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);
        }
예제 #6
0
            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.");
                    }
                }
            }
예제 #7
0
        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))
            {
            }
        }
예제 #8
0
 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));
 }