About the author
Well, I was going to talk about how I designed a wizard using the Open Tools API to create Control Panel applets, but I haven't succeeded in that, so it's a talk planned for the near future when I managed to gain more of an understanding with the Open Tools API, or become “one with the Open Tools API” in Delphi 8.
Then, I figured, what the heck? I might as well talk about how I managed to migrate that Delphi 7 Date Control Panel applet, which runs on the Win32 platform, to Delphi 8, which runs on the .NET platform.
Right. Now, on with the talk. The difficulty in migrating the control panel applet is listed in the items shown below.
The control panel applet structure looks like this.
tagNEWCPLINFOA = packed record dwSize: DWORD; // similar to the commdlg dwFlags: DWORD; dwHelpContext: DWORD; // help context to use lData: Longint; // user defined data hIcon: HICON; // icon to use, this is owned by CONTROL.EXE (may be deleted) szName: array[0..31] of AnsiChar; // or WideChar szInfo: array[0..63] of AnsiChar; szHelpFile: array[0..127] of AnsiChar; end;In order to translate this Win32 structure to .NET, there is a need to apply some attributes to the record. The structure, translated to .NET, looks like
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] tagNEWCPLINFO = packed record dwSize: DWORD; // similar to the commdlg dwFlags: DWORD; dwHelpContext: DWORD; // help context to use lData: Longint; // user defined data hIcon: HICON; // icon to use, this is owned by CONTROL.EXE (may be deleted) [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] szName: string; // short name [MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)] szInfo: string; // long name (status line) [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] szHelpFile: string; // path to help file to use end;The CLR controls the physical layout of data fields in a class or structure. With the StructLayout attribute, the class/structure can be arranged in a certain way so that it can be passed to unmanaged code that expects a specific layout.
As seen in the translation above, most of the fields in the record can be translated without any changes, except for the 3 string fields, which are translated to string, and adorned with the MarshalAs attribute. The ByValTStr tells the CLR that when it is passed to unmanaged code, it should be unwrapped into an array of Char, or WideChar, depending on whether the platform is Win98/ME (in which case it's unwrapped into array of Char of 32, 64, or 128 in size), or WinNT/2000 (in which case, it's unwrapped into an array of WideChar of 32, 64, or 128 in size). The CharSet attribute, as set to Auto, informs the CLR what to do. So, if the CharSet is set to Ansi, the strings are unwrapped to array[0..Size-1] of Char, wherelse if CharSet is set to Unicode, the strings are unwrapped to array of [0..Size-1] of WideChar, and when the CharSet is set to Auto, the strings are unwrapped to array[0..Size-1] of WideChar or array[0..Size-1] of Char, depending on whether the platform is Unicode (WinNT/2000/XP/2003) or Ansi (Win98/ME).
To be continued...