dcsimg
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 21

Thread: oh no.. here we go again!

  1. #1
    Join Date
    Oct 2003
    Location
    .NET2.0 / VS2005 Developer
    Posts
    7,104

    Thumbs down oh no.. here we go again!

    in a similar style to a previous problem, i need to create a timer in a module (or class module, im not bothered) that does not have a form

    Saying:

    Private clock as Timer
    Dim x as Timer

    both are ok, but trying to do anything with them results in:

    With Block or Object Variable not set


    anyone tell me how to make a timer in a module that is not a form?
    i solved a similar issue with the Inet control, by adding MSINET.OCX to my references. but Timer is part of VB6.OLB and is hence loaded as a component, so i cannot load it as a refrence.. :/
    "it's a fax from your dog, Mr Dansworth. It looks like your cat" - Gary Larson...DW1: Data Walkthroughs 1.1...DW2: Data Walkthroughs 2.0...DDS: The DataSet Designer Surface...ANO: ADO.NET2 Orientation...DAN: Deeper ADO.NET...DNU...PQ

  2. #2
    Join Date
    Jun 2001
    Location
    Mi
    Posts
    1,249
    Try going the API route ... SetTimer

  3. #3
    Join Date
    Sep 2001
    Location
    Québec, Canada
    Posts
    1,923
    SetTimer require a window handle, so your still stuck with a form, you could try CreateTimerQueue, but it only work with 2k+ (I can't test it actually, the example say it need a form, but nowhere the form handle is used):

    http://www.mentalis.org/apilist/Crea...eueTimer.shtml

    Having an invisible form is ok, it's pretty annoying when you only need it to have some control, but it's a VB limitation, it's VisualBasic after all

    JeffB
    CodeGuru VB FAQ Visual Basic Frequently Asked Questions
    VB Code color Tool to color your VB code on CodeGuru
    Before you post Importants informations to know before posting

  4. #4
    Join Date
    Jul 2000
    Location
    Milano, Italy
    Posts
    7,726

    Strange...this seems to work...

    Only, if you run it in ide, it may be a bit instable (stop it pressing "q", not via end button of Vb!)
    You know it works when compiled as you wait around 10 seconds and then press "q", and see messagebox...thus timer was working...

    Code:
    Option Explicit
    'In a bas module
    Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
    Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
    Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
    Private Cnt As Long, Ret As String
    Dim bQuit As Boolean
    Function GetPressedKey() As String
        For Cnt = 32 To 128
            'Get the keystate of a specified key
            If GetAsyncKeyState(Cnt) <> 0 Then
                GetPressedKey = Chr$(Cnt)
                Exit For
            End If
        Next Cnt
    End Function
    Sub TimerProc(ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long)
        Ret = GetPressedKey
        If Ret = "q" Or Ret = "Q" Then
             bQuit = True
        End If
    End Sub
    
    
    Sub Main()
        SetTimer 0, 0, 1000, AddressOf TimerProc
        Do While Not bQuit
          DoEvents
        Loop
        KillTimer 0, 0
        MsgBox "Ending!"
    End Sub
    ...at present time, using mainly Net 4.0, Vs 2010



    Special thanks to Lothar "the Great" Haensler, Chris Eastwood , dr_Michael, ClearCode, Iouri and
    all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

  5. #5
    Join Date
    Sep 2001
    Location
    Québec, Canada
    Posts
    1,923
    This is some nice work Cesare, the handle "0" is the handle of the Desktop if I'm not mistaken. I added a debug.print and the timer was still running even after I pressed "Q", you just need to use the TimerID (returned from SetTimer) to stop it:

    Code:
    Option Explicit
    'In a bas module
    Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
    Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
    Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
    Private Cnt As Long, Ret As String
    Dim bQuit As Boolean
    
    Private TimerID As Long
    Function GetPressedKey() As String
        For Cnt = 32 To 128
            'Get the keystate of a specified key
            If GetAsyncKeyState(Cnt) <> 0 Then
                GetPressedKey = Chr$(Cnt)
                Exit For
            End If
        Next Cnt
    End Function
    Sub TimerProc(ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long)
        Ret = GetPressedKey
        If Ret = "q" Or Ret = "Q" Then
             bQuit = True
        End If
         
        Debug.Print Time
    End Sub
    
    
    Sub Main()
        TimerID = SetTimer(0, 0, 1000, AddressOf TimerProc)
        Do While Not bQuit
          DoEvents
        Loop
        KillTimer 0, TimerID
        MsgBox "Ending!"
    End Sub
    But, there is still that DoEvents that make the CPU usage so high, that's why using event are better.

    JeffB
    CodeGuru VB FAQ Visual Basic Frequently Asked Questions
    VB Code color Tool to color your VB code on CodeGuru
    Before you post Importants informations to know before posting

  6. #6
    Join Date
    Oct 2003
    Location
    .NET2.0 / VS2005 Developer
    Posts
    7,104
    fantastic help guys.. i'll give this a go at putting it into my code.. whats it for, you might ask.. well, one of the most common problems i have seen on the net, is:

    "I want an Inet control and a progress bar!"


    so i made everything, dropped it all on a form, and it worked like a charm. i use a timer to fire an event every second that calculates the elapsed and remaining time, average and instant speed or the transfer and bytes so far..

    then i thought:

    to make it more reusable for the vb community, i will make it intoa class module, so all they have to do, is load it into their project, tell it which progressbar and status label to draw on, and it will do it when asked for a url..

    the timer is only used to calculate the status text, every second it updates the downloaded number of bytes, speed, and time to go.

    if the user does not use a status bar, the timer isnt needed


    i have made available, public methods for getting all the things a user might be interested in, so would anyone hence advise to not use a timer at all in the class module, but let the user make his timer on his form, and within the timer event, call the public get commands?

    the only thing i must do then, is calculate the totals by some other event occurrence, like maybe the data received, comes in chunks, so every chunk (2 kilobytes) i calculate the new totals.

    I am hesitant to do this however, because i have specifically programmed an array structure to hold the time and byte for the last 10 seconds (approx) to give a better visualisation of the average speed (and i have just realised there needs to be some work done on the algorithm, but it is trivial)

    so i will use the timer for now, and calculate totals every timer event, if this is thought to be sensible
    (it also means that the frequency of calculation wont change if the modem speed changes)
    "it's a fax from your dog, Mr Dansworth. It looks like your cat" - Gary Larson...DW1: Data Walkthroughs 1.1...DW2: Data Walkthroughs 2.0...DDS: The DataSet Designer Surface...ANO: ADO.NET2 Orientation...DAN: Deeper ADO.NET...DNU...PQ

  7. #7
    Join Date
    Jul 2000
    Location
    Milano, Italy
    Posts
    7,726

    Thanks, JeffB...

    I was not aware of the bug. Thanks, JeffB.
    But did you test it severely (I am asking as I too made some tests in ide and in compiled)?
    After pressing "Q" you had to close msgbox to have it destroy timer and really quit.
    When I tested in compiled version, used taskmanager and saw the running exe disappear after closing msgbox. Still had the doubt timer api could be alive even if nothing could show it...
    ...at present time, using mainly Net 4.0, Vs 2010



    Special thanks to Lothar "the Great" Haensler, Chris Eastwood , dr_Michael, ClearCode, Iouri and
    all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

  8. #8
    Join Date
    Aug 2003
    Location
    London
    Posts
    515
    Here's a timer object....it's basically a cut down version of vbAccelerator's excellent 'Sub-classing and Timer assistant'....I take no credit for the code!
    Attached Files Attached Files

  9. #9
    Join Date
    Sep 2000
    Location
    Indianapolis
    Posts
    6,738

    Thumbs up

    This would make a great article for the VB section of CodeGuru....

    hint, hint.

    Brad!
    -----------------------------------------------
    Brad! Jones,
    LotsOfSoftware, LLC
    -----------------------------------------------

  10. #10
    Join Date
    Jul 2000
    Location
    Milano, Italy
    Posts
    7,726

    ThinkBrad was speaking for you (cjard and JeffB...)

    by the way, from MSDN something that give credits to JeffB:
    1)
    Timers are a limited resource. If all timers are in use, the SetTimer
    function fails. Unless keeping a timer active is absolutely essential
    to a program, the application must destroy the timer when it is
    not in use
    .
    2)
    When a timer is created, it is assigned an ID. Timer IDs are
    passed to timer callback functions and with WM_TIMER
    messages. Timer IDs are also used when killing the timer with
    the KillTimer function. The nIDEvent parameter lets an application
    choose the timer's ID if the hWnd parameter is not NULL. If the
    hWnd parameter is NULL, Windows chooses an ID and returns it
    from the SetTimer function
    . In this case, the nIDEvent parameter
    is ignored, regardless of the value of lpTimerFunc.
    3)
    The return value from SetTimer is 0 (zero) if the timer could not
    be created. This situation occurs only when all timers are in use
    before the function is called. SetTimer returns a nonzero value if
    the timer is successfully created. If the hWnd parameter is NULL,
    this nonzero value is the timer's ID.
    If hWnd is nonzero, the
    function succeeded, and the timer's ID is the value passed in
    nIDEvent. The timer's ID must be saved because it will be needed
    later to kill the timer
    .
    Last edited by Cimperiali; November 7th, 2003 at 10:02 AM.
    ...at present time, using mainly Net 4.0, Vs 2010



    Special thanks to Lothar "the Great" Haensler, Chris Eastwood , dr_Michael, ClearCode, Iouri and
    all the other wonderful people who made and make Codeguru a great place.
    Come back soon, you Gurus.

  11. #11
    Join Date
    Oct 2003
    Location
    .NET2.0 / VS2005 Developer
    Posts
    7,104
    Originally posted by Dmorley
    Here's a timer object....it's basically a cut down version of vbAccelerator's excellent 'Sub-classing and Timer assistant'....I take no credit for the code!
    i cant actually see how this project works, though..

    ctimer is what the user creates, and ctimer is like a pretty interface to an array of basTimers.. a bastimer uses system api calls to make and destroy timers.. but how does the event handling actually get into my program?

    its basically similar to my lack of understanding of ANY event in vb..

    in java, we register objects to receive events, and can register multiple objects to receive the same event.. or maybe it is better to say we can write a common event handler for multiple objects

    in .net i see how it works:

    public sub something(....) Handles button1.click button2.click

    but vb6 has no handles keyword, so how do we make something in VB that handles an event, other than adding a _Click() to the name? where does it register that this will handle the click event? is it hardcoded in vb that:
    XXX_click()

    handles the click event for XXX

    and XXX_Timer() handles the timer event?

    how to register multiple objects per handler?



    theres so much i ahve to learn, and so much that seems backwards and illogical to me when programming this language
    "it's a fax from your dog, Mr Dansworth. It looks like your cat" - Gary Larson...DW1: Data Walkthroughs 1.1...DW2: Data Walkthroughs 2.0...DDS: The DataSet Designer Surface...ANO: ADO.NET2 Orientation...DAN: Deeper ADO.NET...DNU...PQ

  12. #12
    Join Date
    Aug 2003
    Location
    London
    Posts
    515
    This project compiles into an Activex DLL which you can use as follows...

    At module level in your form / class, declare the object with events as follows...

    Private WithEvents m_objTimer as TimerObject.CTimer

    m_objTimer is now available in the objects combo box of your IDE, select it and it will create an event procedure...

    Private Sub m_objTimer_ThatTime()

    End Sub

    You can then use the timer with the following code

    Set m_objTimer = New CTimer
    m_objTimer.Interval = 500
    m_objTimer.Enabled = True

    Every 500 milliseconds, the m_objTimer_ThatTime event will be triggered...!

    It's handy to use in DLL and OCX development, you can just drop the module & class into projects if you don't want to have dependencies.

    Hope that helps...

  13. #13
    Join Date
    Oct 2003
    Location
    .NET2.0 / VS2005 Developer
    Posts
    7,104
    i'm more with it now, cheers...

    I have avoided using it for some reasons:
    .
    .
    .

    i need only one timer

    i take a dim view of an array of objects and searching them all to find the one i want (i like hash tables )

    it seems quite long winded approach


    heres what i did:

    Code:
    'timer things
    Private TimerID As Long
    Private TimerEnabled As Boolean
    Private Const TIMER_INTERVAL = "1000"
    
    Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
    Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
    
    Private Sub StartTimer()
      TimerID = SetTimer(Null, 0, TIMER_INTERVAL, AddressOf TimerPulse)
      If TimerID = 0 Then
        MsgBox "All the system Timers are in use. SOME speed statistics related to the download are unavailable, though this will not affect the program's ability to download files.", vbInformation, "Hello"
      End If
    End Sub
    
    Private Sub StopTimer()
        KillTimer 0, TimerID
        TimerID = -1
    End Sub
    "it's a fax from your dog, Mr Dansworth. It looks like your cat" - Gary Larson...DW1: Data Walkthroughs 1.1...DW2: Data Walkthroughs 2.0...DDS: The DataSet Designer Surface...ANO: ADO.NET2 Orientation...DAN: Deeper ADO.NET...DNU...PQ

  14. #14
    Join Date
    Oct 2003
    Location
    .NET2.0 / VS2005 Developer
    Posts
    7,104
    and now all i do is make a sub like this:

    Code:
    Private Sub TimerPulse(ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long)
    and inside it place my code to do upon each pulse

    thanks for the help, guys
    "it's a fax from your dog, Mr Dansworth. It looks like your cat" - Gary Larson...DW1: Data Walkthroughs 1.1...DW2: Data Walkthroughs 2.0...DDS: The DataSet Designer Surface...ANO: ADO.NET2 Orientation...DAN: Deeper ADO.NET...DNU...PQ

  15. #15
    Join Date
    Oct 2003
    Location
    .NET2.0 / VS2005 Developer
    Posts
    7,104
    woohoo, i found out how to color it, BUT, im puzzled, thanks to jeffb for the link in his sig for the color code 1.6 util..

    i am puzzled by the appearance of a menu sometimes.. it starts with Restore, Color, UnCOlor, Reload Files, and Exit

    but when does this appear? at the moment it appears to be a random thing when i am hovering the mouse near the color button. i dont get it..

    anyways, heres the stuff! yay!

    Code:
    'timer things
    Private TimerID As Long
    Private TimerEnabled As Boolean
    Private Const TIMER_INTERVAL = "1000"
    
    Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
    Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
    
    Private Sub StartTimer()
      TimerID = SetTimer(Null, 0, TIMER_INTERVAL, AddressOf TimerPulse)
      If TimerID = 0 Then
        MsgBox "All the system Timers are in use. SOME speed statistics related to the download are unavailable, though this will not affect the program's ability to download files.", vbInformation, "Hello"
      End If
    End Sub
    
    Private Sub StopTimer()
      If TimerID <> -1 Then
        KillTimer 0, TimerID
        TimerID = -1
      End If
    End Sub
    Code:
    Private Sub TimerPulse(ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long)
    Last edited by cjard; November 7th, 2003 at 12:18 PM.
    "it's a fax from your dog, Mr Dansworth. It looks like your cat" - Gary Larson...DW1: Data Walkthroughs 1.1...DW2: Data Walkthroughs 2.0...DDS: The DataSet Designer Surface...ANO: ADO.NET2 Orientation...DAN: Deeper ADO.NET...DNU...PQ

Page 1 of 2 12 LastLast

Posting Permissions

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


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)