Ross Mack - GUI Computing
'Code, the final frontier...,
These are the voyages of the Starship GUI its continuing mission...,
To explore strange new code to seek out new Tools and new Applications...,
To boldly code what no programmer has coded before.'
Sometimes you get a chance to write something fun using whatever tool you want. This is one of those times.
I originally wrote this DLL in Delphi 1.0 - since then I have ported it to 32 bit and adjusted the functionality a little. Its only purpose is to return the current StarDate as a string. If you do not know what a StarDate is, watch an episode of Star Trek (doesn't matter which episode or flavour) and then come back.
StarDates are a time measurement used in Star Trek. In fact, in the original series (remember Kirk and Spock?) StarDates they meant nothing - they just used random numbers. It was only with the beginnings of Star Trek: The Next Generation that a system was designed to create coherent StarDates. As it turns out they are not a really very useful time measurement, but they work like this anyway:
The first digit is the second digit of the current century (in the 1900s this is a 9). The second digit indicates the series number of Star Trek: The Next Generation that the StarDate is used in. If the StarDate was during the first series of Next Generation, this will be a 1 (one). In the second season it will be a 2, and so on. Next Generation went for seven seasons so the StarDates of the last season began with 47... (Next Generation takes place in the 2400s). This gets a little more complicated with Star Trek - Deep Space Nine and Star Trek - Voyager. Deep Space Nine works its StarDates off whatever the concurrent series number of Next Generation is, and proceeds from there. Voyager proceeds chronologically after the end of Next Generation. The StarDates in the first series of Voyager start with 48, indicating the eighth series of Next Generation (this is equivalent only, there were only seven seasons - as I just mentioned). Here is a little chart:
The next three digits represent the approximate time of year as a portion of 1000 (like a percentage times 10). Therefore, 500 would be midyear. 100 would be early February. 250 would be early April. And so on...
StarDates then have a decimal point and another single digit. This represents the portion of the current day-cycle that has passed in tenths. 5 is midday, 1 is 2 or 3 in the morning, 7 is late afternoon. Let's take an example: 41000.1 - would be about 2:30 am New Years Day of the year in which the first series of Star Trek: the Next Generation is set (that series doesn't actually start until about March of that year).
OK, now that explains what the DLL calculates. Unfortunately we live in the real world and not a series of Next Generation, so series one (1) is assumed for the purposes of the StarDate calculation. For both the 16 and 32 bit version I have provided two calls to retrieve the same data. Both versions support a very basic call that should be used as the lowest common denominator. It works very much like the GetPrivateProfileString API. The VB programmer is required to allocate a string of a size sufficient to accommodate the return value, and then pass that string and its length into the function. Then the function writes data into that string and returns how much data it wrote, so the calling code knows how much of the string is significant. In theory a StarDate is always 7 characters, but there you have it. The call in VB looks like this:
' Using fixed length strings Dim sResult As String * 10 Dim iResult As Integer iResult = StarDate(sResult, 10) MsgBox Left$(sResult, iResult),64,"The Current StarDate is:" or ' Using a variable length string Dim sResult As String Dim iResult As Integer sResult = Space$(10) iResult = StarDate(sResult, 10) sResult = Left$(sResult, iResult) MsgBox sResult, 64,"The Current StarDate is:"
If we didn't pre-allocate the string space we would very quickly get a General Protection Fault (try it if you like…), as the DLL attempts to write data into memory that has not been allocated.
After some discussion with Delphi guru and all round nice guy, Jim Karabatsos, I have implemented an extra call in each DLL to provide an easier interface.
In the 16 bit DLL we use a library provided by Borland to write directly to a VB style string. This means that the function requires no arguments and simply returns a string. This technique is explained by Jim in his article Returning VB Strings from DLLs. I have included the required library in the source code of the downloadable zip file. Because Jim explains this technique so well, I won't go into it here except to say that it simplifies the above code to the following:
' Writing directly to a VB String MsgBox vbStarDate()
In the case of the 32 bit DLL we do something a little more exciting and useful overall. We use the universal accessibility of OLE2 to render the return value as an OLE string. In fact, in this case we use Delphi 2's in-built OLE2 library to perform this transformation - no bizarre specific libraries needed. Again this simplifies the call to a point where it requires no arguments and returns a string directly. The VB 4 code would look like this:
' Writing directly to an OLE string MsgBox vbStarDate()
Better yet, because we are now returning a universal type from a very simple call, we can embed a StarDate directly in an Excel 95 cell, using the following simple Call:function:
Now, that's cool.
The downloadable zip file - stardate.zip (56 kb) - contains both the 16 bit (startrek.dll) and the 32bit (strek32.dll) DLLs. It also contains a text file showing declares for use in Visual Basic and Delphi, for both the 16 and 32 bit versions. You will also find the complete code for both versions. I have named the DLLs differently so that both the 16 and 32 bit versions can coexist in memory, or in your system directory, without any conflicts.