Private Type POINTAPI
x As Long
y As Long
End Type
Private Declare Function Polygon Lib "gdi32" (ByVal hdc As Long, lpPoint As POINTAPI, ByVal nCount As Long) As Long
Private Const Pi As Double = 3.1415926535898
Private Sub RoundRect(ByVal targetDC As Long, X1 As Long, Y1 As Long, X2 As Long, Y2 As Long, Radius As Double)
'assumes x1 < x2 and y1 < y2, and radius < half either width/height
Dim i As Double 'variable for radians
Dim s As Double 'step
Dim c As Double 'complexity(number of points on the 'circle')
Dim x As Double, y As Double 'spatial coordinates, origin center
Dim Width As Double, Height As Double
Dim RPnts() As POINTAPI 'stores the points of the polygon, ubound should always(post loop) result to c + 1
Dim bc As Long, cc As Long, dc As Long 'counters for corners
ReDim RPnts(0) 'init first index
c = Pi * Radius 'accuracy(sides); lower this and the results could be off, increase if you encounter issues(skewed result)
If c < 28 Then c = 28 'minimal quality; 28 points = 7 per corner
If c > 100 Then c = 100 'max points('sides'), 25 per corner
'this is a simple attempt at adapative accuracy, it's not 'fully tested' the min and max should prevent any GDI problems
s = (2# * Pi) / (c) '1 full circle(2pi) / complexity
'calculate width and height, halved('radius')
Width = (X2 - X1) / 2
Height = (Y2 - Y1) / 2
'point 1 should be less than 2
If Width < 0 Or Height < 0 Then Err.Raise 1
'radius should not exceed either of these
If Radius > Width Or Radius > Height Then Err.Raise 1
'adjust width and height, knowing values are good
Width = Width - Radius
Height = Height - Radius
'assign x, y to 'center point'(origin, the circle's middle)
x = (X1 + X2) / 2
y = (Y1 + Y2) / 2
For i = -Pi To Pi Step s
If i < (-Pi / 2) Then
RPnts(UBound(RPnts)).x = (Cos(i) * Radius) + x - Width
RPnts(UBound(RPnts)).y = (Sin(i) * Radius) + y - Height
ElseIf i >= (-Pi / 2) And i < 0 Then
RPnts(UBound(RPnts)).x = (Cos(i) * Radius) + x + Width
RPnts(UBound(RPnts)).y = (Sin(i) * Radius) + y - Height
ElseIf i >= 0 And i < (Pi / 2) Then
RPnts(UBound(RPnts)).x = (Cos(i) * Radius) + x + Width
RPnts(UBound(RPnts)).y = (Sin(i) * Radius) + y + Height
ElseIf i >= (Pi / 2) Then
RPnts(UBound(RPnts)).x = (Cos(i) * Radius) + x - Width
RPnts(UBound(RPnts)).y = (Sin(i) * Radius) + y + Height
End If
ReDim Preserve RPnts(UBound(RPnts) + 1)
Next
'draw the result using Polygon(could convert pointAPI to pointF and use GDI+(AA) here instead)
Polygon targetDC, RPnts(0), UBound(RPnts) - 1
End Sub
Private Sub Form_Click()
RoundRect Form1.hdc, 0, 0, 100, 100, 100 'a circle, try complexity(c) of 8 for an octagon
RoundRect Form1.hdc, 0, 100, 300, 200, 5 'a big rectangle
End Sub