Results 1 to 10 of 10

Thread: Rotate a picturebox?

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    May 2006
    Posts
    2,295

    Rotate a picturebox?

    Hi there folks. I am working on an analog clock to teach students to tell the time in English and French. I would like to rig it up so the student simply moves a picture box for the minutehand and another for the hour. I have used mouse move, but in this case I need to keep 1 end of the picturebox centered in the middle of the clock so only the other end will let me move it around clockwise or counter clockwise.

    Has anyone ever tried to do something like that?

    Thanks!

    Edit: I suppose it could also be a thick line that rotates instead?
    Last edited by Justin M; Apr 9th, 2015 at 03:05 AM.

  2. #2
    Frenzied Member
    Join Date
    Feb 2003
    Posts
    1,807

    Re: Rotate a picturebox?

    I'm not entirely sure what you want, but drawing a simple clock with moving hands can be done using the Line graphics statement with a form or picturebox object. You would need to convert the time (hour and minutes) to an angle specified in radians and then calculate the x and y coordinates for the hand to point at using the Cos() and Sin() math functions. I might still have some code I wrote once. If this is what you meant.

    Edit 1:
    The attached program demonstrates how to draw a clock using vb6. Edit 2: Moved to: http://www.vbforums.com/showthread.p...59#post4962259
    Last edited by Peter Swinkels; Nov 20th, 2015 at 09:42 AM. Reason: Attached a much improved clock demo.

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

    Re: Rotate a picturebox?

    Dragging on and rotating the hands would be easier in VB.Net because of the use of GDI+.
    I haven't done GDI+ in VB6, although I know of a few people who have.
    Most recently LaVolpe has a codebank submission that you may want to take a look at.
    http://www.vbforums.com/showthread.p...nd-Hit-Testing

    Good old GDI also supported a rotation matrix to transform drawing, but it is not as easy as GDI+ (at least in .Net).
    But I did have an example I did a while ago on another forum that used the GDI rotation, so I thought that could be modified to give you clock hand dragging capability without too much work.
    I'll attach the original example code, which is interesting in its own right. It sets up the matrix and constantly rotates and bitblts a pair of picturebox images to do a transparent drawing overlay on a picturebox with an image in the background. It also draws a grid of lines using regular VB6 drawing commands to show that the regular VB6 drawing is also subject to the rotation matrix currently in effect.
    To create the dynamically transparent rotating image, drag the mouse in the pictureboxes at the top of the form. DoubleClick in them to clear the image.

    Second attachment, I copied the previous example to a new directory, removed a bunch of the code. I added code to determine angle of the mouse and setup the matrix and draw accordingly. I just loaded up a clock face as the backgorund image, and an hour hand and minute hand to be drawn from the pictureboxes up top. Since the hands are mostly black on a white background, we can just bitblt that onto the clock face with a srcAnd Raster OP without needing a mask to support transparency.

    Rather than have to figure out which hand you are dragging on, I just used two different buttons of the mouse. If you click and drag with the left button, the minute hand will follow the mouse. If you click and drag with the right mouse button, the hour hand will follow the mouse.
    Dragging with either mouse button will adjust the time on the clock relative to where the given hand is pointing, and the other hands position will be calculated to keep it in the appropriate position for the 12 hour time displayed.

    Some X/Y axis flipping and sin/cos reversals to the atan2 function had to be done to change the normal mathematical angles (0 degrees out the X axis, positive angles moving counter-clockwise), to the angles associated with clocks and compasses (0 degrees up along the Y axis, positive degrees moving clockwise).
    An interesting exercise in any case.
    Name:  RotatingClockHandsVB6.png
Views: 3634
Size:  23.6 KB
    Attached Files Attached Files
    Last edited by passel; Apr 9th, 2015 at 10:08 PM.

  4. #4
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: Rotate a picturebox?

    Thank Passel!
    Here is GDI+ version of Clock.

    GDI+ Clock.zip

    Name:  clock_GDI+.png
