VB6 overflow error when using function TimeGetTime of winmm.dll

Posted on 2014-10-27
Last Modified: 2014-11-10
I use the function TimeGetTime to control time spans in this way (to do something all 20 s):

Public Declare Function gr_GetTime Lib "winmm.dll" _
  Alias "timeGetTime" _
  () As Long
Public StartNew as long


StartNew = gr_GetTime()
Do while True
  If Abs(gr_GetTime() - StartNew) >= 20000 Then
    'Do something
    StartNew = gr_GetTime()
  end if '20 s later?

This works fine for at most 24.8551 days. Then an overflow error occurs because in VB6 long variagles are signed whereas timeGetTime returns unsigned dword (32 bit). So the difference between actuell time and StartNew exceeds 2,147,483,647 (the range of VB6 longs).

What can I best do to avoid this failure?
(The function's TimeGetTime >>return value wraps around to 0 every 2^32 milliseconds, which is about 49.71 days<<, so that is no problem)

Thanks for help
Question by:joschramm
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
LVL 15

Expert Comment

ID: 40406934
This may work....

Can you save the result in a double rather than a long.

Also why don't you use a timer control or use Now to return the current time and then use DateDiff to check for 20 seconds elapsing.
LVL 76

Expert Comment

ID: 40407228
If, for accuracy, you require a very big 'integer' type, you can use the Currency type.

It will deal with at least 14 decimal places, but will not ignore the least significant digits if they have an absolute value greater than .0001.

In fact it, as designed, it can take four (non-lossy) decimal places, so it can be arithmetically manipulated to cater for integers with 18 digits.

Author Comment

ID: 40408481
Hi, ChloesDad,
>>Also why don't you use a timer control or use Now to return the current time and then use DateDiff to check for 20 seconds elapsing.<<
Because I needed a precise timer with a great range of time intervalls, which are very nice with long vars. So since years and years I use TimeGetTime in nearly all my projects. Unfortunately it never occurred to me that the said problem exists.
So I would like still to use longs. I need an encapsulating funged gr_GetTime with this features:
VB6 maps hex values to long in this way:
00000000 .. 7FFFFFFF ==> 0 .. 2147483647
80000000 .. FFFFFFFF ==> -2147483648 .. -1
I need this mapping:
00000000 .. 7FFFFFFF ==> 0 .. 2147483647
80000000 .. FFFFFFFF ==> 2147483648 .. 1
How do I achieve this?
MS Dynamics Made Instantly Simpler

Make Your Microsoft Dynamics Investment Count  & Drastically Decrease Training Time by Providing Intuitive Step-By-Step WalkThru Tutorials.

LVL 16

Accepted Solution

HooKooDooKu earned 500 total points
ID: 40408636
If you need numbers greater than 2 billion, you MUST move to a different data type like the other experts recommended.  Still pull back a long from the API (since you can not change that) but wrap your function call in another function that returns a different data type.

Once you've done that, you can have your wrapper function take negative numbers and modify them to the appropriate value... something like this:  (Sorry, this is off the cuff as I currently don't have a VB6 editor to check the text).

Public Function GetTimeDouble() as double
Dim lTime as long
Dim dTime as double

    lTime = gr_GetTime();
    if lTime < 0 Then
        dTime = CDbl( lTime )
        GetTimeDouble = 4294967296.0 - dTime;
        GetTimeDouble = CDbl( lTime )
    end if
End Function

Open in new window

Otherwise, you have to find a way to deal with negative numbers.  Interestingly enough, your last statement above basically asks for a way to map 800000000...FFFFFFFF to make to 2147483648 to 1... which you can do by multiplying the result by negative one... except for when you have the value 80000000... since there is no way to represent positive 2147483648 with a signed long.

Author Closing Comment

ID: 40408691
Hi HooKooDooKu,
thats it!
Many thanks
LVL 15

Expert Comment

ID: 40409016
That solution is still setting the return value into a long, so will still crash when you try and put a value >= 2^31

Public Function GetTimeDouble() as double
Dim dTime as double

    dTime = CDbl(gr_GetTime());
    if dTime < 0 Then
        GetTimeDouble = 4294967296.0 - dTime;
        GetTimeDouble = dTime
    end if
End Function

Open in new window


Author Comment

ID: 40433122
Hi CloesDad,  you are right, of course. However: The function's TimeGetTime >>return value wraps around to 0 every 2^32 milliseconds (see above). What is more:
 if dTime < 0 Then
        GetTimeDouble = 4294967296.0 - dTime;
should be
 if dTime < 0 Then
        GetTimeDouble = 4294967296.0 + dTime;
as dTime is clearly negative.
I did some more musing and now found this solution:
Private Declare Function my_GetTime Lib "winmm.dll" _
  Alias "timeGetTime" _
  () As Long

' Procedure : gr_GetTime
' Author    : JSchramm
' Date      : 10.11.2014
' Purpose   : Wrapper to prevent Out Of Range Error through the fact that VB long values are signed,
'             whereas timeGetTime delivers unsigned word

'             Use of gr_GetTime (all times in ms):
'             lTimeStart = gr_GetTime()
'             ...
'             lSomeTimeLater = Abs(gr_GetTime() - lTimeStart)
'             Only in case of wraparound between two immediately following calls of my_GetTime
'             over the "magical" border of &H80000000 there is a loss of one millisecond (ms)

Public Function gr_GetTime()
  Dim lTimeCur As Long
  lTimeCur = my_GetTime()
  If lTimeCur = &H80000000 Then
    'to prevent out of Range thru result of -1 * &H80000000
    'which would be greater than &H7FFFFFFF, the greatest positive long value
    lTimeCur = &H7FFFFFFF
  ElseIf lTimeCur < 0 Then
    lTimeCur = CLng(-1# * CDbl(lTimeCur))
    'lTimeCur is not changed
  End If 'special cases
  gr_GetTime = lTimeCur
End Function

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
Article by: Martin
Here are a few simple, working, games that you can use as-is or as the basis for your own games. Tic-Tac-Toe This is one of the simplest of all games.   The game allows for a choice of who goes first and keeps track of the number of wins for…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question