用Ole Automation实现Delphi和AutoCad之间的数据交换

类别:Delphi 点击:0 评论:0 推荐:

 

用Ole Automation实现Delphi和AutoCad之间的数据交换
                      广州 XD.W

    AutoCad是一些做设计的朋友最常用软件之一,有时需要从AutoCad的图纸
中提取数据进行一些计算和优化工作,用手工进行提取工作量非常大;用AutoCad
的AutoLisp、ADS或者ObjectArx进行计算,对不熟悉的人来说掌握起来比较困难,
界面也不够友好。下面我们通过Ole Automation,利用Delphi来实现这一工作,
相关的AutoCad Automation信息请参见AutoCad的帮助文件acadauto.hlp。
    首先在Delphi中建立一个新工程,在主Form放置三个TButton,分别命名为:
btnOpen,btnSend,btnGet,用于实现打开AutoCad,向Cad发送数据,从Cad提取
数据的功能,再放置一个TPaintBox,用于实现输出功能。下面是程序的主单元代码。

unit main;
interface

uses
file://在引用单元中要包含ComObj单元,用于支持Ole操作。
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, ComObj;

const
file://定义AutoCad中的实体类型常量,本程序中只用到直线,所以只定义了直线的类型常量。
  acLine = 19;

type
file://定义程序中用到的数据结构
  ZPoint = record
    x,y: double;
  end;

  PZLine = ^ZLine;
  ZLine = record
    sp,ep: ZPoint;
    next: PZLine;
  end;

  TForm1 = class(TForm)
    Panel1: TPanel;
    btnOpen: TButton;
    BtnSend: TButton;
    btnGet: TButton;
    PaintBox1: TPaintBox;
    procedure btnOpenClick(Sender: TObject);
    procedure btnSendClick(Sender: TObject);
    procedure btnGetClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure PaintBox1Paint(Sender: TObject);
  private
file://存放数据的指针 
    pData: PZLine;
file://释放存放数据的内存
    procedure FreeData;
  public
  end;

var
  Form1: TForm1;

implementation
{$R *.DFM}

procedure TForm1.FreeData;
var
  pTmp: PZLine;
begin
file://释放数据链表内存
  while pData <> nil do begin
    pTmp := pData;
    pData := pData^.next;
    Dispose(pTmp);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
file://在主窗体的创建时初始化数据指针
  pData := nil;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
file://在主窗体的销毁过程中释放内存
  FreeData;
end;

file://打开AutoCad
procedure TForm1.btnOpenClick(Sender: TObject);
var
 AcadApp : OleVariant;
begin
file://通过创建Ole Automation对象启动AutoCad
 AcadApp := CreateOleObject('AutoCad.Application');
 AcadApp.visible := true;
file://OleVariant数据类型是自动释放的,所以这里没有释放代码
end;

file://向AutoCad发送数据
procedure TForm1.btnSendClick(Sender: TObject);
var
  AcadApp: OleVariant;
  AcadDoc: OleVariant;
  AcadMoSpace: OleVariant;
  sp,ep: Variant;
  pTmp: PZLine;
begin
file://得到已启动的AutoCad Application对象
  AcadApp := GetActiveOleObject('AutoCad.Application');
file://得到AutoCad Document对象
  AcadDoc := AcadApp.ActiveDocument;
file://得到AutoCad ModelSpace对象
  AcadMoSpace := AcadDoc.ModelSpace;
file://遍历数据链表
  pTmp := pData;
  while pTmp <> nil do begin
file://创建包含数组的Variant变量sp,用于向AutoCad传递起点数据
   sp := VarArrayCreate([0,2],VarDouble);
    sp[0] := pTmp^.sp.x;
    sp[1] := pTmp^.sp.y;
    sp[2] := 0.0;
file://创建包含数组的Variant变量ep,用于向AutoCad传送终点数据
    ep := VarArrayCreate([0,2],VarDouble);
    ep[0] := pTmp^.ep.x;
    ep[1] := pTmp^.ep.y;
    ep[2] := 0.0;