Views: 2556
Size:  25.8 KB
    Last edited by Jonney; Apr 9th, 2015 at 10:35 PM.

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    May 2006
    Posts
    2,295

    Re: Rotate a picturebox?

    I think I am in love. Thank you all for your help!

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    May 2006
    Posts
    2,295

    Re: Rotate a picturebox?

    I have been playing with the code on the second attachment, and one thing I would like to know is how to reposition the hour and minute picture boxes so they are centered on a slightly larger clock image. I attached the image if that helps, but is just a little bigger than the one in the attachment.
    Attached Files Attached Files

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

    Re: Rotate a picturebox?

    Yes, the code did expect the clock face to be in the center of a square bitmap.
    But, it is easily remedied.
    The matrix translate 0,0 to a location in these two fields of the matrix
    Code:
    '...
      Dim hd As Single    'hd=half radius of destination
    '...
      hd = Picture2.ScaleWidth / 2   'radius of the destination
    '...
    
        mtx.eDx = hd        'translate the rotation point
        mtx.eDy = hd        'to the middle of our destination
    So, the fix is to add both an X and Y center destination value
    Code:
    '...
      Dim hdX As Single    'hdX=center of rotation in X direction
      Dim hdY As Single    'hdY=center of totation in Y direction
    '...
      hdX = Picture2.ScaleWidth / 2   'X center of rotation
      hdY = Picture2.ScaleHeight / 2   'Y center of rotation
    '...
        mtx.eDx = hdX        'translate the rotation point
        mtx.eDy = hdY        'to the middle of our destination
    I was going to remind you to remember to change the eDx and eDy in both places where they are set in the matrix (once for each hand), but since the hands rotate around the same point, you can just comment out or remove those two lines in the second matrix setup block, that way you only have to set the center once.

    I also updated the comments above to indicate what the hdX,Y values were for (Center of Rotation), rather then the generic, "half radius", which wasn't correct anyway, it was "half diameter".

    You will probably want the hands bigger, or make new hands.
    The point the hands will rotate around is based on X,Y offset from the upper left corner of the bitmap.
    When bitblting the bitmap, the bitmap location (upper,left corner) is offset negatively by the X,Y amount, so the rotation point ends up at the 0,0 point of the coordinate system, which the rotation matrix is rotating points around.
    Below, the point I want to be the center of rotation for the hand image is 15,25 so the bitblt location is offset by that amount -15, -25
    Code:
        BitBlt .hdc, -15, -25, pSizeX, pSizeY, Picture1(0).hdc, 0, 0, vbSrcAnd
    The code I had done in VB.Net for a similar clock example (which is where I got these images) had the hand images pointing straight up. Because of the way the GDI matrix worked (0 degrees being along the X axis), and the moving hands with the mouse requirment, I rotated the images so the hands pointed along the X axis.
    In the end I had to flip various things to get it to work, so it might have actually been good to see if using Vertical oriented hands would remove a "flip" somewhere, but at this point I have no interest in "fixing" working code. So, if you do create new hands, just make sure they point to the right in the bitmaps.

    And a caveat. I originally had the bitmap for the minute hand cropped much narrower (in height) and was also a bit longer so reached out to the edge of the clock face.
    But there was some bad pixelation at some shallow angles (around 280 degrees (between 9 and 10 near 9)) and 80 degrees (betwen 2 and 3, near 3), which the hour hand didn't show to the same extent.
    So, I played around with minute hand quite a bit, making it stubbier, and thicker, and various widths.
    Couldn't really get it to straighten out until I decided that the hour hand seemed to work well, and the bitmap was 50 pixels in height, so I made the minute hand 50 pixels in height as well. I positioned it to use the same pixel offset in the image for rotation. That seem to pretty much cure it.
    Perhaps you don't want to have too narrow of a bitmap in one direction vs the other, otherwise some bad things might happend along the edges of the long side at certain shallow angles. I don't know. Just something to be aware of.
    Last edited by passel; Apr 10th, 2015 at 09:50 AM.

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

    Re: Rotate a picturebox?

    I went ahead and enlarged the hands from the example. I started over with the originals I had (.png) and did the rotation and resizing so that the quality would be better than what I posted in the first example. I reduced the one's in the first example as GIF to save space. This time I when ahead and left them as 24-bit bitmap to leave some "smoothing" at the edges, although the original was a rough cut from some other image so isn't ideal to begin with.

    I did change the order so that the hour hand is drawn first, with the minute hand on top, although that would be hard to tell without some other "shadows" or something to give some depth cues.
    The bitmap has an even number of pixels in height and width, and there is not center pixel in the clock face (the center is in the non-existent space between two pixels). I tested the rotations out visually to see where the minute hand aligned at exactly 12, 3, 6 and 9 (:00 seconds) and adjusted the destination value and rotation offset in the image by a pixel here and there to balance it out visually within reason.

    <edit>
    Already posted the zip file, but looking at it again I believe that moving the Center of rotation down one pixel will be a more accurate indication of exactly 15 minutes after or before the hour (the 3 and 9 positions), so add 1 to where the center y is chosen after you unzip the attachment (based on observation of when the seconds readout is :00 in the debug.print in the immediate window). Without the + 1, the hand is just a little above the tick.
    Code:
      hdY = Picture2.ScaleHeight / 2 + 1 'Y center of rotation
    <another edit>
    The background clockface is probably off a little bit. As already mentioned it isn't centered around a pixel, so we can't have a center pixel we rotate around, but it might be off slightly in shape. Not sure. But as a easier way to test, rather than have to try to position the rotation precisely to a minute (i.e. seconds = :00), you can add a scrollbar to pick the minute and then adjust the minute hand based on the minute of the hour, and the hour hand by the time of day (updated from the minute scroll bar).

    Since there are 720 minutes in a twelve hour period, add a vertical scrollbar to one side of the form and set its maximum value to 719, so the time can go from 12:00:00 (0 minutes) to 11:59:00 (719 minutes). If you make the scrollbar the full height of the form, you can almost get a 1 to 1 mapping of pixel to minute input.
    You can always use the scrollbar arrow buttons to go up or down by 1 minute increments.
    The code to add to change the clock hand angles (and timeOfDay value) by minute input is:
    Code:
    Private Sub VScroll1_Change()
      UpdateByMinute VScroll1.Value
    End Sub
    Private Sub VScroll1_Scroll()
      UpdateByMinute VScroll1.Value
    End Sub
    Private Sub UpdateByMinute(m As Integer)
      Dim minute As Integer
      minute = m Mod 60  'change minute of 12 hour period, to minute of the hour
      MinuteAng = minute * twoPi / 60
      TimeOfDay = TwelveHours * VScroll1.Value / 720
      AngHour = (TimeOfDay / 12)  
      DrawIt
    End Sub
    If you step the scrollbar minute by minute, you can see how the hand angle is a little off in some areas of the clock. Redoing the clock face, by picking a center pixel and aligning the ticks by computed angles around that center pixel shouldn't be that hard to do, and would give an accurate correlation between hand angles and time of day, but for your purposes I'm sure this is fine the way it is.

    <last edit (I think)>I just went ahead and added the above two changes in a new zip, as some may not read everything posted.
    So, DragRotateImage3.zip has the vertical scrollbar, and values are probably as good as it is going to get for rotation around the existing bitmap.
    Attached Files Attached Files
    Last edited by passel; Apr 10th, 2015 at 05:27 PM.

  9. #9

    Thread Starter
    PowerPoster
    Join Date
    May 2006
    Posts
    2,295

    Re: Rotate a picturebox?

    That is awesome! Is there a place where I can look at the x and y coordinate of the minute and hour hand, and then use that to print in a label caption what the hour/minute is in digital time, so students can see the comparison. Like an if statement such as if x = and y = something then hourlbl.caption = ??

    Thanks,

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

    Re: Rotate a picturebox?

    Look for the Debug.Print statement. It is printing out the time in the Immediate window.
    I didn't know if you wanted that displayed since you might be teaching clock reading.
    Just replace the Debug.Print with Label1.Caption =

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