If you're curious about sine and cosine(they're not pronounced sin and cos, btw) Google it. I'm not a math teacher, and it's really not that difficult, but you should practice to get the hang of using them.

Create a new project, paste this into it:

vb Code:
  1. Private Type POINTAPI
  2.         x As Long
  3.         y As Long
  4. End Type
  5.  
  6. Private Declare Function Polygon Lib "gdi32" (ByVal hdc As Long, lpPoint As POINTAPI, ByVal nCount As Long) As Long
  7.  
  8. Private Const Pi As Double = 3.1415926535898
  9.  
  10. Private Sub RoundRect(ByVal targetDC As Long, X1 As Long, Y1 As Long, X2 As Long, Y2 As Long, Radius As Double)
  11. 'assumes x1 < x2 and y1 < y2, and radius < half either width/height
  12.  
  13. Dim i As Double 'variable for radians
  14. Dim s As Double 'step
  15. Dim c As Double 'complexity(number of points on the 'circle')
  16. Dim x As Double, y As Double 'spatial coordinates, origin center
  17.  
  18. Dim Width As Double, Height As Double
  19. Dim RPnts() As POINTAPI 'stores the points of the polygon, ubound should always(post loop) result to c + 1
  20. Dim bc As Long, cc As Long, dc As Long 'counters for corners
  21.  
  22. ReDim RPnts(0) 'init first index
  23.  
  24. c = Pi * Radius 'accuracy(sides); lower this and the results could be off, increase if you encounter issues(skewed result)
  25. If c < 28 Then c = 28 'minimal quality; 28 points = 7 per corner
  26. If c > 100 Then c = 100 'max points('sides'), 25 per corner
  27. 'this is a simple attempt at adapative accuracy, it's not 'fully tested' the min and max should prevent any GDI problems
  28.  
  29. s = (2# * Pi) / (c) '1 full circle(2pi) / complexity
  30.  
  31. 'calculate width and height, halved('radius')
  32. Width = (X2 - X1) / 2
  33. Height = (Y2 - Y1) / 2
  34.  
  35. 'point 1 should be less than 2
  36. If Width < 0 Or Height < 0 Then Err.Raise 1
  37.  
  38. 'radius should not exceed either of these
  39. If Radius > Width Or Radius > Height Then Err.Raise 1
  40.  
  41. 'adjust width and height, knowing values are good
  42. Width = Width - Radius
  43. Height = Height - Radius
  44.  
  45. 'assign x, y to 'center point'(origin, the circle's middle)
  46. x = (X1 + X2) / 2
  47. y = (Y1 + Y2) / 2
  48.  
  49. For i = -Pi To Pi Step s
  50.  
  51.     If i < (-Pi / 2) Then
  52.         RPnts(UBound(RPnts)).x = (Cos(i) * Radius) + x - Width
  53.         RPnts(UBound(RPnts)).y = (Sin(i) * Radius) + y - Height
  54.     ElseIf i >= (-Pi / 2) And i < 0 Then
  55.         RPnts(UBound(RPnts)).x = (Cos(i) * Radius) + x + Width
  56.         RPnts(UBound(RPnts)).y = (Sin(i) * Radius) + y - Height
  57.     ElseIf i >= 0 And i < (Pi / 2) Then
  58.         RPnts(UBound(RPnts)).x = (Cos(i) * Radius) + x + Width
  59.         RPnts(UBound(RPnts)).y = (Sin(i) * Radius) + y + Height
  60.     ElseIf i >= (Pi / 2) Then
  61.         RPnts(UBound(RPnts)).x = (Cos(i) * Radius) + x - Width
  62.         RPnts(UBound(RPnts)).y = (Sin(i) * Radius) + y + Height
  63.     End If
  64.        
  65.     ReDim Preserve RPnts(UBound(RPnts) + 1)
  66. Next
  67.  
  68. 'draw the result using Polygon(could convert pointAPI to pointF and use GDI+(AA) here instead)
  69. Polygon targetDC, RPnts(0), UBound(RPnts) - 1
  70. End Sub
  71.  
  72. Private Sub Form_Click()
  73. RoundRect Form1.hdc, 0, 0, 100, 100, 100 'a circle, try complexity(c) of 8 for an octagon
  74. RoundRect Form1.hdc, 0, 100, 300, 200, 5 'a big rectangle
  75. End Sub

Click anywhere on the form.

Code could be MUCH better. But it's presented here in what I think is the easiest to learn format.

What would make it better:
  • Make a loop for each corner OR...
  • Create a LUT for the COS/SIN functions
  • GDI+ can do floating-point(POINTF) anti-aliased(smoothing mode bicubic) polygons
  • Could probably figure out a better adaptive routine if you gave it a whirl
  • Then of course things like filling
  • You could even reuse just one quadrant, mirroring/flipping for the other corners(if you're considering a manual fill), otherwise GDI+ offers lot of fill(and other) options