file://VarArrayRef把包含数组的Variant变量转换成Variant数组,
file://使用AutoCad 14.0时要调用此函数,AutoCad 2000不需要
    AcadMoSpace.AddLine(VarArrayRef(sp),VarArrayRef(ep));
    pTmp := pTmp^.next;
  end;
end;

file://从AutoCad提取数据
procedure TForm1.btnGetClick(Sender: TObject);
var
  AcadApp: OleVariant;
  AcadDoc: OleVariant;
  AcadMoSpace: OleVariant;
  AcadObj: OleVariant;
  AcadPt: Variant;
  i: integer;
  EntiType: Integer;
  pTmp: PZLine;
begin
file://得到所需的AutoCad对象
  AcadApp := GetActiveOleObject('AutoCad.Application');
  AcadDoc := AcadApp.ActiveDocument;
  AcadMoSpace := AcadDoc.ModelSpace;
file://释放以前存放的数据
  FreeData;
file://遍历模型空间中的每一个实体对象
 for i := 0 to AcadMoSpace.Count-1 do begin
file://引用第i个实体对象
    AcadObj := AcadMoSpace.Item(i);
file://提取实体类型
    EntiType := AcadObj.EntityType;
file://判断是不是直线
    if EntiType = acLine then begin
file://如果是直线,则提取相应的起点终点数据
      new(pTmp);
      AcadPt := AcadObj.StartPoint;
      pTmp^.sp.x := AcadPt[0];
      pTmp^.sp.y := AcadPt[1];
      AcadPt := AcadObj.EndPoint;
      pTmp^.ep.x := AcadPt[0];
      pTmp^.ep.y := AcadPt[1];
      pTmp^.next := pData;
      pData := pTmp;
    end;
  end;
file://刷新用于显示结果的PaintBox
  PaintBox1.Invalidate;
end;

file://显示提取的数据
procedure TForm1.PaintBox1Paint(Sender: TObject);
var
  MaxX, MaxY: double;
  MinX, MinY: double;
  pTmp: PZLine;
  scale: double;
  x,y: integer;
begin
  pTmp := pData;
  if pTmp = nil then exit;
 
file://计算放缩比例 
  MaxX := pTmp^.sp.x;
  MinX := MaxX;
  MaxY := pTmp^.sp.y;
  MinY := MaxY;
  while pTmp <> nil do begin
    if MaxX < pTmp^.sp.x then MaxX := pTmp^.sp.x;
    if MinX > pTmp^.sp.x then MinX := pTmp^.sp.x;
    if MaxY < pTmp^.sp.y then MaxY := pTmp^.sp.y;
    if MinY > pTmp^.sp.y then MinY := pTmp^.sp.y;
    if MaxX < pTmp^.ep.x then MaxX := pTmp^.ep.x;
    if MinX > pTmp^.ep.x then MinX := pTmp^.ep.x;
    if MaxY < pTmp^.ep.y then MaxY := pTmp^.ep.y;
    if MinY > pTmp^.ep.y then MinY := pTmp^.ep.y;
    pTmp := pTmp^.next;
  end;
  scale := (PaintBox1.Width - 10) / (MaxX-MinX);
  if scale > (PaintBox1.Height - 10) / (MaxY-MinY) then begin
    scale := (PaintBox1.Height - 10) / (MaxY-MinY);
  end;
 
file://显示提取的数据
  pTmp := pData;
  while pTmp <> nil do begin
    x := round((pTmp^.sp.x - MinX) * scale) + 5;
    y := PaintBox1.Height - (round((pTmp^.sp.y - MinY) * scale) + 5);
    PaintBox1.Canvas.MoveTo(x,y);
    x := round((pTmp^.ep.x - MinX) * scale) + 5;
    y := PaintBox1.Height - (round((pTmp^.ep.y - MinY) * scale) + 5);
    PaintBox1.Canvas.LineTo(x,y);
    pTmp := pTmp^.next;
  end;
end;

end.

    本程序在PWin98se+Delphi5.0环境下编译通过,在AutoCad14.0、AutoCad2000
下运行通过,源代码可在此下载:http://wangxd.51.net/software/delphicad.zip。

本文地址:http://com.8s8s.com/it/it6052.htm