Wednesday, November 30, 2005
PocketCaddy gets the ECO treatment
A while ago I wrote an application to demonstrate the capabilities of the Delphi for .NET Compact Framework preview compiler. This application was designed to keep track of the scores for a round of golf for one or more players, and has been floating around on CodeCentral for a while. It was even given a mention in David Intersimone's blog.
One thing that became apparent very early on in the PocketCaddy development cycle was that it that it is extremely tedious to enter course and player data on a PocketPC device. I decided to use this as an excuse to finally dive head first into the ECO world, and set about creating an administration application which would allow data to be entered on a PC and downloaded to the PocketPC via a web service. I am pleased to announce that this is now downloadable from CodeCentral.
Because this was my first ECO application, I wanted to explore many aspects of ECO development, so as a result it will show examples of the following ECO technologies and techniques :-
- ECO Winforms application
- ECO web service application
- ECO sync server application used by the Winforms and web service applications to broker persistence requests to an Interbase database
- Traversing an ECO model at runtime and serializing to custom XML
- Custom AutoForms implementation (ported from an original C# implementation written by Peter Morris, with his kind permission)
Be aware that it was developed using Delphi 2006 and ECO III, so you may be unable to compile it in Delphi 2005. Nevertheless the code should still give insights into many techniques that will work with ECO II. Feel free to offer any feedback, but please be gentle. As I mentioned earlier, this was my first attempt at an ECO app :-)
Thursday, November 24, 2005
Enumerating COM ports in Delphi for .NET
unit AvailablePortsUnit;
interface
uses
System.Runtime.InteropServices, System.Collections.Specialized;
type
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
PORT_INFO_1 = record
pName: string;
end;
function AvailablePorts(const AComPortsOnly: Boolean): StringCollection;
implementation
[DllImport('winspool.drv', CharSet=CharSet.Auto)]
function EnumPorts(AName: string; ALevel: Integer; ABuffer: IntPtr;
ACbBuff: Integer; out ANeeded: Integer; out AReturned: Integer): Boolean; external;
function AvailablePorts(const AComPortsOnly: Boolean): StringCollection;
type
TPortInfoArray = array of PORT_INFO_1;
var
lIndex: Integer;
lComName: string;
i: Integer;
lCurrent: IntPtr;
lPorts: TPortInfoArray;
lBuffer: IntPtr;
lNeeded: Integer;
lReturned: Integer;
begin
Result := StringCollection.Create;
lBuffer := IntPtr.Zero;
EnumPorts(nil, 1, lBuffer, 0, lNeeded, lReturned);
lBuffer := Marshal.AllocHGlobal((lNeeded + 1));
try
EnumPorts(nil, 1, lBuffer, lNeeded, lNeeded, lReturned);
SetLength(lPorts, lReturned);
lCurrent := lBuffer;
for i := 0 to lReturned - 1 do
begin
lPorts[i] := (PORT_INFO_1(Marshal.PtrToStructure(lCurrent, TypeOf(PORT_INFO_1))));
if (not AComPortsOnly) or (lPorts[i].pName.StartsWith('COM')) then
begin
if AComPortsOnly then
begin
lIndex := lPorts[i].pName.IndexOf(':');
if (lIndex <> -1) then
lComName := lPorts[i].pName.Remove(lIndex, 1)
else
lComName := lPorts[i].pName;
end
else
lComName := lPorts[i].pName;
Result.Add(lComName);
end;
lCurrent := IntPtr((Integer(lCurrent) + Marshal.SizeOf(TypeOf(PORT_INFO_1))));
end;
finally
Marshal.FreeHGlobal(lBuffer);
end;
end;
end.