protected override void OnPaint(PaintEventArgs e) { // I could use a Graphics.Save() / Restore() but I figure storing only the Clip is more efficient... Region originalRegion = e.Graphics.Clip.Clone(); if (HasBorder && RectangleIntersectsWithBorder(e.ClipRectangle)) { e.Graphics.SetClip(ContentSurfaceWithScrolls, CombineMode.Exclude); PaintBorderRegion(e.Graphics); e.Graphics.Clip = originalRegion; } // to be more precise, we could use originalRegion.IsVisible(ContentSurface) here, but the dotnet framework // doesn't actually call GetUpdateRgn to get the real update region. Instead, we just get e.ClipRectangle that is the // bounds of the update region and the e.Graphics.Clip is equals to this ClipRectangle // So... TLDR : we will always get a rectangle to update, never a complex region if (ContentSurface.IntersectsWith(e.ClipRectangle)) { e.Graphics.SetClip(ContentSurface, CombineMode.Intersect); PaintContentSurface(e.Graphics); e.Graphics.Clip = originalRegion; } PaintScrollBars(e, originalRegion); }
/// <summary> /// Handle mouse double click to select word under the mouse. /// </summary> protected override void OnMouseDoubleClick(MouseEventArgs e) { base.OnMouseDoubleClick(e); if (ContentSurface.Contains(e.Location)) { _htmlContainer?.HandleMouseDoubleClick(this, e); } }
/// <summary> /// Handle mouse up to handle selection and link click. /// </summary> protected override void OnMouseUp(MouseEventArgs e) { if (ContentSurface.Contains(e.Location)) { OnMouseClick(e); } _htmlContainer?.HandleMouseUp(this, e); base.OnMouseUp(e); }
/// <summary> /// Handle mouse move to handle hover cursor and text selection. /// </summary> protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (ContentSurface.Contains(e.Location)) { _htmlContainer?.HandleMouseMove(this, e); } else { Cursor = DefaultCursor; } }