Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 612
  • Last Modified:

VB6 overflow error when using function TimeGetTime of winmm.dll

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
  DoEvents
  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)
see: http://msdn.microsoft.com/de-de/library/windows/desktop/dd757629%28v=vs.85%29.aspx


Thanks for help
Josef
0
joschramm
Asked:
joschramm
1 Solution
 
ChloesDadCommented:
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.
0
 
GrahamSkanRetiredCommented:
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.
0
 
joschrammAuthor Commented:
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?
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
HooKooDooKuCommented:
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;
    else
        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.
0
 
joschrammAuthor Commented:
Hi HooKooDooKu,
thats it!
Many thanks
Josef
0
 
ChloesDadCommented:
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;
    else
        GetTimeDouble = dTime
    end if
End Function

Open in new window

0
 
joschrammAuthor Commented:
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))
  Else
    'lTimeCur is not changed
  End If 'special cases
  gr_GetTime = lTimeCur
 
End Function
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now