Results 1 to 24 of 24

Thread: [VB6/VBA] Timer class.

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,673

    [VB6/VBA] Timer class.

    Hello everyone!

    This class allows to use the timers in VB6/VBA. It contains the Interval propertiy which sets the interval between the Tick events. It also contains the Tag property which allows to hold any data associated with the timer instance. The class uses the assembly thunks which check allow use the single class without any other dependencies. It also has the simple checking to reduce the crashes. It check the EbMode function and if the code is stopped it automatically disables the timers and if the code is in the stepping mode it just bypasses the events generation until the code is running. This checking simplifies debugging but doesn't exclude the crashes (because if the timer wasn't disabled since the last debugging session it'll continue execution with the old invalid data.) This code is compatible with the 64 bit office as well. If you want to add a method to the class you should update the TIMERPROC_INDEX constant according to the offset.

    Link on GitHub.

    Thanks for your attention!

    The trick, 2019.

  2. #2
    Fanatic Member
    Join Date
    Aug 2016
    Posts
    673

    Re: [VB6/VBA] Timer class.

    Very useful

  3. #3
    Hyperactive Member
    Join Date
    Jun 2016
    Location
    EspaƱa
    Posts
    506

    Re: [VB6/VBA] Timer class.

    great job

  4. #4
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: [VB6/VBA] Timer class.

    all ways dumplicated post, sorry

  5. #5
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Resolved Re: [VB6/VBA] Timer class.

    Quote Originally Posted by xxdoc123 View Post
    Very useful
    there has one uses paul caton's thunk in excelhome

  6. #6

  7. #7
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: [VB6/VBA] Timer class.

    when i say excelhome, i mean a forum
    http://club.excelhome.net/thread-629386-1-1.html this used Paul Caton's thunk in class
    but it can not be used in office x64

  8. #8
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: [VB6/VBA] Timer class.

    i can not use it in my office 2010 x86
    i add to ActiveX Control to main document, and write down code in "ThisDocument":
    when i click "Start" button, it debug nothing...
    Code:
    Option Explicit
    Private WithEvents c As CTrickTimer
    Private n As Long
    Private Sub c_Tick()
        n = n + 1
        Debug.Print c.Tag & vbTab & n
    End Sub
    Private Sub cmdStart_Click()
        Set c = New CTrickTimer
        c.Tag = "loquat"
        c.Interval = 1000
    End Sub
    Private Sub cmdStop_Click()
        c.Interval = 0
    End Sub

  9. #9

  10. #10
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    Re: [VB6/VBA] Timer class.

    Trick,

    Great code! I do a lot of VBA coding and this is the first code that I have seen with a thunk that works in a 64-bit environment.

    I'd like to learn more about the thunks you have written (I used to do assembly programming many moons ago). Do you have the asm listing for the 32 and 64-bit thunks?

    You say we should change the TIMERPROC_INDEX constant, currently set to 5, that should be changed if the position of the function TimerProc changes. When I count procedures from the top, TimerProc is the 6th (the ones above it are properties) and counting from the bottom it is the 9th (8th for VBA).

    I am guessing the count is from the top but there is an issue (I think). For the Tag property there is a Let and a Set. I haven't seen this before. I am guessing that only one is used and if so then TimerProc is the 5th procedure. Is this correct? Which one can I delete?

    A minor nitpick: in a few places you use a conditional compilation constant expression "If CBool(VBA6 or VBA7)". Conditional compilation constants are boolean so the CBool is not required. Also, all code that has VBA7 et True also has VBA6 set True so you only need "If VBA6".

  11. #11
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    Re: [VB6/VBA] Timer class.

    I took your VBA code and implemented it in Excel. I am now running it in 64-bit Office 365. I have noticed a strange thing. When I call up frmMain as a vbModal form everything woks as expected. However, if I open the form modelessly the timer never triggers. That doesn't make sense to me since all the form does relative to the timer(s) is to just catch the output in the ListBox. I can't see why the timer itself doesn't appear to fire.

  12. #12
    Lively Member
    Join Date
    May 2021
    Posts
    95

    Re: [VB6/VBA] Timer class.

    @MountainMan - I've also can't seem to get the timer to decouple from the modal UserForm (Office 365/64bit) - I don't suppose you've managed to solve this? I've tried relocating the m_cTimers collection to a standard module, and using a second collection as a replacement for the lstTimers listbox, but no luck.

  13. #13

  14. #14
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    Re: [VB6/VBA] Timer class.

    Dan_W,

    The VB6/VBA thunks that are available all check something known a the EbMode to determine if the user is in Run, Break or Design mode. As you might guess, if a user has stopped code execution but the timer is still going yet the code is not available for the system callback on the timer then bad things are going to happen. The thunks then stop the timer callback unless in Run mode.

    VBA is different than VB6 in several areas and this happens to be one of them. When you show a modal form the VBA system thinks it is in Run mode and all is good, just like for VB6. However, when you show a form non-modally or are just executing code not tied to a form, this EbMode is not set to Run mode and as soon as this happens the timer gets stopped. The trick and I went back and forth a few times trying to solve this but I don't think we got to a satisfactory solution. Maybe he has come up with a workaround.

    I have a class module I could shae with you that doesn't use the thunk approach. It works even in a non-modal form but is more dangerous to use since you will ever use "End" in your code. Especially if you have the VBA IDE open and start changing code while the timer is still running it will crash.

  15. #15
    Lively Member
    Join Date
    May 2021
    Posts
    95

    Re: [VB6/VBA] Timer class.

    My apologies for the late reply - it's been hectic at work.

    The Trick - thank you very much for offering to look at my code. Given MountainMan's explanation re: EBMode, I don't want to waste your time. With much of what I do taking place on the userform anyway, your code works beautifully - thank you very much for taking the time for coming up with a solution that includes VBA/64bit Office. It isn't always easy getting VB6 code to work when it comes to API calls and thunks.

    MoutainMan - thank you for this explanation. It actually helped explain quite a few things that I had been 'aware of' though hadn't properly understood, but now seem to fall into place - in particular,

    "...when you show a form non-modally or are just executing code not tied to a form, this EbMode is not set to Run mode and as soon as this happens the timer gets stopped."
    this makes a lot of sense, thank you. And I am keenly and painfully familiar with your point about "then bad things are going to happen". They almost always do.
    Thank you for the offer of sharing your class module - I don't ever use 'End' in my code, but I have been known to press the stop button, which I suspect probably has the same disasterous effect?
    I don't want to bother you or anyone else with this though - a timer is just a small piece in an ongoing personal project . I'm a self-taught hobbyist, and my 'studies' have brought me to VB6. Porting all this code over to something I can use in VBA has been a pet project - as you say, there are a number of areas where VB6 differs from VBA, and a working reliable timer is one of them (another is the picturebox, but I'm working on that!)

    Thank you both.

  16. #16
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: [VB6/VBA] Timer class.

    it seems have a faster way to get EbMode function address
    when we use addressof to get function or sub pointer
    it will get EbMode function at offset 0xA
    vb6:
    02710CFD - B8 E016A90F - mov eax,VBA6.EbMode { (-17296.09) }
    vbe x86:
    167A5B65 - B8 C7A78153 - mov eax,VBE7.rtcBeep+5474 { (246) }
    vbe x64: offset 0x25
    1E597C19C87 - 48 B8 70D0E3F7FB7F0000 - mov rax,VBE7.DLL+FD070 { (-1958193856) }

    these should be EbMode right?

  17. #17
    Member
    Join Date
    Apr 2019
    Posts
    63

    Re: [VB6/VBA] Timer class.

    Trick, thanks so much for this class. I'm intrigued by your usage of EbMode. I'm currently working on a project where it would be very useful to identify the EbMode of another VBA application. If I can obtain the address of the EbMode function within the other application (i.e. through a combination of EnumProcessModules and GetModuleFileName to get hVBE etc.), and if I call the EbMode function address directly from within another application, which application will I obtain the EbMode for?

    I.E. If VBA ProcessA calls EbMode function of VBA ProcessB's VBE7 dll; would it return the EbMode of VBA ProcessB? I worry that it'll return ProcessA's EbMode and there may be no way of identifying the EbMode of ProcessB without being in the process itself...

  18. #18
    PowerPoster
    Join Date
    Jan 2020
    Posts
    3,746

    Re: [VB6/VBA] Timer class.

    EbMode maybe only run in vb6 ide or excel vba ide,you can Inject a DLL into the VBA window for a try, and then get the function address of EBMODE

  19. #19
    Member
    Join Date
    Apr 2019
    Posts
    63

    Re: [VB6/VBA] Timer class.

    Quote Originally Posted by xiaoyao View Post
    EbMode maybe only run in vb6 ide or excel vba ide,you can Inject a DLL into the VBA window for a try, and then get the function address of EBMODE
    Yeah both processes are VB6/VBA though? So which process does it get the ebmode for? I.E. is the ebmode function relative to the application it's loaded into, or relative to the application executing it?

  20. #20

  21. #21
    Member
    Join Date
    Apr 2019
    Posts
    63

    Re: [VB6/VBA] Timer class.

    Quote Originally Posted by The trick View Post
    How do you call function in another process?
    Excuse my ignorance but I assumed `DispCallFunc` would be able to do that...

    But if not I guess the only option is loading a DLL into the external process right? Sucks...
    Last edited by sancarn; Jul 5th, 2023 at 06:54 AM.

  22. #22
    PowerPoster
    Join Date
    Jan 2020
    Posts
    3,746

    Re: [VB6/VBA] Timer class.

    Quote Originally Posted by sancarn View Post
    Excuse my ignorance but I assumed `DispCallFunc` would be able to do that...

    But if not I guess the only option is loading a DLL into the external process right? Sucks...
    DispCallFunc only for same process,if you wan't to call other process,you need use ASM CODE OR LOAD dll to do

  23. #23

  24. #24
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: [VB6/VBA] Timer class.

    hello the trick, can you add Enabled and Name property for this class?

Tags for this Thread

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