I have a Delphi program I have to convert to c#. I have done most of the conversion but ran into a couple of challenges with VarArrayCreate.
what I have is this : Line := VarArrayCreate([0, 1], varVariant);
I can't seem to figure out a conversion or substitute for the VarArrayCreate. I know that the object in c# can be used for Variant substitute but the above has me stuck.
any help would be great.
I have added the Delphi code below I interested in the procedure "TForm1.Button3Click(Sender: TObject); procedure:
unit Unit1;
(*------------------------------------------------------------------------------
DX Atlas Automation demo #2 (early binding)
Make sure that DX Atlas is installed.
Requires DxAtlas_TLB. You can either generate this file in Delphi
(Project -> Import Type Library -> DxAtlas) or use the one included
with this demo.
http://www.dxatlas.com
------------------------------------------------------------------------------*)
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
OleServer, StdCtrls, DxAtlas_TLB, ActiveX, AxCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
CheckBox1: TCheckBox;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Button6: TButton;
procedure FormShow(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
private
{ Private declarations }
public
Atlas: IAtlas;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//------------------------------------------------------------------------------
// Start DX Atlas
//------------------------------------------------------------------------------
procedure TForm1.FormCreate(Sender: TObject);
begin
//connect to Dx Atlas on program startup
try
Atlas := CoAtlas.Create;
except on E: Exception do
begin
ShowMessage('Cannot connect to DX Atlas: ' + E.Message);
Application.Terminate;
end;
end;
end;
procedure TForm1.FormShow(Sender: TObject);
var
WorkArea: TRect;
begin
//get Desktop work area dimensions
SystemParametersInfo(SPI_GETWORKAREA, 0, @WorkArea, 0);
//form placement
Top := WorkArea.Top;
Left := WorkArea.Left;
Height := WorkArea.Bottom - WorkArea.Top;
//atlas placement
//stop repainting
Atlas.Map.BeginUpdate;
//place window
Atlas.Top := Top;
Atlas.Left := Left + Width;
Atlas.Width := WorkArea.Right - Left - Width;
Atlas.Height := Height;
//hide prefixes
Atlas.Map.PrefixesVisible := false;
//now allow repainting
Atlas.Map.EndUpdate;
//show the Atlas window
Atlas.Visible := true;
end;
//------------------------------------------------------------------------------
// Points
//------------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
Pt, Points: OleVariant;
i: integer;
Layer: ICustomLayer;
begin
Randomize;
//create Variant array for data
Points := VarArrayCreate([0, 999], varVariant);
//fill the array with random points
for i:=0 to 999 do
begin
//each point is a variant array with 2 elements
Pt := VarArrayCreate([0,1], varVariant);
//point coordinates are random (decimal degrees)
Pt[0] := Random(360) - 180; //longitude
Pt[1] := Random(180) - 90; //latitude
//add point to the data array
Points[i] := Pt;
end;
//show data on the map
Atlas.Map.BeginUpdate;
with Atlas.Map do
try
Projection := PRJ_RECTANGULAR;
Dimmed := false;
CustomLayers.Clear;
//add new custom layer
Layer := CustomLayers.Add(LK_POINTS);
with Layer do
begin
//set layer attributes
PenColor := clBlue;
BrushColor := clLime;
PointSize := 2;
//set data
SetData(Points);
end;
finally
EndUpdate;
end;
end;
//------------------------------------------------------------------------------
// Labels
//------------------------------------------------------------------------------
procedure TForm1.Button2Click(Sender: TObject);
var
//Lb: Variant;
Labels: Variant;
i: integer;
Layer: ICustomLayer;
begin
Randomize;
Labels := VarArrayCreate([0, 999], varVariant);
for i:=0 to 999 do
begin
//each label is a variant array of 3 Variants
Labels[i] := VarArrayOf([Random(360) - 180, //longitude
Random(180) - 90, //latitude
Format(' LABEL #%d ', [i])]); //label text
//alternate way of creating and filling the array
{
Lb := VarArrayCreate([0,2], varVariant);
Lb[0] := Random(360) - 180;
Lb[1] := Random(180) - 90;
Lb[2] := Format(' Label #%d ', [i]);
Labels[i] := Lb;
}
end;
Atlas.Map.BeginUpdate;
with Atlas.Map do
try
Projection := PRJ_RECTANGULAR;
Dimmed := false;
CustomLayers.Clear;
Layer := CustomLayers.Add(LK_LABELS);
with Layer do
begin
LabelsTransparent := CheckBox1.Checked;
//label BG if not transparent
BrushColor := clAqua;
//font attributes
with (Font as IFont) do
begin
Put_Name('Courier New');
Put_Italic(true);
Put_Size(9);
//Put_Name('Small fonts');
//Put_Size(5);
end;
//font color
PenColor := clBlue;
//data
SetData(Labels);
end;
finally
EndUpdate;
end;
end;
//------------------------------------------------------------------------------
// Lines
//------------------------------------------------------------------------------
procedure TForm1.Button3Click(Sender: TObject);
var
Pt, Line, Meridians, Parallels: OleVariant;
i, j: integer;
begin
//generate meridians
Meridians := VarArrayCreate([0, 7], varVariant);
for i:=0 to 7 do
begin
Line := VarArrayCreate([0, 36], varVariant);
for j:=0 to 36 do
begin
Pt := VarArrayCreate([0, 1], varVariant);
Pt[0] := i*45 - 180;
Pt[1] := j*5 - 90;
Line[j] := Pt;
end;
Meridians[i] := Line;
end;
//generate parallels
Parallels := VarArrayCreate([0, 2], varVariant);
for i:=0 to 2 do
begin
Line := VarArrayCreate([0, 72], varVariant);
for j:=0 to 72 do
begin
Pt := VarArrayCreate([0, 1], varVariant);
Pt[0] := j*5 - 180;
Pt[1] := i*45 - 45;
Line[j] := Pt;
end;
Parallels[i] := Line;
end;
//show on the map
Atlas.Map.BeginUpdate;
with Atlas.Map do
try
Projection := PRJ_AZIMUTHAL;
Dimmed := false;
CenterLatitude := 43;
CenterLongitude := -79;
CustomLayers.Clear;
//show meridians
with CustomLayers.Add(LK_LINES) do
begin
PenColor := clBlue;
SetData(Meridians);
end;
//show parallels
with CustomLayers.Add(LK_LINES) do
begin
PenColor := clRed;
SetData(Parallels);
end;
finally
EndUpdate;
end;
end;
//------------------------------------------------------------------------------
// Area
//------------------------------------------------------------------------------
procedure TForm1.Button4Click(Sender: TObject);
var
Pt, Area, Areas: OleVariant;
i: integer;
begin
//single area
Areas := VarArrayCreate([0, 0], varVariant);
//generate area data
Area := VarArrayCreate([0, 72], varVariant);
for i:=0 to 72 do
begin
Pt := VarArrayCreate([0, 1], varVariant);
Pt[0] := -79 + 20 * cos(i*5/180*Pi);
Pt[1] := 43 + 20 * sin(i*5/180*Pi);
Area[i] := Pt;
end;
Areas[0] := Area;
//show on the map
Atlas.Map.BeginUpdate;
with Atlas.Map do
try
Projection := PRJ_RECTANGULAR;
Dimmed := true;
CustomLayers.Clear;
with CustomLayers.Add(LK_AREAS) do
begin
AreaBrightness := 12; //0..15, 15=max
SetData(Areas);
end;
finally
EndUpdate;
end;
end;
//------------------------------------------------------------------------------
// Glyphs
//------------------------------------------------------------------------------
procedure TForm1.Button5Click(Sender: TObject);
var
Glyphs: Variant;
i: integer;
Layer: ICustomLayer;
begin
Randomize;
//create array of Variants
Glyphs := VarArrayCreate([0,333], varVariant);
//each element of the array is a variant array with 3 elements
for i:=0 to 333 do
Glyphs[i] := VarArrayOf([Random(360)-180, //longitude -180..180
Random(180)-90, //latitude -90..90
Random(10)]); //image index 0..9
Atlas.Map.BeginUpdate;
with Atlas.Map do
try
Projection := PRJ_RECTANGULAR;
Dimmed := false;
//delete all layers
CustomLayers.Clear;
//add layer
Layer := CustomLayers.Add(LK_GLYPHS);
//Glyphs.bmp is a bitmap 160x16 that contains 10 glyphs, 16x16 each
//the color of lower left pixel (clFuchsia) is considered transparent
//the hot spot of the glyph is at (1, 15).
Layer.LoadGlyphsFromFile(ExtractFilePath(ParamStr(0)) + 'Glyphs.bmp', 1, 15);
//send locations to the layer
Layer.SetData(Glyphs);
finally
//now allow repainting
EndUpdate;
end;
end;
//------------------------------------------------------------------------------
// Great Circle paths
//------------------------------------------------------------------------------
procedure TForm1.Button6Click(Sender: TObject);
var
Pt, Line, Lines: Variant;
i, j: integer;
begin
//generate an array of Great Circle paths
Lines := VarArrayCreate([0, 33], varVariant);
for i:=0 to 33 do
begin
//a Great Circle path is defined by its end points
Line := VarArrayCreate([0, 1], varVariant);
Line[0] := VarArrayOf([-79, 43 {Toronto}]);
Line[1] := VarArrayOf([Random(360) - 180, Random(180) - 90]);
//add path to the array
Lines[i] := Line;
end;
//show paths on the map
Atlas.Map.BeginUpdate;
with Atlas.Map do
try
Projection := PRJ_RECTANGULAR;
Dimmed := false;
CustomLayers.Clear;
with CustomLayers.Add(LK_LINES) do
begin
PenColor := clBlue;
SetData(Lines);
end;
finally
EndUpdate;
end;
//Note that Delphi automatically releases the variant arrays when they go out of scope开发者_运维百科.
//In other languages you may have to release them explicitly.
end;
end.
Mike
The VarArrayCreate call in your example is creating an array of 2 elements starting with index zero and ending with index 1.
The C# equivalent would be this:
object[] Line;
Line = new object[2];
It should perhaps be mentioned that varArray creates an array of the variant datatype, which is quite different from normal types. It creates a structure in memory that cannot be compared to an object instance (AFAIK). It is expected to be stored as an inter-linked (by pointer) list of nodes. However, the Delphi variant structure is identical to Microsoft's own storage format, which means you can call winapi to achieve the same thing.
If you havent solved it yet I would take a look at the COM support libraries inside .NET. Probably under "System.Runtime.InteropServices"". Or look at the variants.pas unit in Delphi and see what WinAPI functions they call.
private void _showPoints()
{
object[] pt = new object[2];
object[] points = new object[4];
for (int i = 0; i < 3; i++)
{
pt[0] = _dx[i, 0];
pt[1] = _dx[i, 1];
points[i] = pt;
}
_aquaPoints.SetData(points);
}
Above is an example of the ShowPoints method from Alex's VB code. It will also apply to the conversion of the Delphi code you are converting...
object is the nearest thing to variant in C#.
you can either make a "normal" array....
MyType[] Line = new MyType[2];
or a generic List....
List<MyType> Line = new List<MyType>(); // list is empty, still have to add n elements
Line.Add( new MyType() );
Line.Add( new MyType() );
which way you go depends on what you need. If you need an "array" that grows dynamically while your program is running, go with a generic List. if not, go with an array.
now, the thing to keep in mind is that either one of these is 0 based--not arbitrarily starting at N like Delphi can do.
now, you could simulate that with a HashTable
or a Dictionary
, if you need to.
精彩评论