Delphi Clinic | C++Builder Gate | Training & Consultancy | Delphi Notes Weblog | Dr.Bob's Webshop |
|
Almost everybody has experienced a situation for which two Bytes had to be converted to a Word, or two Words to a LongInt, etc.
We can use the Lo and Hi built-in functions to get the low-order or high-order Byte of the argument, but we cannot go back easily or can we?
In fact, there are many techniques we can use to 'merge' 2 Bytes to a single Word. The first way is to use the absolute keyword, to make sure the bytes and word use the same memory space, like this:
var LowByte, HighByte: Byte; MergedWord: Word absolute LoWByte;Now, the variable MergedWord contains the combined values of the two bytes LowByte and HighByte. We don't even have to do or call anything!
type TWord = record case Boolean of true: (LowByte, HighByte: Byte); false: (MergedWord: Word); end {TWord};although this is in fact only a variation of the absolute method mapping MergedWord to the same address space occupied by LowByte and HighByte.
We can of course use the same techniques to convert two Words or four Bytes (or to Bytes and a Word) into a LongInt:
type TLongInt = record case Boolean of True: (LWLoByte, LWHiByte, HWLoByte, HWHiByte: Byte; False: (LoWord: Word; HiWord: Word); end {TLongInt};Now we can simultaneously assign values to the HiWord, or to the HighByte of the LowWord (= LWHiByte). All without executing any code to convert between datatypes!!
As a useful example of this technique, let's take a look at how to obtain the DOS and Windows' version number. For dissecting the info returned by GetVersion you can use this variant record:
var Version: record case Boolean of False: ( Windows: record major: Byte; minor: Byte; end; DOS: record minor: Byte; major: Byte; end; ); True: (GetVersion: LongInt); end {Version};The GetVersion API returns 3.1 for Windows 3.1, Windows 3.11, Windows for Workgroups 3.11 and Windows NT (if called from a 16-bits Windows application), 3.95 for Windows 95 (when called from a 16-bits Windows applications), and 4.0 for Win32 applications (on Win95 or NT).
As a bonus for this time, you can find out if you're really running on NT (vs. Win95) with the following 16-bits code:
const WF_WINNT = $4000; NT := (GetWinFlags and WF_WINNT) <> 0;This code doesn't work on Win32, however (GetWinFlags has been removed, and we need to call GetSystemInfo from now on).
The final example program - using the variant record technique - that tells you which version of DOS/Windows you're running is as follows:
program Hood7; uses WinProcs, SysUtils, Dialogs; var Version: record case Boolean of False: ( Windows: record major: Byte; minor: Byte; end; DOS: record minor: Byte; major: Byte; end; ); True: (GetVersion: LongInt); end {Version}; begin Version.GetVersion := GetVersion; if Version.Windows.major < 4 then ShowMessage(Format('DOS %d.%-d, Windows %d.%-d', [Version.DOS.major,Version.DOS.minor, Version.Windows.major,Version.Windows.minor])) else ShowMessage(Format('Windows 95/NT %d.%-d', [Version.Windows.major,Version.Windows.minor])) end.When compiled with Delphi 1.02 and run on Windows 95, this program returns "DOS 7.0, Windows 3.95". When compiled with Delphi 2.01 and run on Windows 95, this program returns "Windows 95/NT 4.00", and so it should.