Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do I make a realistic analogue clock? 1

Status
Not open for further replies.

tedsmith

Programmer
Nov 23, 2000
1,762
AU
I want to create a small realistic analogue clock, not with just a simple line for a hand. (Hours and Minutes only)
I have in mind a transparent 3D metallic style background graphic for the minute hand that rotates about a point.
I know how to make a borderless form that is transparent except for where the hand is but not a transparent graphic.
Is there a way or rotating a form or a transparent bit map graphic about a point?
I could have 3600 jpegs of each situation and change them each minute but that I would be ashamed to admit that!
 
>Is there a way or rotating a form or a transparent bit map graphic about a point?

Yes

(and I'm afraid that you are going to have to live with that response until I get near one of my VB machines. And have some time. One thing that might help point you in the right direction is the SetWorldTransform API call; you'll find working examples of this API call from me in this forum)
 
Ok, I have a basic example of how to do this up and running. I just want to clean it up a bit.
 
Ok, Ted. You'll need a form with at least 1 picture box (2 if you want to use the example to investigate imposing one rotating image above a static background image as I suspect you will; see the comments in the Timer code on how to enable this), a timer, and an ImageList control. Make sure the picture boxes are set to pixel for their scale mode

The ImageList control should be loaded with the graphic for your clock hand (I'm assuming you know how to set the Mask color to render parts of the image you load transparent), and the second picture box (if you use it) should be loaded with your background image. In my example I had both the picture boxes measuring 64 x 64 pixels, and my clock hand image measured 5 x 32 pixels

Oh, I know you only wanted this for hour and minute hands, but I've got it ticking each second for the purposes of illustration)
Code:
[blue]Option Explicit

Private Type XFORM
        eM11 As Single
        eM12 As Single
        eM21 As Single
        eM22 As Single
        eDx As Single
        eDy As Single
End Type

Private Declare Function SetGraphicsMode Lib "gdi32" (ByVal hdc As Long, ByVal iMode As Long) As Long
Private Declare Function GetGraphicsMode Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function SetMapMode Lib "gdi32" (ByVal hdc As Long, ByVal nMapMode As Long) As Long

Private Declare Function GetWorldTransform Lib "gdi32" (ByVal hdc As Long, lpXform As XFORM) As Long
Private Declare Function SetWorldTransform Lib "gdi32" (ByVal hdc As Long, lpXform As XFORM) As Long

Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function DrawIconEx Lib "user32" (ByVal hdc As Long, ByVal xLeft As Long, ByVal yTop As Long, ByVal hIcon As Long, ByVal cxWidth As Long, ByVal cyWidth As Long, ByVal istepIfAniCur As Long, ByVal hbrFlickerFreeDraw As Long, ByVal diFlags As Long) As Long

Private Const DI_NORMAL = &H3
Private Const GM_ADVANCED = 2
Private Const GM_COMPATIBLE = 1
Private Const MM_TEXT = 1
Private Const MM_LOENGLISH = 4

Private gOldWorld As XFORM

Private Sub Form_Load()
    [green]' Initialise Picture1's device context to work with SetWorldTransform ...[/green]
    SetGraphicsMode Picture1.hdc, GM_ADVANCED
    SetMapMode Picture1.hdc, MM_TEXT
    Timer1.Interval = 1000
    Timer1.Enabled = True
End Sub

Private Sub Timer1_Timer()
    [green]' Uncomment the two lines of code that follow this comment and comment out
    ' the Picture1.Cls line if you want to render the rotated image onto another
    ' image (e.g a hand onto a clock). The background image should be loaded into Picture2
    ' RotateTargetDC Picture1.hdc, 0, 0, 0
    ' BitBlt Picture1.hdc, 0, 0, 64, 64, Picture2.hdc, 0, 0, vbSrcCopy[/green]
    Picture1.Cls
    RotateTargetDC Picture1.hdc, 32, 32, (Second(Now) - 30) * 6
    [green]' We coukld have used ListImages Draw method in the next line, but it is fractionally less flexible when it comes
    ' to mucking about with the point of origin of the source[/green]
    DrawIconEx Picture1.hdc, -3, -3, ImageList1.ListImages(1).ExtractIcon.Handle, 5, 32, 0, 0, DI_NORMAL
End Sub

[green]' This particular XForm is a rotation only[/green]
Private Function buildXForm(ByVal x0 As Long, ByVal y0 As Long, ByVal q As Single) As XFORM
    q = RadDeg(q)
    buildXForm.eM11 = Round(Cos(q), 4)
    buildXForm.eM12 = Round(Sin(q), 4) [green]' sign swapped with eM21 because y axis is downwards[/green]
    buildXForm.eM21 = Round(-Sin(q), 4)
    buildXForm.eM22 = Round(Cos(q), 4)
    buildXForm.eDx = x0 'x0 - Cos(q) * x0 + Sin(q) * y0
    buildXForm.eDy = y0 'y0 - Cos(q) * y0 - Sin(q) * x0
End Function

Private Function RadDeg(ByVal angle As Double) As Double
    RadDeg = angle * Atn(1) / 45
End Function

Private Sub RotateTargetDC(ByVal hdcTarget As Long, ByVal aboutX As Long, ByVal aboutY As Long, ByVal rotate As Single)
    Dim myXForm As XFORM
    
    [green]' Build rotation transformation matrix
    ' In this case rotating 'rotate' degrees clockwise about point aboutX, aboutY[/green]
    myXForm = buildXForm(aboutX, aboutY, rotate)

    [green]' Apply the transform to our DC[/green]
    SetWorldTransform hdcTarget, myXForm
End Sub[/blue]
Happy Easter
 
Im having problems with the DrawIconEx Picture1.hdc, -3, -3, ImageList1.ListImages(1).ExtractIcon.Handle, 5, 32, 0, 0, DI_NORMAL statement erroring with "Index out of Bounds"
is this because I dont have bmps exactly the same size as yours?
 
No I cant see anywhere how you can, I thought the image from the pic box appeared in the image list box.
I am using an ImageList Box from Windows Common controls 5. There is nothing in my help disk that tells me how to use it.
 
Right-click it once you have placed it on the form, select Properties and the rest should be fairly self-explanatory.

The only thing that may not be is how to get transparency selected. What you need to do is select the Mask Color; this will be the color that is transparent in the final rendering
 
Sorry I havent had time to scratch myself - and I'm supposed to be retired!
We have a big problem here in Australia with a shortage in every sort of skilled labour as a resulot of the China minerals boom.
This is the result of years of inactivity by conservative governments not putting any real effort into technical education.
They seem to be calling back all us old folks back into the workforce!

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top