2010-12-16 123 views
4

我有一个Delphi程序,我必须转换为C#。我已经完成了大部分转换,但遇到了VarArrayCreate的一些挑战。德尔福到C#问题

我所拥有的是:Line:= VarArrayCreate([0,1],varVariant);

我似乎无法弄清楚VarArrayCreate的转换或替代。 我知道c#中的对象可以用于Variant替代品,但上面有我卡住。

任何帮助将是伟大的。

我已经加入下面我感兴趣的过程“TForm1.Button3Click(发信人:TObject的)的Delphi代码;过程:

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. 

麦克

回答

0

你可以做一个“正常”的数组....

MyType[] Line = new MyType[2]; 

或泛型列表....

List<MyType> Line = new List<MyType>(); // list is empty, still have to add n elements 
Line.Add(new MyType()); 
Line.Add(new MyType()); 

你走哪条路取决于你所需要的。如果您需要在程序运行时动态增长的“数组”,请使用通用列表。如果没有,请使用数组。

现在,需要记住的是,其中任何一个都是基于0的 - 并不是像德尔福那样从N开始任意开始。

现在,您可以使用HashTableDictionary来模拟,如果需要的话。

3

的VarArrayCreate呼叫在你的例子是创建一个数组开始索引零并用索引结束2个元素1.

C#的等效会是这样:

object[] Line; 
Line = new object[2]; 
+0

这是严格的可比性?那岂不是依赖于行的什么内容[]成员继续是?如果随后将变量数组传递给COM接口,那么数组实际上是变体数组并不重要吗? f变体,而不是简单的一些构造在功能/行为上恰好相似?(当然,我不知道 - 这些信息不在问题中,也许.NET会自动从一个对象数组中强制变体的变体阵列......我不知道) – Deltics 2010-12-17 01:19:51

+0

@Deltics :我认为是这样的,因为在.NET中,所有东西都是从'object'下降的,甚至值类型都会被装箱到一个对象实例(类似于几乎任何东西的变体)。 – 2010-12-17 09:48:52

+0

那么,正如我怀疑的那样,额外的代码表明,严格的Delphi术语所需要的只是一个Integer数组的数组,而不是Variant。但它也表明变体正在传递给COM接口,所以它需要是一个实际的变体数组,而不仅仅是一个功能兼容的容器。我怀疑海报需要调查.NET中显式的Variant支持以正确地进行端口转换,而不是简单地将Delphi代码转换为表面上等效的.NET结构。 – Deltics 2010-12-17 23:14:34

1

也许应该提到的是,varArray会创建一个变体数据类型的数组,这与正常类型非常不同。它在内存中创建一个无法与对象实例(AFAIK)进行比较的结构。预计将被存储为相互链接的(通过指针)节点列表。但是,Delphi变体结构与Microsoft自己的存储格式相同,这意味着您可以调用winapi来实现相同的功能。

如果你还没有解决它,我会看看.NET中的COM支持库。也许在“System.Runtime.InteropServices””。还是看看在Delphi中variants.pas单元,看看他们所谓的WinAPI的功能。

+0

请参阅我的编辑请求我已经添加了delphi代码 – Mike 2010-12-17 17:45:41

1
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); 
} 

以上是由亚历克斯的VB代码ShowPoints方法的一个例子,它也适用于正在转换的Delphi代码的转换...

对象在C#变体最近的事情。