UDTs
on Windows CE:We may assume that the same approach was used on
Windows CE. However,
this hasnt been tested systematically on all the processors supported by Windows
CE. Take caution with this.
So, now that we know how to fill every byte of a UDT, all we have to do is write some
functions to build a String with the exact same values. For our example:
Public
Function IntegerToBinaryString(ByVal IntIn As Integer) As String
Dim aux As Integer
aux = IntIn: If IntIn < 0 Then aux
= IntIn - &H8000
IntegerToBinaryString =
IntegerToBinaryString & ChrB(aux Mod 256)
aux = aux \ 256
If IntIn < 0 Then
IntegerToBinaryString
= IntegerToBinaryString & ChrB(aux + &H80)
Else
IntegerToBinaryString
= IntegerToBinaryString & ChrB(aux)
End If
End
Function
Public
Function SYSTEMTIME( _
wYear As Integer, _
wMonth As Integer, _
wDayOfWeek As Integer, _
wDay As Integer, _
wHour As Integer, _
wMinute As Integer, _
wSecond As Integer, _
wMilliseconds As Integer) As
String
SYSTEMTIME = _
IntegerToBinaryString(wYear)
& _
IntegerToBinaryString(wMonth)
& _
IntegerToBinaryString(wDayOfWeek)
& _
IntegerToBinaryString(wDay)
& _
IntegerToBinaryString(wHour) & _
IntegerToBinaryString(wMinute)
& _
IntegerToBinaryString(wSecond)
& _
IntegerToBinaryString(wMilliseconds)
End Function
Be careful with the Declare statement: the UDT must always be specified as a String passed ByVal which IS NOT what youll find on the API Text Viewer
for the Winceapi. This is the correct Declare:
Declare
Function SetLocalTime Lib "Coredll" _
(ByVal
lpSystemTime As String) As Long
Notice that, on Windows CE, most of the system calls will use Coredll.dll
instead of Kernel32.dll. Also, Windows CE is a UNICODE OS meaning that every
string character occupies two bytes. Be careful: for example, Mid(StringIn, 1, 1) will
return two bytes; MidB(StringIn, 1, 1) will return only one.
Our call ends up as follows:
Dim
sysTime as string
SysTime = SYSTEMTIME(1999, 12, 0, 31, 24, 59, 59, 0)
Call SetLocalTime(sysTime)
and will perform the same way as its 95/98/NT counterpart.
There are still other problems that we could face: when we have a UDT with a UDT
field. This would mean that wed have to pass the address of the inner UDT as a Long in the outer UDT. However, these functions are seldom used.
Other problem, which is much more common, is when we pass an empty UDT to the
system call in order to receive the information back from that call inside this UDT.
Lets assume we implement the code to have a calendar control on our form.
This is more complicated because will have to deal with messages between windows. However,
the interesting part for our discussion is that the Time/Date is sent back to us as a SYSTEMTIME UDT.
As we saw previously, we have to reserve an empty block of memory with the same
size as the UDT. In VBCE theres no fixed length strings (we cant use Dim
aux * 8 , p.e) but this is easily solved:
Dim aux as String: aux = String(8, Chr(0))
Remember that WinCE uses UNICODE: weve just reserverd 16 bytes of memory
the same size as a SYSTEMTIME UDT variable.
Call the function as in the following example:
MonthCal_GetCurSel = SendMessage(hmc, MCM_GETCURSEL, 0, aux)
In aux we receive a string with all the UDT bytes. Lets get
them:
Dim
wYear As Integer, wMonth As Integer, wDayOfWeek As Integer
Dim wDay As Integer, wHour As Integer, wMinute As Integer
Dim wSecond As Integer, wMilliseconds As Integer
Call getSYSTEMTIME(aux, _
wYear,
wMonth, wDayOfWeek, wDay, wHour, wMinute, wSecond, wMilliseconds)
And the last thing: implement the get functions:
Public
Function BinaryStringToInteger(StringIn As String) As Integer
If AscB(MidB(StringIn, 2)) And
&H80 Then
BinaryStringToInteger
= (AscB(MidB(StringIn, 2)) - &HFF) * 256 + _
(AscB(StringIn)
- 256)
Else
BinaryStringToInteger
= AscB(MidB(StringIn, 2)) * 256 + AscB(StringIn)
End If
End
Function
Public
Sub getSYSTEMTIME(ByVal str As String, _
ByRef wYear As Integer, ByRef
wMonth As Integer, _
ByRef wDayOfWeek As Integer,
ByRef wDay As Integer, _
ByRef wHour As Integer, ByRef
wMinute As Integer, _
ByRef wSecond As Integer, ByRef
wMilliseconds As Integer)
wYear
= BinaryStringToInteger(MidB(str, 1, 2)))
wMonth =
BinaryStringToInteger(MidB(str, 3, 2))
wDayOfWeek =
BinaryStringToInteger(MidB(str, 5, 2))
wDay =
BinaryStringToInteger(MidB(str, 7, 2))
wHour =
BinaryStringToInteger(MidB(str, 9, 2))
wMinute =
BinaryStringToInteger(MidB(str, 11, 2))
wSecond =
BinaryStringToInteger(MidB(str, 13, 2))
wMilliseconds =
BinaryStringToInteger(MidB(str, 15, 2))
End
Sub