Microsoft Developer Network > Программирование в Microsoft Visual Basic > Windows API и DLL > Примеры CopyMemory

Совет 173. Как реализовать функции MKx$/CVx в VB/Win

Именно с этого совета (№ 3) три года назад мы начали свои публикации для пользователей VB в КомпьютерПресс № 3’96. Напомнить о нем мы решили для иллюстрации применения функции CopyMemory.

Дело в том, что в DOS-овских версиях Microsoft Basic (Quick, PDS, Visual) имелась группа очень полезных встроенных функций MKx$/CVx (x — тип числовых данных: I, L, S, D), которые почему-то пропали в VB/Win. (Их описание приводится во встроенной справке QBasic, которая входит в состав Microsoft DOS 5.0 и 6.x.)

С помощью этих функций производится преобразование числовых (целых, вещественных и пр.) данных в строковый формат и наоборот. Точнее говоря, никакого преобразования значений здесь не выполняется, а просто N-е количество байт меняет название типа данных.

Основной смысл такого преобразования — это возможность хранения и передачи разнотипных данных в виде одной строковой переменной, что является отличной альтернативой структурам данных Type с их жестким описанием полей на уровне исходного текста. В свое время мы очень широко использовали в своей практике этот прием для создания гибких, динамически настраиваемых структур данных.

Применение данных функций позволяет осуществлять весьма изящные преобразования данных. Например, в Совете 117 мы говорили о проблеме обработки беззнаковых целых чисел и приводили пример слияния двух 16-разрядных целых чисел в 32-разрядное представление и наоборот.

Сравните приведенный там пример со следующим вариантом:

  1. LongValue& => IntHigh% & IntLow%

    Листинг 1.

    IntHigh% = CVI(LEFT$(MKL$(LongValue&), 2))
    IntLow% = CVI(RIGHT$(MKL$(LongValue&), 2))
    ' вместо Совета 117
    IntegetHigh% = LongValue& \ &H10000
    IntegerLow% = LongValue& And &H7FFF
    If (LongValue& AND &H8000) <> 0 Then
      IntegerLow% = IntegerLow% Or &H8000
    End If
  2. IntHigh% & IntLow% => LongValue&

    Листинг 2.

    LongValue& = CVL(MKI$(IntHigh%) + MKI$(IntLow%))
    ' вместо Совета 117
    LongValue& = IntHigh% * &H10000 + (IntegerLow% AND &H7FFF)
    If IntegerLow% < 0 Then LongValue& = LongValue& or &h8000&

С помощью функций Win API в VB/Win можно довольно просто реализовать эти полезные Basic-функции. Набор таких процедур приведен в модуле MKXCVX.BAS, а пример их применения — в модуле MKXCVXTS.BAS.

Листинг 3.

Attribute VB_Name = "MKxCVxTS"
Sub main()
   '
   ' Пример обращения к функциям MKx$, CVx
   ' в стиле "a-la" Microsoft Basic for DOS (QB/PDS/VBDOS)
   IntValue% = 12345
   x$ = MKI$(IntValue%)
   MsgBox Str$(CVI(x$)), , "Integer"
   '
   LongValue& = 12345678
   x$ = MKL$(LongValue&)
   MsgBox Str$(CVL(x$)), , "Long"
   '
   SingleValue! = 123.45
   x$ = MKS$(SingleValue!)
   MsgBox Str$(CVS(x$)), , "Single"
   '
   DoubleValue# = 1.2345
   x$ = MKD$(DoubleValue#)
   MsgBox Str$(CVD(x$)), , "Double"
   '
End Sub

===============================================================

Attribute VB_Name = "MKxCVx32"
 #If Win32 Then
   Public Declare Sub HMemCpy Lib "kernel32" Alias _
       "RtlMoveMemory" (Destination As Any, Source As Any, _
       ByVal Length As Long)
 #Else
   Declare Sub HMemCpy Lib "kernel" (hpvDest As Any, _
       hpvSource As Any, ByVal cbCopy As Long)
 #End If
'
' Реализация функций CVx/MKx$ с помощью обращения к
' функциям Windows API — HmemCpy или RtlMoveMemory
' (копирование заданного числа байт из одной области
' памяти в другую)
'
' ПРИМЕЧАНИЕ. Передача строковой переменной по значению
' (ByVal) означает, что в функцию HMemCpy передается
' адрес не описателя, а самой строки
'
Function CVD(x$) As Double
   HMemCpy Temp#, ByVal x$, 8
   CVD = Temp#
End Function

Function CVI(x$) As Integer
   HMemCpy Temp%, ByVal x$, 2
   CVI = Temp%
End Function

Function CVL(x$) As Long
   HMemCpy Temp&, ByVal x$, 4
   CVL = Temp&
End Function

Function CVS(x$) As Single
   HMemCpy Temp!, ByVal x$, 4
   CVS = Temp!
End Function

Function MKD$(x#)
   Dim Temp As String * 8
   HMemCpy ByVal Temp, x#, 8
   MKD$ = Temp
End Function

Function MKI$(x%)
   Dim Temp As String * 2
   HMemCpy ByVal Temp, x%, 2
   MKI$ = Temp
End Function

Function MKL$(x&)
   Dim Temp As String * 4
   HMemCpy ByVal Temp, x&, 4
   MKL$ = Temp
End Function

Function MKS$(x!)
   Dim Temp As String * 4
   HMemCpy ByVal Temp, x!, 4
   MKS$ = Temp
End Function