这个例子有错误! 点的类型很多时候不是单一的;

譬如某个点可能同时是子路径结束点、曲线点、标记点, 此时类型值就是三种类型的复合值.

遗憾的是做这个例子时, 我还不知道... 放在这里吧, 留个纪念, 记下曾经的幼稚!


本例效果图:



代码文件:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    procedure FormCreate(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses GDIPOBJ, GDIPAPI;

procedure TForm1.FormCreate(Sender: TObject);
begin
  StringGrid1.Align := alRight;
  StringGrid1.FixedCols := 0;
  StringGrid1.ColCount := 3;
  StringGrid1.ColWidths[0] := 25;
  StringGrid1.ColWidths[1] := 25;
  StringGrid1.ColWidths[2] := 80;
  StringGrid1.DefaultRowHeight := 20;

  StringGrid1.Cells[0,0] := 'X';
  StringGrid1.Cells[1,0] := 'Y';
  StringGrid1.Cells[2,0] := '点类型';
end;

procedure TForm1.FormPaint(Sender: TObject);
var
  g: TGPGraphics;
  p: TGPPen;
  path: TGPGraphicsPath;
  points: array of TGPPoint;
  types: PByte;
  typestr: string;
  i: Integer;
begin
  g := TGPGraphics.Create(Canvas.Handle);
  p := TGPPen.Create(aclRed);
  path := TGPGraphicsPath.Create;

  path.StartFigure;
  path.AddRectangle(MakeRect(30,20,90,40));
  path.AddEllipse(MakeRect(30,80,90,180));
  path.CloseFigure;

  g.DrawPath(p, path);

  SetLength(points, path.GetPointCount);
  GetMem(types, path.GetPointCount);

  path.GetPathPoints(PGPPoint(points), Length(points));
  path.GetPathTypes(types, Length(points));

  StringGrid1.RowCount := Length(points) + 1;

  for i := 0 to Length(points) - 1 do
  begin
    case types^ of
      $00 : typestr := '路径起始点';
      $01 : typestr := '直线点';
      $03 : typestr := '贝塞尔线点';
      $07 : typestr := '遮盖点';
      $10 : typestr := '虚线点';
      $20 : typestr := '路径标记';
      $80 : typestr := '子路径结束点';
    end;
    StringGrid1.Cells[0, i+1] := IntToStr(points[i].X);
    StringGrid1.Cells[1, i+1] := IntToStr(points[i].Y);
    StringGrid1.Cells[2, i+1] := typestr;
    Inc(types);
  end;

  Dec(types, Length(points));
  FreeMem(types);
  types := nil;
  path.Free;
  p.Free;
  g.Free;
end;

procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
var
  x,y: Integer;
begin
  x := StrToIntDef(StringGrid1.Cells[0,ARow], 0);
  y := StrToIntDef(StringGrid1.Cells[1,ARow], 0);
  Repaint;
  Canvas.Brush.Color := clBlue;
  Canvas.FillRect(Bounds(x-3,y-3,6,6));
  Text := Format('%d,%d',[x,y]);
end;

end.

这个例子有点麻烦, 如果使用 TPathData 类会简单许多, 下面是用 TPathData 实现的代码, 运行效果相同; 不过这样获取的点数组必须是小数数组. 代码如下:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    procedure FormCreate(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses GDIPOBJ, GDIPAPI;

procedure TForm1.FormCreate(Sender: TObject);
begin
  StringGrid1.Align := alRight;
  StringGrid1.FixedCols := 0;
  StringGrid1.ColCount := 3;
  StringGrid1.ColWidths[0] := 25;
  StringGrid1.ColWidths[1] := 25;
  StringGrid1.ColWidths[2] := 80;
  StringGrid1.DefaultRowHeight := 20;

  StringGrid1.Cells[0,0] := 'X';
  StringGrid1.Cells[1,0] := 'Y';
  StringGrid1.Cells[2,0] := '点类型';
end;

procedure TForm1.FormPaint(Sender: TObject);
var
  g: TGPGraphics;
  p: TGPPen;
  path: TGPGraphicsPath;
  PathData: TPathData;
  Points: PGPPointF;
  Types: PByte;
  TypeStr: string;
  i: Integer;
begin
  g := TGPGraphics.Create(Canvas.Handle);
  p := TGPPen.Create(aclRed);
  path := TGPGraphicsPath.Create;

  path.StartFigure;
  path.AddRectangle(MakeRect(30,20,90,40));
  path.AddEllipse(MakeRect(30,80,90,180));
  path.CloseFigure;

  g.DrawPath(p, path);

  PathData := TPathData.Create;
  path.GetPathData(PathData);
  Points := PathData.Points;
  Types := PathData.Types;

  StringGrid1.RowCount := PathData.Count + 1;

  for i := 0 to PathData.Count - 1 do
  begin
    case Types^ of
      $00 : TypeStr := '路径起始点';
      $01 : TypeStr := '直线点';
      $03 : TypeStr := '贝塞尔线点';
      $07 : TypeStr := '遮盖点';
      $10 : TypeStr := '虚线点';
      $20 : TypeStr := '路径标记';
      $80 : TypeStr := '子路径结束点';
    end;
    StringGrid1.Cells[0, i+1] := IntToStr(Trunc(Points.X));
    StringGrid1.Cells[1, i+1] := IntToStr(Trunc(Points.Y));
    StringGrid1.Cells[2, i+1] := TypeStr;
    Inc(Points);
    Inc(Types);
  end;

  PathData.Free;
  path.Free;
  p.Free;
  g.Free;
end;

procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
var
  x,y: Integer;
begin
  x := StrToIntDef(StringGrid1.Cells[0,ARow], 0);
  y := StrToIntDef(StringGrid1.Cells[1,ARow], 0);
  Repaint;
  Canvas.Brush.Color := clBlue;
  Canvas.FillRect(Bounds(x-3,y-3,6,6));
  Text := Format('%d,%d',[x,y]);
end;

end.

窗体文件:
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 276
  ClientWidth = 303
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  Position = poDesktopCenter
  OnCreate = FormCreate
  OnPaint = FormPaint
  PixelsPerInch = 96
  TextHeight = 13
  object StringGrid1: TStringGrid
    Left = 88
    Top = 40
    Width = 154
    Height = 120
    TabOrder = 0
    OnSelectCell = StringGrid1SelectCell
  end
end

路径中的点类型枚举:
PathPointType = (
  PathPointTypeStart        = $00, {路径起始点}
  PathPointTypeLine         = $01, {直线点}
  PathPointTypeBezier       = $03, {默认贝塞尔线点}
  PathPointTypePathTypeMask = $07, {遮盖点}
  PathPointTypeDashMode     = $10, {虚线点}
  PathPointTypePathMarker   = $20, {路径标记}
  PathPointTypeCloseSubpath = $80, {子路径结束点}

  PathPointTypeBezier3      = $03  {立体贝塞尔线点}
);
TPathPointType = PathPointType;

posted on 2008-06-18 18:23  万一  阅读(3451)  评论(0编辑  收藏  举报