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)) { } }
/// <summary> /// The AdornerWindow intercepts all designer-related messages and forwards them to the BehaviorService /// for appropriate actions. Note that Paint and HitTest messages are correctly parsed and translated /// to AdornerWindow coords. /// </summary> protected override void WndProc(ref Message m) { //special test hooks if (m.Msg == (int)WM_GETALLSNAPLINES) { _behaviorService.TestHook_GetAllSnapLines(ref m); } else if (m.Msg == (int)WM_GETRECENTSNAPLINES) { _behaviorService.TestHook_GetRecentSnapLines(ref m); } switch ((User32.WM)m.Msg) { case User32.WM.PAINT: { // Stash off the region we have to update. using var hrgn = new Gdi32.RegionScope(0, 0, 0, 0); User32.GetUpdateRgn(m.HWnd, hrgn, BOOL.TRUE); // The region we have to update in terms of the smallest rectangle that completely encloses // the update region of the window gives us the clip rectangle. RECT clip = new RECT(); User32.GetUpdateRect(m.HWnd, ref clip, BOOL.TRUE); Rectangle paintRect = clip; using Region region = hrgn.CreateGdiPlusRegion(); // Call the base class to do its painting. DefWndProc(ref m); // Now do our own painting. using Graphics g = Graphics.FromHwnd(m.HWnd); using PaintEventArgs pevent = new PaintEventArgs(g, paintRect); g.Clip = region; _behaviorService.PropagatePaint(pevent); break; } case User32.WM.NCHITTEST: Point pt = new Point( (short)PARAM.LOWORD(m.LParam), (short)PARAM.HIWORD(m.LParam)); var pt1 = new Point(); User32.MapWindowPoints(IntPtr.Zero, Handle, ref pt1, 1); pt.Offset(pt1.X, pt1.Y); if (_behaviorService.PropagateHitTest(pt) && !ProcessingDrag) { m.Result = (IntPtr)User32.HT.TRANSPARENT; } else { m.Result = (IntPtr)User32.HT.CLIENT; } break; case User32.WM.CAPTURECHANGED: base.WndProc(ref m); _behaviorService.OnLoseCapture(); break; default: base.WndProc(ref m); break; } }
public unsafe void Update(bool timerCaused) { IconRegion iconRegion = _provider.Region; Size size = iconRegion.Size; _windowBounds = Rectangle.Empty; for (int i = 0; i < _items.Count; i++) { ControlItem item = _items[i]; Rectangle iconBounds = item.GetIconBounds(size); if (_windowBounds.IsEmpty) { _windowBounds = iconBounds; } else { _windowBounds = Rectangle.Union(_windowBounds, iconBounds); } } using var windowRegion = new Region(new Rectangle(0, 0, 0, 0)); for (int i = 0; i < _items.Count; i++) { ControlItem item = _items[i]; Rectangle iconBounds = item.GetIconBounds(size); iconBounds.X -= _windowBounds.X; iconBounds.Y -= _windowBounds.Y; bool showIcon = true; if (!item.ToolTipShown) { switch (_provider.BlinkStyle) { case ErrorBlinkStyle.NeverBlink: // always show icon break; case ErrorBlinkStyle.BlinkIfDifferentError: showIcon = (item.BlinkPhase == 0) || (item.BlinkPhase > 0 && (item.BlinkPhase & 1) == (i & 1)); break; case ErrorBlinkStyle.AlwaysBlink: showIcon = ((i & 1) == 0) == _provider._showIcon; break; } } if (showIcon) { iconRegion.Region.Translate(iconBounds.X, iconBounds.Y); windowRegion.Union(iconRegion.Region); iconRegion.Region.Translate(-iconBounds.X, -iconBounds.Y); } if (_tipWindow is not null) { ComCtl32.TTF flags = ComCtl32.TTF.SUBCLASS; if (_provider.RightToLeft) { flags |= ComCtl32.TTF.RTLREADING; } var toolInfo = new ComCtl32.ToolInfoWrapper <ErrorWindow>(this, item.Id, flags, item.Error, iconBounds); toolInfo.SendMessage(_tipWindow, (User32.WM)ComCtl32.TTM.SETTOOLINFOW); } if (timerCaused && item.BlinkPhase > 0) { item.BlinkPhase--; } } if (timerCaused) { _provider._showIcon = !_provider._showIcon; } using var hdc = new User32.GetDcScope(Handle); using var save = new Gdi32.SaveDcScope(hdc); MirrorDcIfNeeded(hdc); using Graphics g = hdc.CreateGraphics(); using var windowRegionHandle = new Gdi32.RegionScope(windowRegion, g); if (User32.SetWindowRgn(this, windowRegionHandle, BOOL.TRUE) != 0) { // The HWnd owns the region. windowRegionHandle.RelinquishOwnership(); } User32.SetWindowPos( new HandleRef(this, Handle), User32.HWND_TOP, _windowBounds.X, _windowBounds.Y, _windowBounds.Width, _windowBounds.Height, User32.SWP.NOACTIVATE); User32.InvalidateRect(new HandleRef(this, Handle), null, BOOL.FALSE); }
public unsafe DCMapping(IntPtr hDC, Rectangle bounds) { if (hDC == IntPtr.Zero) { throw new ArgumentNullException(nameof(hDC)); } bool success; _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. 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 { // Create an empty region oriented at 0,0 so we can populate it with the original clipping region of the hDC passed in. var hOriginalClippingRegion = new Gdi32.RegionScope(0, 0, 0, 0); Debug.Assert(!hOriginalClippingRegion.IsNull, "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) 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. 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)) { _dc.RestoreHdc(); _dc.Dispose(); } }