[WINGLESS] Perfect Rounded Rectangle using WinAPI+MSAA !! 02-23-2016, 03:05 AM
#1
Perfect ???
As some of you know, the usual RoundRect function which uses arcs and ellipses to draw roundrectangles is not very efficient. Artifacts can be seen everywhere, and AA sucks with it.
The top left rounded corner is fine, but the rest of them far from fine. So much that the bottom right seems completely dishtinguishable from the top left. Now this is not symmetrical and human eye praises symmetry so, they are bad.
Most of the time you will find yourself compromising to the situation but no more !
![[Image: 35irkmp.png]](http://i64.tinypic.com/35irkmp.png)
See, all the corners are different
What is this MSAA ?
MSAA is a method of anti aliasing used to smooth out jagged lines. In this method, the target image is rendered at a higher resolution than normal, and the shrinked to the original size. Downscaling largely removes aliasing, and the render resolution is, smoother is the image.
WinAPI ?
I saw a function in WinAPI that produces roundrects. Named CreateRoundRectRgn, it takes the bounds of the rectangle and radius of the rounds as parameters, and gives to us a perfectly rounded-rectangle region. You can now use this region as you wish.
MSAA + WinAPI ?
Apparently the region that you create with CreateRoundRectRgn is a very jagged one, with harsh lines everywhere. It may be perfectly round, but actually is far from perfect. So I decided to get the best of both worlds, combine CreateRoundRectRgn with 8x MSAA and Voila ! there it was, the *PERFECT* roundrect.
This one does not have any (normally visible) jagged lines, all the rounds are symmetrical, and with the function I have written, you can draw a roundrect in just one statement, complete with border and fill color. (Set the fill/border color to color.transparent if you do not want them to be showed.)
The function DrawRoundRectangle returns a bitmap which you can draw as in the following example:
Here the base rectangle is rect(5,5,width-10,height-10),
radius is 10 and
MSAA multiplier is 8(x)
Border color is color.fromargb(51,51,51)
Fill Color is color.fromargb(28,28,28)
![[Image: 2wp01uc.png]](http://i65.tinypic.com/2wp01uc.png)
See, a perfect one.
Also, do not forget to use the
G.InterpolationMode=7
(I have not used it in the code) Without it, your borders may be different in width.
As some of you know, the usual RoundRect function which uses arcs and ellipses to draw roundrectangles is not very efficient. Artifacts can be seen everywhere, and AA sucks with it.
The top left rounded corner is fine, but the rest of them far from fine. So much that the bottom right seems completely dishtinguishable from the top left. Now this is not symmetrical and human eye praises symmetry so, they are bad.
Most of the time you will find yourself compromising to the situation but no more !
![[Image: 35irkmp.png]](http://i64.tinypic.com/35irkmp.png)
See, all the corners are different
MSAA+WinAPI to the rescue
What is this MSAA ?
MSAA is a method of anti aliasing used to smooth out jagged lines. In this method, the target image is rendered at a higher resolution than normal, and the shrinked to the original size. Downscaling largely removes aliasing, and the render resolution is, smoother is the image.
WinAPI ?
I saw a function in WinAPI that produces roundrects. Named CreateRoundRectRgn, it takes the bounds of the rectangle and radius of the rounds as parameters, and gives to us a perfectly rounded-rectangle region. You can now use this region as you wish.
MSAA + WinAPI ?
Apparently the region that you create with CreateRoundRectRgn is a very jagged one, with harsh lines everywhere. It may be perfectly round, but actually is far from perfect. So I decided to get the best of both worlds, combine CreateRoundRectRgn with 8x MSAA and Voila ! there it was, the *PERFECT* roundrect.
This one does not have any (normally visible) jagged lines, all the rounds are symmetrical, and with the function I have written, you can draw a roundrect in just one statement, complete with border and fill color. (Set the fill/border color to color.transparent if you do not want them to be showed.)
Code:
Class RoundedRectangle
<DllImport("gdi32.dll")> _
Shared Function CreateRoundRectRgn(ByVal x1 As Integer, ByVal y1 As Integer, ByVal x2 As Integer, ByVal y2 As Integer, ByVal cx As Integer, ByVal cy As Integer) As IntPtr
End Function
Shared Function DrawRoundRectangle(rct As Rectangle, r As Integer, MSAA As Integer, FillColor As Color, BorderColor As Color, Optional BorderWidth As Single = 1)
If MSAA <= 0 Then MSAA = 1
If r <= 0 Then r = 1
Dim b As New Bitmap(rct.Width * MSAA + MSAA, rct.Height * MSAA + MSAA)
Dim g As Graphics = Graphics.FromImage(b)
Dim RegH As IntPtr = CreateRoundRectRgn(rct.Left, rct.Top, (rct.Width) * MSAA, (rct.Height) * MSAA, r * MSAA, r * MSAA)
Dim RegH1 As IntPtr = CreateRoundRectRgn(rct.Left + (MSAA * BorderWidth), rct.Top + (MSAA * BorderWidth), (rct.Width - BorderWidth) * MSAA, (rct.Height - BorderWidth) * MSAA, (r - 2) * MSAA, (r - 2) * MSAA)
Dim Reg As Region = Region.FromHrgn(RegH)
Dim Reg1 As Region = Region.FromHrgn(RegH1)
g.InterpolationMode = InterpolationMode.HighQualityBicubic
g.FillRegion(New SolidBrush(BorderColor), Reg)
g.SetClip(Reg1, CombineMode.Replace)
g.Clear(FillColor)
Return b
End Function
End ClassThe function DrawRoundRectangle returns a bitmap which you can draw as in the following example:
Code:
Protected Overrides Sub OnPaint(e As PaintEventArgs)
Dim g As Graphics = e.Graphics
g.Clear(Parent.BackColor)
g.DrawImage(RoundedRectangle.DrawRoundRectangle(New Rectangle(5, 5, Width - 10, Height - 10), 10, 8, Color.FromArgb(28, 28, 28), Color.FromArgb(51, 51, 51)), 5, 5, Width - 10, Height - 10)
End SubHere the base rectangle is rect(5,5,width-10,height-10),
radius is 10 and
MSAA multiplier is 8(x)
Border color is color.fromargb(51,51,51)
Fill Color is color.fromargb(28,28,28)
![[Image: 2wp01uc.png]](http://i65.tinypic.com/2wp01uc.png)
See, a perfect one.
Also, do not forget to use the
G.InterpolationMode=7
(I have not used it in the code) Without it, your borders may be different in width.
(This post was last modified: 02-23-2016, 03:21 AM by Wingless.)


![[+]](https://sinister.li/images/modern/collapse_collapsed.png)