'Fill a Rectangular with an inflating Circle without crossing its borders (Ripple)

I have a control surface (my custom control) and a drawed rectangular smaller than the whole surface. Now I need to draw a circle (FillEllipse) within this rectangular and the circle must not overdraw the rectangular borders.

I made a ButtonStrip like this one know from Angular: https://material.angular.io/components/button-toggle/overview And want to create such ripples: https://material.angular.io/components/ripple/examples

It is almost perfect. I would like to make such an animation. The filling progress is not a problem, but the fact, that I dont use kinda "child control buttons" in my ButtonStrip and therefore no "real" borders, I struggle with the not"over"drawing the borders of my clicked button.

And no, I will not use child buttons as controls to put into my strip. I dont want this control in control control. I am drawing the buttons and use the rectangulars as "address" for my events like Hover/Click/Clicked etc.

Here is an example of my ButtonStrip (Month is hovered). Day is clicked.

enter image description here

Every Button (in a List or Dictionary) has its own rectangular which is pre calculated:

Dim InnerWidth As Integer = If(_IOSwitchVisible = True,
    (Me.Width - _IOSwitchWidth) \ Buttons.Count,
    Me.Width \ Buttons.Count)

If InnerWidth = 0 Then Return

For Each b In Buttons.Values
    b.Rect = New Rectangle(CurrLeft, 0, InnerWidth, Me.Height)
    VerticalLinePos.Add(CurrLeft)
    CurrLeft += InnerWidth
Next

This is only a part of the code. And here is a snippet how I draw a clicked button (either hovered or not)

'Clicked
For Each btn In Buttons.Values.ToList.Where(Function(x) x.Clicked = True)
    If _HoveredElement IsNot Nothing AndAlso _HoveredElement.Rect = btn.Rect Then
        'If the button is already clicked
        e.Graphics.FillRectangle(New SolidBrush(ClickedHoveredColor), btn.Rect)
    Else
        'Otherwise draw clicked color
        e.Graphics.FillRectangle(New SolidBrush(ClickedColor), btn.Rect)
    End If
Next

Does someone got an idea how to fill one of these buttons with a circle which must not overdraw to its neighbour buttons?

Edit: As soon as I (or you) found out how, I will include a loop to inflate the circle to animate a filling progress.



Solution 1:[1]

Thanks to Jimi I got it working with his Clip hint: enter image description here

(The yellow circle is from ScreenToGif)

Private Sub AnimateRipple(G As Graphics, C As Color, R As Rectangle)
    Dim ClipRegion As New Region(R)
    G.SetClip(ClipRegion, Drawing2D.CombineMode.Replace)

    Dim EllipseRect As Rectangle = R
    EllipseRect.Width = 1
    EllipseRect.Height = 1
    EllipseRect.Y = R.Height \ 2
    EllipseRect.X += R.Width \ 2

    EllipseRect.Inflate(InflateValue, InflateValue)
    Dim RippleBrush As SolidBrush = New SolidBrush(C)
    G.FillEllipse(RippleBrush, EllipseRect)
    G.ResetClip()
    RippleBrush.Dispose()
End Sub

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1