Delphi转C#的问题

4
我有一个Delphi程序需要转换成c#。我已经完成了大部分的转换,但在VarArrayCreate方面遇到了一些挑战。
我的代码是这样的:Line := VarArrayCreate([0, 1], varVariant);
我似乎无法找到VarArrayCreate的转换或替代方法。我知道在c#中可以使用对象来替代Variant,但上述代码让我卡住了。
任何帮助都将不胜感激。
我已经添加了Delphi代码,我对“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.

迈克

4个回答

3

你的例子中VarArrayCreate调用创建了一个从索引0开始到索引1结束的2个元素数组。

C#等价于以下内容:

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

这是否是严格可比的?这不取决于Line[]成员的内容将要是什么吗?如果变量数组随后在调用COM接口时传递,那么数组实际上是一个变体数组而不仅仅是某个构造函数在功能/行为上类似的东西,这难道不重要吗?(当然我不知道 - 这些信息不在问题中。也许.NET会自动从对象数组强制转换为变体数组...同样,我不知道) - Deltics
@Deltics:我认为是这样的,在.NET中,所有东西都是从“object”派生的,即使是值类型也会被装箱为对象实例(类似于变体是几乎任何东西的盒子)。 - Jeroen Wiert Pluimers
好的,正如我所怀疑的那样,附加发布的代码表明,在严格的Delphi术语中,所需的只是一个整数数组的数组,而不是变体。但它还显示该变量被传递到COM接口,因此它需要是实际的变体数组,而不仅仅是功能上兼容的容器。我怀疑发布者需要调查.NET中显式变体支持以正确移植,而不仅仅是将Delphi代码转换为表面等效的.NET结构。 - Deltics
1
啊哈,但是我自己对这个领域进行了一些挖掘,发现.NET COM Interop确实会将对象数组作为变体数组进行封送。 :) - Deltics
1
很高兴你也得出了同样的结论。:P - dthorpe

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

上面是Alex的VB代码中ShowPoints方法的示例。它也适用于您要转换的Delphi代码的转换...
在C#中,object是最接近variant的东西。

1

需要提到的是,varArray创建了一个变体数据类型的数组,这与普通类型非常不同。它在内存中创建了一个结构,不能与对象实例(据我所知)进行比较。它预计将作为节点的互联(通过指针)列表存储。然而,Delphi变量结构与Microsoft自己的存储格式相同,这意味着您可以调用winapi来实现相同的功能。

如果您还没有解决问题,建议查看.NET内部的COM支持库。可能在“System.Runtime.InteropServices”下。或者查看Delphi中的variants.pas单元,看看它们调用了哪些WinAPI函数。


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() );

你要选择哪种方式取决于你的需要。如果你需要一个在程序运行时动态增长的“数组”,那么使用通用 List。否则,使用数组。

现在,需要记住的是这两者都是以0为基础的——而不像 Delphi 可以任意从 N 开始。

如果需要,你可以通过使用 HashTable 或 Dictionary 来模拟它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接