2010-12-16 160 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#變體最近的事情。