how to convert int to float in VB6 - vb6

I am trying to convert a pair of integers into a floating point variable (they should translate in a float value). I succesfully converted the pair of integers into a Long and i assumed that I was homefree by using the CDbl function. Unfortunately I am just getting the same number in the Double variable. The Long has a number like 1141187758 and this should translate in something like 530.xxx as a float. Anybody who can help me with this?

Air code
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long)
Function LongToFloat(ByVal l As Long) as Single
Dim f As Single
CopyMemory f, l, LenB(l)
LongToFloat = f
End Function
Adapted from this answer

Related

Numeric values of WinHTTP constants (eg. WINHTTP_NO_CLIENT_CERT_CONTEXT)

I need to set this property for a WinHttp request...
BOOL fRet = WinHttpSetOption(hRequest,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
WINHTTP_NO_CLIENT_CERT_CONTEXT,
0);
But from within an old VB application. I can access the method but can't use the constants.
I can use this to access the method from VB...
Declare Function WinHttpSetOption Lib "winhttp.dll" _
(ByVal hInternet As Variant, ByVal dwOption As Integer, ByVal lpBuffer As Byte, ByVal dwBufferLength As Integer) _
As Boolean
And then call it like so...
Call WinHttpSetOption(hRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
But have to replace the constants WINHTTP_OPTION_CLIENT_CERT_CONTEXT and WINHTTP_NO_CLIENT_CERT_CONTEXT with the correct numbers, or figure out how to import them.
After I long google search, I think WINHTTP_OPTION_CLIENT_CERT_CONTEXT is 47 but can't find WINHTTP_NO_CLIENT_CERT_CONTEXT anywhere.
Many thanks

How to find correct values for HWND window handles?

WinRestore,% hwnd([1])
i have found in many programming language the use of hwnd. after searching on google it comes out to be handle. I didnt got more information on this. how programmer knows the value to put in, eg.
Const LB_GETTEXTLEN = &H18A
Const LB_GETTEXT = &H189
Const LB_GETCOUNT = &H18B
&h18a how he known, how will he use this?
this is the example program
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Const LB_GETTEXTLEN = &H18A
Const LB_GETTEXT = &H189
Const LB_GETCOUNT = &H18B
Private Function GetListItems(ByVal hList As Long) As Variant
Dim i As Long, nCount As Long, lItemLength As Long
Dim sItem() As String
nCount = SendMessage(hList, LB_GETCOUNT, 0, ByVal 0&)
For i = 0 To nCount - 1
lItemLength = SendMessage(hList, LB_GETTEXTLEN, i, ByVal 0&)
ReDim Preserve sItem(i)
sItem(i) = String(lItemLength, 0)
Call SendMessage(hList, LB_GETTEXT, i, ByVal sItem(i))
Next i
GetListItems = sItem
End Function
there are many such examples in all different languages but concept will be the same. so i want to learn it. what does it mean and how to use it.
another example from ahk
Gui,2:+hwndhwnd
hwnd(2,hwnd)
Those are all window messages that you can find information about on the MSDN Documentation by googling them. See below links:
LB_GETTEXTLEN
LB_GETTEXT
LB_GETCOUNT
You can find them and other related messages by checking the documentation for the native List Box control.
As for the numbers they're hexadecimal numbers which are (usually) mentioned in the documentation. But since these aren't you'll have to google them and check other websites/forums, or find their values on your own by experimenting with them in C or C++ .
In VB hexadecimal numbers are represented by prepending the number with &H, whereas in C, C++, C# or alike they're prepended with 0x.
In a forms editor each window/control has a hwnd property. For windows not created by your forms package you use the API calls FindWindow (easiest but not reliable) or EnumWindows. Also GetForegroundWindow and GetDesktopWindow.
To find out the value of constants you download the C header files as part of the Windows SDK https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk. It also has the documentation for all these API calls. This is online documentation listing all the windows' functions https://msdn.microsoft.com/en-us/library/windows/desktop/ms633505(v=vs.85).aspx.

VB6 sidebar app

All.
I'm attempting to develop a 'sidebar' application with vb6, which I want to behave like windows Vista's gadget sidebar or Google Desktop sidebar, in the respect that other windows could not maximize over it.
I'm aware that chances of this happening are probably very little, but I'm asking just in case.
Currently, I've got a form that has multiple controls, and runs a function on load which makes itself the exact height of the screen, minus the taskbar, and it's 'left' location is set by a timer to be 'screen.width - me.width', so it will start at full height on the far right of the screen, and cannot be moved. Code for the height is as follows, if it is necessary.
Declare Function GetUserNameA Lib "advapi32.dll" (ByVal lpBuffer As String, nSize As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Public Declare Function SetLayeredWindowAttributes Lib "user32" ( _
ByVal hwnd As Long, _
ByVal crKey As Long, _
ByVal bAlpha As Byte, _
ByVal dwFlags As Long) As Long
Public Const GWL_STYLE = (-16)
Public Const GWL_EXSTYLE = (-20)
Public Const WS_EX_LAYERED = &H80000
Public Const LWA_COLORKEY = &H1
Public Const LWA_ALPHA = &H2
Private Const ABM_GETTASKBARPOS = &H5
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type APPBARDATA
cbSize As Long
hwnd As Long
uCallbackMessage As Long
uEdge As Long
rc As RECT
lParam As Long
End Type
Private Declare Function SHAppBarMessage Lib "shell32.dll" (ByVal dwMessage As Long, pData As APPBARDATA) As Long
Function Fixheight()
Dim ABD As APPBARDATA
SHAppBarMessage ABM_GETTASKBARPOS, ABD
Form1.Height = Screen.Height - ((ABD.rc.Bottom - ABD.rc.Top) * 12)
If Form1.Height <= 600 Then
Form1.Height = Screen.Height
End If
End Function
To be clear, I do not want an 'always on top' function. I already have that, and it's driving me insane, as the form has to me closed or minimized in order to maximize, minimize of close another program (i.e. chrome, word, etc) behind it. This form must instead not allow other programs to maximize over it, so that if for example, the user maximized Chrome, chrome would maximize minus form1.width.
I doubt that this is possible because as far as I'm concerned, that would mean taking control of chrome, and essentially making it's maximize function as
me.height = screen.height - ((ABD.rc.Bottom - ABD.rc.Top) * 12)
me.width = screen.width - form1.width
which isn't possible.
Anyway, hopefully someone out there can help. As I said, I seriously doubt the possibility of having this work, but if so, all the better.
Thanks in advance!
Thanks to Ken White, I googled SHAppBarMessage and found the following website, offering a downloadable source with the very feature I needed. I just have to implement it now!!
Very glad I asked! Thank you!
Edit: Found this spanish website, which while needed some help from Google Translate, is more suited to my needs. Just need to figure out how to make it work on the Right Hand Side! Thanks again!

How to represent 64-bit integer in VB6?

I am having to augment a legacy app to handle 64-bit integers. However, VB6 doesn't have a data type for that. The recommendation online that I've found has been to use the Currency data type.
However, I've found that I am running into some overflow issues.
Example - Results in Overflow during CCur call:
dim c as currency
' set maximum value of int64
c = CCur("9223372036854775807")
However, if I apply a smaller number (but still much larger than int32), it does work:
dim c as currency
' Remove the last 4 digits
c = CCur("922337203685477")
So what am I missing here? How can I handle a 64-bit value?
The only thing that I need to do with the 64-bit values is to read them from a SQL Server stored procedure (it comes as sql type bigint) and then display it to the form.
ADO Field.Value is type Variant. When you retrieve an adBigInt in VB6 the Variant will be of subtype Decimal.
You can use Variant datatype with CDec() conversion.
dim c as variant
' set maximum value of int64
c = CDec("9223372036854775807")
Now you can even use standard vb6 math operations, or string conversion functions on c.
Dim c As Variant, d As Variant
c = CDec("9223372036854775807")
Dim i As Integer
i = 1000
d = 10
Debug.Print c + i
Debug.Print c / d
Debug.Print CStr(c)
Results
9223372036854776807
922337203685477580,7
9223372036854775807
Just be aware that Decimal type Variant is wider than 64 bits, so you don't get the 'Overflow' on the server side :)
The answer is, it depends on what you're going to do with the 64 bit value. If you simply want to hold a value without doing any arithmetic on it, then it may be better to create a byte array or long array. For example:
Dim SixtFourBit(7) As Byte
or
Dim SixtyFourBit(1) As Long
Using the currency type is a simpler solution since you can apply arithmetic to it. But the Currency type is a fixed format representation, always having four decimal places. That means the lower bytes of the 64 bit representation go to make up the fractional part of the Currency value (sort of).
To coerce between Currency and arrays use the devilish CopyMemory windows API function:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Integer)
Sub SomeFunction()
Dim AnArray(7) As Byte
Dim ACurrency as Currency
ACurrency = 123.4567
CopyMemory AnArray(0), VarPtr(ACurrency), 8&
' Inspecting AnArray in the watch window will show you the byte representation of ACurrency
End Sub
With the caveat, that this sort of trickery is to be generally avoided. Incorrect use of CopyMemory can kill your program.
VB6 can be used with variant type of I8 to provide a 64-bit signed integer. (UI8 does not work with VB6). There are some limitations, for example TypeName does not work, whilst VarType does.
Example of function cInt64 to create a 64-bit integer variant which first creates a decimal variant then converts this to an I8 variant:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Enum VARENUM
VT_I8 = &H14
End Enum ' } VARENUM;
Private Type Dec_Hdr
DecType As Integer
DecScale As Byte
DecSign As Byte
End Type
Function cInt64(v As Variant) As Variant
Dim DecHdr As Dec_Hdr
cInt64 = CDec(v) ' first create a Decimal Variant
CopyMemory DecHdr, ByVal VarPtr(cInt64), Len(DecHdr)
'Correct possible CDec conversion errors with Hex strings
If VarType(v) = vbString Then
If InStr(1, v, "&h", vbTextCompare) = 1 Then DecHdr.DecSign = 0
End If
'Remove any decimal places
If DecHdr.DecScale Then cInt64 = Fix(cInt64)
'Convert Decimal to Int64, setting sign and scale to zero
CopyMemory ByVal VarPtr(cInt64), CLng(VT_I8), 4
'Adjust for Decimal Sign
If (DecHdr.DecSign <> 0) And (cInt64 > 0) Then cInt64 = -cInt64
'Finally check variant is of type I8
If (VarType(cInt64) <> VT_I8) Then Err.Raise 6
End Function

How to return a byte array as a variant in vb6

I've been trying to figure out why the function below throws an error saying "Type Mismatch" when it returns. From what I know about VB6, this should work without any issue, yet it obviously does not. Can anyone see what I am doing wrong here and let me know how I can fix it? Thanks in advance.
Private Function GetByteArray(source As Variant, index As Integer, length As Integer) As Variant
Dim buff() As Byte
ReDim buff(0 To length - 1)
Dim i As Integer
For i = 0 To length - 1
buff(i) = CByte(source(index + i))
Next i
GetByteArray = buff
End Function
It turns out that the problem did not have anything to do with the Function I posted, but rather with what I was doing with the result. I was using the method to get the bytes of a double, and then using CDbl to get the double value. This is where the error was really happening.
The way I should have been doing this is to use the following code:
CopyMemory rfcTest.rfcFloat, GetByteArray(buff, 0, 8), Len(rfcTest.rfcFloat)
Note that in order to use this, you must also declare the CopyMemoryMethod like this:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSrc As Any, ByVal ByteLen As Long)

Resources