Results 1 to 2 of 2

Thread: Transforming Graphics Coordinates in Windows Forms

  1. #1

    Thread Starter
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,344

    Transforming Graphics Coordinates in Windows Forms

    C# version here.

    You can work with matrices to transform the coordinate system of a Graphics object but it is often more intuitive to call the TranslateTransform, RotateTransform and ScaleTransform methods. Here's a demo that uses the first two of those methods to draw a clock face. To see this code in action, create a new Windows Forms Application project, add a PictureBox and a Timer to the form and then set the Enabled property of the Timer to True. You may also like to set the Dock property of the PictureBox to Fill or else snap it to each edge and then set the Anchor property to all sides. Add the following code and run the application and you'll see a simple analogue clock showing the current time.
    VB.NET Code:
    1. Const CLEARANCE As Integer = 10
    2. Const MIN_DIAMETER As Integer = 50
    3. Const DEGREES_PER_HOUR As Integer = 30
    4. Const DEGREES_PER_MINUTE As Integer = 6
    5. Const DEGREES_PER_SECOND As Integer = 6
    6.  
    7. Private ReadOnly hourPen As Pen = Pens.Black
    8. Private ReadOnly minutePen As Pen = Pens.Blue
    9. Private ReadOnly secondPen As Pen = Pens.Red
    10.  
    11. Private Function GetHourAngle(currentTime As Date) As Single
    12.     Return (currentTime.Hour Mod 12 + (currentTime.Minute + CSng(currentTime.Second / 60)) / 60) * DEGREES_PER_HOUR
    13. End Function
    14.  
    15. Private Function GetMinuteAngle(currentTime As Date) As Single
    16.     Return (currentTime.Minute + CSng(currentTime.Second / 60)) * DEGREES_PER_MINUTE
    17. End Function
    18.  
    19. Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
    20.     Dim diameter = Math.Max(MIN_DIAMETER,
    21.                             Math.Min(PictureBox1.Width,
    22.                                      PictureBox1.Height) - 2 * CLEARANCE)
    23.  
    24.     'Ensure that the diameter is an odd number so there is a definite centre.
    25.     diameter = If(diameter Mod 2 = 0, diameter + 1, diameter)
    26.  
    27.     With e.Graphics
    28.         'Draw the clock outline.
    29.         .DrawEllipse(Pens.Black, CLEARANCE, CLEARANCE, diameter, diameter)
    30.  
    31.         'Shift the origin to the centre of the circle to make it easy to draw radial lines.
    32.         .TranslateTransform(CLEARANCE + diameter \ 2 + 1, CLEARANCE + diameter \ 2 + 1)
    33.  
    34.         'Draw the hour and minute increments.
    35.         For a = DEGREES_PER_MINUTE To 360 Step DEGREES_PER_MINUTE
    36.             .RotateTransform(DEGREES_PER_MINUTE)
    37.  
    38.             If a Mod DEGREES_PER_HOUR = 0 Then
    39.                 'Hour markers are the length of the clearance.
    40.                 .DrawLine(hourPen, 0, CLEARANCE - diameter \ 2, 0, -diameter \ 2)
    41.             Else
    42.                 'Minute markers are the half the length of the clearance.
    43.                 .DrawLine(minutePen, 0, (CLEARANCE - diameter) \ 2, 0, -diameter \ 2)
    44.             End If
    45.         Next
    46.  
    47.         Dim currentTime = Date.Now
    48.         Dim hourAngle = GetHourAngle(currentTime)
    49.         Dim minuteAngle = GetMinuteAngle(currentTime)
    50.         Dim secondAngle = currentTime.Second * DEGREES_PER_SECOND
    51.  
    52.         Dim fullHandLength = diameter \ 2 - CLEARANCE
    53.  
    54.         'The hands are drawn vertically upward in relation to the transformed coordinate system so the Y coordinate of the end-point is negative.
    55.  
    56.         'Draw the minute hand first.
    57.         .RotateTransform(minuteAngle)
    58.         .DrawLine(minutePen, 0, 0, 0, -fullHandLength)
    59.         .RotateTransform(-minuteAngle)
    60.  
    61.         'Draw the hour hand over the minute hand.
    62.         .RotateTransform(hourAngle)
    63.         .DrawLine(hourPen, 0, 0, 0, -fullHandLength \ 2)
    64.         .RotateTransform(-hourAngle)
    65.  
    66.         'Draw the second hand over all others.
    67.         .RotateTransform(secondAngle)
    68.         .DrawLine(secondPen, 0, 0, 0, -fullHandLength)
    69.         .RotateTransform(-secondAngle)
    70.     End With
    71. End Sub
    72.  
    73. Private Sub PictureBox1_SizeChanged(sender As Object, e As EventArgs) Handles PictureBox1.SizeChanged
    74.     PictureBox1.Invalidate()
    75. End Sub
    76.  
    77. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    78.     PictureBox1.Invalidate()
    79. End Sub
    Last edited by jmcilhinney; Oct 27th, 2017 at 12:33 AM. Reason: Fixed typo in title

  2. #2
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Transforming Graphics Coordinates in Windows Forms

    Another example of using those methods to draw an analog clock can be found here.
    In this case the hands are drawn using bitmaps that are rotated. The program doesn't show the current time (I did add that in another version), but a random time when you click on the label (it was an example of a teaching tool someone wanted). But it also has an additional form that allows manipulating the values going to the TranslateTransform, RotateTransform and ScaleTransform methods so you can see how changes can offset the hands from the center, and how they rotate if offset, and changing the size of the hands.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width