Adit Cookbook Pages

Home
Cookbook
A Question of Sorts
Bits & Bobs
Error Event Handling
SQL for Access
Grid Copy
Temporary Files
Delete or Kill
Credit Card
Virtual Arrays
Binary Chop
Numbers
VB to HTML
Viewport
Printing Grids

Storing  Numeric Values in Strings

Or Emulating the CVI and MKI$ functions

Or Whatever happened to hmemcpy?

I needed to extract some numbers being presented to an RS232 port as part of a string of bytes. The numbers were in binary format and I had the task of  extracting the relevant bits from the string to form integer values. I recalled ancient dialects of Basic that contained in built functions to encode numbers as strings so they could be stored in simple file structures. The MSDN library CD's revealed some emulation  functions for these and I decided to bring them up to date.

The problem with "mapping" an integer (say) into the same  memory space as a string is that VB's strong data typing gets in the way. The way around this used to be to use a 16 bit call to a windows sub called hmemcpy(). This copied the  bytes stored at any given memory location to another. So, to store an integer in a two  byte string you just copied the relevant two bytes of the integer to a predefined and  sized string in memory. When I came to look for hmemcpy() among the win32 API calls - it was missing. It was also missing from the list of calls that had not survived the  transition from 16 to 32 bits. A little research found another MSDN article taken from  Bruce McKinney's excellent book "Hardcore Visual Basic". If you can find a copy,  then you can follow the trail to Bruce McKinney's replacement for hmemcpy() -  CopyMemory(). This is defined as an "alias" for the RtlMoveMemory() function that resides in the Kernel32 library. Bruce gets all of the credit for this and thus for most of what follows, excluding any mistakes - these are all mine.

The code below can be downloaded (with a demonstration screen) as a zip  file by clicking here (3 KB). Instructions for  the demo can be found towards the end of this page.

In order to use the following functions you will need to declare the following

Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" _
(hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

The functions follow in pairs below:

Public Function MKI(ValToConvert As Integer) As String
    ’
This function converts an integer to a two byte string
    Dim WorkString As String
    
    WorkString = Space$(2)  ’
Get the size right
    CopyMemory ByVal WorkString, ValToConvert, 2
    MKI = WorkString
End Function
Public Function CVI(ValToConvert As String) As Integer
    ’
This function extracts an integer from a two byte string
    Dim WorkInt As Integer
    
    CopyMemory WorkInt, ByVal ValToConvert, 2
    CVI = WorkInt
End Function
Public Function MKL(ValToConvert As Long) As String
    ’
This function converts a Long to a four byte string
    Dim WorkString As String
    
    WorkString = Space$(4)  ’
Get the size right
    CopyMemory ByVal WorkString, ValToConvert, 4
    MKL = WorkString
End Function
Public Function CVL(ValToConvert As String) As Long
   
 ’This function extracts a long from a four byte string
    Dim WorkLong As Long
    
    CopyMemory WorkLong, ByVal ValToConvert, 4
    CVL = WorkLong
End Function
Public Function MKS(ByVal ValToConvert As Single) As String
    ’
this function converts a single to a four byte string
    Dim WorkString As String
    
    WorkString = Space$(4)
    CopyMemory ByVal WorkString, ValToConvert, 4
    MKS = WorkString
End Function
Public Function CVS(ValToConvert As String) As Single
    ’
This function converts the content of a 4 byte string to a single
    Dim WorkSingle As Single
    
    CopyMemory WorkSingle, ByVal ValToConvert, 4
    CVS = WorkSingle
End Function
Public Function MKD(ByVal ValToConvert As Double) As String
   
 ’This function places a double into an 8 byte string
    Dim WorkString As String
    
    WorkString = Space$(8)
    CopyMemory ByVal WorkString, ValToConvert, 8
    MKD = WorkString
End Function
Public Function CVD(ValToConvert As String) As Double
    ’
This function extracts a double form an 8 byte string
    Dim WorkDouble As Double
    
    CopyMemory WorkDouble, ByVal ValToConvert, 8
    CVD = WorkDouble
End Function

A short word of warning. You may not be as "thick" as me but when I was setting up the simple code demo for this cook-book entry I stored the returned  strings from the conversions in the relevant Caption property of the labels in the Frames. I noticed, that if the number passed to the floating point conversion functions was in fact an integer the caption stored a zero length string. Took me some minutes to work out  why and to change the demo string data storage to a simple array.

The downloadable demo code:

To operate the demo, put your numbers into the text box and then select the conversion type. Then click the "To string" button to encode the number as a string and to put it into storage. Clicking the "To Number" button will extract  the selected number type from the relevant storage string (provided there is something in  there already). There is an indicator (of sorts) to show which data types have a stored  value.

The functions should not be used within a class unless they are ONLY called from within that class. Using a class to expose them as a function to the rest of an application will result in a memory bounds error at runtime when they are used. As the demo code shows, they work just fine if included within a code module.

Google
 
Web www.adit.co.uk
www.aditsite.co.uk