Repository navigation
Conversation
OnPaint cleared the control with this.Parent.BackColor. That was wrong in three ways. It ignored the control's own BackColor, which is the property a consumer sets to say what the switch is sitting on, so setting it did nothing. It required a parent to exist at paint time, so rendering an unparented instance - DrawToBitmap, or some designer hosting - threw. And it blacked out the corners the rounded switch does not reach whenever the parent's BackColor was Color.Transparent, because clearing with a transparent colour writes it into the double buffer rather than letting anything through. That went unnoticed while the switch itself defaulted to black, since the black corners and the black switch were indistinguishable; it appears the moment a consumer gives the switch a colour of its own. Nothing needs to be cleared here. AllPaintingInWmPaint has the background painted from BackColor immediately before OnPaint runs. BackColor is ambient, so a consumer that has not set one still gets the parent's colour and nothing changes for them; one that has set it now gets what it asked for. SupportsTransparentBackColor is added alongside, so BackColor can be set to Color.Transparent and have whatever the control sits on show through the corners properly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0153VVkWg7DQmdaNLcvtY37w
…ggle Two faults in the geometry, both of which only became visible once the switch was given a colour of its own. The background stopped two pixels short of the control's right edge, so a sliver of the control was left uncovered beside the rounded end and showed as a notch hanging off the corner. The rounded ends are now as wide as the control is tall and the right one ends on the last pixel, so the background fills the control. The toggle's size and its position were set from separate expressions that did not agree: it was inset two pixels from the top and the left, but its diameter left it four pixels short of the right end of the background, and the checked position put it two pixels from that end instead. The gap on the side the toggle had travelled to came out narrower than the others, and a gap of a pixel or two, once antialiasing has taken its share, reads as the toggle breaking out of the background rather than sitting in it. Both the diameter and the two positions now come from one inset, so the gap is the same on every side and the two states are mirror images of each other. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0153VVkWg7DQmdaNLcvtY37w
Removing the clear from OnPaint went one step too far. The reasoning was that AllPaintingInWmPaint has the background painted before OnPaint runs, which is true of Control but not of ButtonBase: ButtonBase paints its own background from OnPaint, by way of the renderer it runs from there, and this override replaces that. Nothing was left clearing the surface. The previous frame therefore stayed underneath, and every repaint blended the new switch's antialiased edge over the old one. Switching the toggle on left a grey fringe of the off state's track hanging outside the blue, one pixel clear of it, following the curve of the rounded end. It was measurable as neutral grey - the switch's own edges blend toward the colour behind them, so anything neutral on a white surface came from somewhere else. The surface is cleared again, from the control's own BackColor rather than the parent's, which is what the original was doing wrong. A consumer that wants what is behind the control to show through sets BackColor to Color.Transparent, and that is handed to the framework to paint. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0153VVkWg7DQmdaNLcvtY37w
There was a problem hiding this comment.
🟡 Changes recommended
AssemblyInformationalVersion remains at 1.0.0, leaving the user-visible/release-tag version inconsistent with the bumped 1.0.1.0 version.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR fixes rendering issues in ToggleButton when using non-default colors by properly clearing/painting the background surface (including transparent scenarios) and by making the track/toggle geometry consistent so the toggle sits evenly inside the background in both states.
Changes:
- Paint/clear the control surface using the control’s own
BackColor, enabling proper transparent-corner behavior viaSupportsTransparentBackColor. - Adjust background path geometry to reach the right edge and unify toggle sizing/positioning via a single inset.
- Bump assembly version/file version to
1.0.1.0.
File summaries
| File | Description |
|---|---|
| ToggleButton.cs | Fixes background clearing behavior and corrects track/toggle geometry so drawing is consistent with non-black colors and transparent backgrounds. |
| Properties/AssemblyInfo.cs | Updates assembly versioning for the 1.0.1.0 release. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| [assembly: AssemblyFileVersion("1.0.1.0")] | ||
|
|
||
| // The version reported to users, and the version the release tag must match | ||
| [assembly: AssemblyInformationalVersion("1.0.0")] |
The release workflow reads AssemblyInformationalVersion, not AssemblyVersion, and refuses to build a tag that disagrees with it. Only the other two were bumped with the fix, so a v1.0.1 tag would have been rejected as not matching the assembly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0153VVkWg7DQmdaNLcvtY37w
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three faults in how
ToggleButtondraws itself, all found by giving the switch a colour other than the blackit defaults to. The first two had been there since the original implementation and were invisible while the
switch was black; the third was introduced fixing the first, in this same branch.
Black corners
OnPaintcleared the control withthis.Parent.BackColor. That was wrong three ways: it ignored thecontrol's own
BackColor, which is the property a consumer sets to say what the switch is sitting on, sosetting it did nothing; it required a parent to exist at paint time, so rendering an unparented instance
threw; and it turned the corners the rounded switch does not reach black whenever the parent's
BackColorwasColor.Transparent, because clearing with a transparent colour writes it into the doublebuffer rather than letting anything through.
The clear now comes from the control's own
BackColor.SupportsTransparentBackColoris added alongside, soa consumer can set
BackColor = Color.Transparentand have whatever the control sits on show throughproperly.
A notch off the corner, and a toggle that looked to have escaped
The background stopped two pixels short of the control's right edge, leaving a sliver of the control
uncovered beside the rounded end, which showed as a notch hanging off the corner.
Separately, the toggle's size and its position came from expressions that did not agree: it was inset two
pixels from the top and the left, but its diameter left it four pixels short of the right end of the
background, and the checked position put it two pixels from that end instead. The gap on the side the toggle
had travelled to came out narrower than the others, and a gap of a pixel or two, once antialiasing has taken
its share, reads as the toggle breaking out of the background rather than sitting in it.
Both the diameter and the two positions now come from one inset, so the gap is the same on every side and
the two states are mirror images of each other.
A fringe of the previous frame
Removing the clear in the first commit went one step too far. The reasoning was that
AllPaintingInWmPainthas the background painted before
OnPaintruns — true ofControl, but not ofButtonBase, which paintsits own background from
OnPaint, by way of the renderer it runs there. This control's override replacesthat, so nothing was left clearing the surface.
The previous frame therefore stayed underneath, and every repaint blended the new switch's antialiased edge
over the old one. Switching the toggle on left a grey fringe of the off state's track hanging outside the
blue, one pixel clear of it, following the curve of the rounded end.
Verification
There are no tests in this repository, so this was verified by driving the consumer that uncovered it. Read
straight out of the bitmap, along the middle row of a 71-pixel-wide control:
Exact mirror images, and no neutral-grey pixel anywhere in the switch — the switch's own antialiased edges
blend toward the colour behind them, so on a white surface anything neutral had come from somewhere else.
The disabled state was checked separately for any blue left over from the previous frame: none.
Version
AssemblyVersionandAssemblyFileVersionare bumped to1.0.1.0. The release workflow requires the tag tobe reachable from
master, so a release can be cut once this lands.🤖 Generated with Claude Code
https://claude.ai/code/session_0153VVkWg7DQmdaNLcvtY37w