⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 curvepic.pas

📁 矢量图源代码 包括直线文本矩形等等
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit CurvePic;

interface

uses Windows,Graphics,Math,Classes,Controls,
  PicConst,PicBase,PicFuns;

const
  FOCUS_NUM=8;

type
  TCurvePoint=packed record
    aPointNum: Integer;
    aCurvePoint:Array[0..3] of TPoint;
  end;

type
  TCurvePic=Class(TPicBase)
    private
      FocusPoint:Array[1..FOCUS_NUM] of TPoint;
      fCurvePoint:TCurvePoint;
      MouseFocus: Integer;
      OldPoint: TPoint;
      procedure GetFocusPoints;
      procedure SetCurvePicRect;
      function  GetCurvePoint:TCurvePoint;
      function  GetCurvePointNum:Integer;
      procedure SetCurvePointNum(V:Integer);
    protected

    public
      constructor Create;
      destructor  Destroy; override;
      procedure DrawPic(ACanvas:TCanvas);  override;        //在acanvas上画图
      procedure MovePic(ACanvas:TCanvas; APoint:TPoint); override; //在acanvas上移动
      function  MouseInPicRegion(ACanvas:TCanvas;APoint:TPoint): MOUSE_POS; override; //鼠标位置
      function  CreatePicRgn(ACanvas:TCanvas): HRGN; override; //产生图元区域的句柄
      procedure DrawFocusRect(ACanvas:TCanvas); override; //在Acanvas上画焦点
      //鼠标响应
      procedure ParentMouseDown(ACanvas:TCanvas;CursorNum:Integer; Button: TMouseButton;Shift: TShiftState; APoint:TPoint); override;
      procedure ParentMouseMove(ACanvas:TCanvas;CursorNum:Integer; Shift: TShiftState;APoint:TPoint);  override;
      procedure ParentMouseUp(ACanvas:TCanvas;CursorNum:Integer; Button: TMouseButton;  Shift: TShiftState; APoint:TPoint); override;
      //键盘响应
      procedure ParentKeyDown(ACanvas:TCanvas;CursorNum:Integer; var Key: Word; mouse: TPoint; Shift:TShiftState); override;
      procedure ParentKeyUp(ACanvas:TCanvas;CursorNum:Integer; var Key: Word; mouse: TPoint; Shift: TShiftState); override;
      //图象改变
      procedure PicChangeing(ACanvas:TCanvas; mouseInPos: MOUSE_POS; chooseRect:TRect;
        mouseDownOldX, mouseDownOldY, mouseOldX, mouseOldY, mouseX, mouseY:Integer); override;
      procedure PicChangedUpdate(ACanvas:TCanvas; mouseInPos: MOUSE_POS;chooseRect: TRect; //选择图元形成的矩形
        mouseDownOldX, mouseDownOldY: Integer; mouseX, mouseY: Integer); override; //鼠标当前的坐标
      //位置代码可参见 PicConst.pas
      procedure AssignPic(SourcePic: TPicBase); override;
      //保存和读取数据
      procedure GetClassDataFromChar(var Len:Integer; var Buf:Array of Char); override;
      procedure SaveClassDataToChar(var Len:Integer; var Buf:Array of Char);  override;
      //非重载函数
      //绘图函数
      procedure DrawCurvePic(ACanvas: TCanvas; aPoints:Array of TPoint);
      //property 的实现方法
    published
      property CurvePoint: TCurvePoint read GetCurvePoint;
      property CurvePointNum:Integer read GetCurvePointNum write SetCurvePointNum;
      property PicPen;
      property PicBrush;
      Property PicFont;
      property PicRect;
      property Choosed;
      property PicId;
      property FocusPen;
      property FocusBrush;
      property DrawEndEvent;
      property PicIndex;
  end;


implementation

constructor TCurvePic.Create;
begin
  inherited Create;
  fCurvePoint.aPointNum:=0;
  MouseFocus:=-1;
end;

destructor  TCurvePic.Destroy;
begin
  inherited Destroy;
end;


function  TCurvePic.GetCurvePointNum:Integer;
begin
  Result:=fCurvePoint.aPointNum;
end;

procedure TCurvePic.SetCurvePointNum(V:Integer);
begin
  fCurvePoint.aPointNum:=0;
end;


procedure TCurvePic.GetFocusPoints;
var
  StartPos,EndPos:TPoint;
begin
  StartPos:=PicRect.TopLeft;
  EndPos:=PicRect.BottomRight;
  focusPoint[1] := startPos; //左上
  focusPoint[2] := Point((StartPos.X+ endPos.X)div 2, StartPos.Y); //上中
  focusPoint[3] := Point(EndPos.X,StartPos.Y); //右上
  focusPoint[4] := Point(StartPos.X,(StartPos.Y+ endPos.Y)div 2); //左中
  focusPoint[5] := Point(EndPos.X,(StartPos.Y+ endPos.Y)div 2); //右中
  focusPoint[6] := Point(StartPos.X,EndPos.Y); //左下
  focusPoint[7] := Point((StartPos.X + endPos.X)div 2, EndPos.Y); //下中
  focusPoint[8] := endPos; //终点
end;

procedure TCurvePic.SetCurvePicRect;
var
  i:Integer;
  tmpRect:TRect;
begin
  with tmpRect do begin
    Left  := fCurvePoint.aCurvePoint[0].x;
    Top   := fCurvePoint.aCurvePoint[0].y;
    Right := fCurvePoint.aCurvePoint[0].x;
    Bottom:= fCurvePoint.aCurvePoint[0].y;
  end;
  with tmpRect do begin
    for i := 1 to fCurvePoint.aPointNum-1 do begin
      Left  := Min(Left, fCurvePoint.aCurvePoint[i].x);
      Top   := Min(Top,  fCurvePoint.aCurvePoint[i].y);
      Right := Max(Right, fCurvePoint.aCurvePoint[i].x);
      Bottom:= Max(Bottom, fCurvePoint.aCurvePoint[i].y);
    end; //调整起点和终点的位置
    if Right = Left then  Inc(Right);
    if Top = Bottom then  Inc(Bottom);
  end;
  PicRect:=tmpRect;
end;

function  TCurvePic.GetCurvePoint:TCurvePoint;
begin
  Result:=fCurvePoint;
end;


procedure TCurvePic.DrawPic(ACanvas:TCanvas);         //在acanvas上画图
begin
  ACanvas.Pen:=PicPen;
  ACanvas.Brush:=PicBrush;
  ACanvas.Font:=PicFont;
  DrawCurvePic(ACanvas,fCurvePoint.aCurvePoint);
  if Choosed then DrawFocusRect(ACanvas);
end;

procedure TCurvePic.MovePic(ACanvas:TCanvas; APoint:TPoint); //在acanvas上移动
var
  i: Integer;
begin
  for i := 0 to fCurvePoint.aPointNum-1 do begin
    Inc(fCurvePoint.aCurvePoint[i].x, APoint.X);
    Inc(fCurvePoint.aCurvePoint[i].y, APoint.Y);
  end;
  //调整图元矩形区域
  SetCurvePicRect;
end;

function  TCurvePic.MouseInPicRegion(ACanvas:TCanvas;APoint:TPoint): MOUSE_POS;  //鼠标位置
var
  mRect: TRect;
  mPoint: Tpoint;
  i: Integer;
  polyHrgn: HRGN;
begin
  Result := POS_OUT;
  mPoint.x := APoint.X;
  mPoint.y := APoint.Y;
  polyHrgn := CreatePicRgn(ACanvas); //产生图元句柄
  if not Choosed  then begin //图元未选中,只要判断是否在图元区域即可
    if PtInRegion(polyHrgn, APoint.x, APoint.y) = True then  Result := POS_CENTER
  end else  begin //图元被选中,不仅要判断是否在图元区域,还需要判断在图元的具体位置
    if PtInRegion(polyHrgn, APoint.x, APoint.y) = True then Result := POS_CENTER;
    GetFocusPoints;
    for i := 1 to 8 do begin //先判断多边形所在矩形的8个焦点
      with mRect do  begin
        Left := focusPoint[i].x - FOCUS_SIZE;
        Top := focusPoint[i].y - FOCUS_SIZE;
        Right := focusPoint[i].x + FOCUS_SIZE;
        Bottom := focusPoint[i].y + FOCUS_SIZE;
      end;
      if PtInRect(mrect, mPoint) = True then  begin
        Result := MOUSE_POS(i);
        MouseFocus := 0;
        break;
      end;
    end;
    for i := 0 to fCurvePoint.aPointNum-1 do begin
      with mRect do begin
        Left := fCurvePoint.aCurvePoint[i].x - FOCUS_SIZE;
        Top := fCurvePoint.aCurvePoint[i].y - FOCUS_SIZE;
        Right := fCurvePoint.aCurvePoint[i].x + FOCUS_SIZE;
        Bottom := fCurvePoint.aCurvePoint[i].y + FOCUS_SIZE;
      end;
      if PtInRect(mrect, mPoint) = True then begin
        MouseFocus := i;
        Result := POS_CURVEPOINT;
        break;
      end;
    end;
  end;
  DeleteObject(polyHrgn);
end;

function  TCurvePic.CreatePicRgn(ACanvas:TCanvas): HRGN;  //产生图元区域的句柄
var
  i: Integer;
  drawVerPoint: array[0..4] of TPoint;
begin
  for i := 0 to 3 do drawVerPoint[i] :=fCurvePoint.aCurvePoint[i];
  LpToDp(ACanvas.Handle, drawVerPoint[0], 4);
  Result := CreatePolygonRgn(drawVerPoint[0], 4, ALTERNATE);
end;

procedure TCurvePic.DrawFocusRect(ACanvas:TCanvas); //在Acanvas上画焦点
var
  mRect: TRect;
  i: Integer;
begin
  GetFocusPoints;
  ACanvas.Pen:=FocusPen;
  ACanvas.Brush:=FocusBrush;
  for i := 1 to FOCUS_NUM do begin  //绘制焦点矩形
    mRect.Left := focusPoint[i].x - FOCUS_SIZE;
    mRect.Top := focusPoint[i].y - FOCUS_SIZE;
    mRect.Right := focusPoint[i].x + FOCUS_SIZE;
    mRect.Bottom := focusPoint[i].y + FOCUS_SIZE;
    ACanvas.Rectangle(mRect.Left, mRect.Top, mRect.Right, mRect.Bottom);
  end;
  for i := 0 to fCurvePoint.aPointNum-1 do begin  //绘制焦点矩形
    ACanvas.Brush.Color:=clLime;
    mRect.Left := fCurvePoint.aCurvePoint[i].x - FOCUS_SIZE;
    mRect.Top  := fCurvePoint.aCurvePoint[i].y - FOCUS_SIZE;
    mRect.Right := fCurvePoint.aCurvePoint[i].x + FOCUS_SIZE;
    mRect.Bottom:= fCurvePoint.aCurvePoint[i].y + FOCUS_SIZE;
    ACanvas.Rectangle(mRect.Left, mRect.Top, mRect.Right, mRect.Bottom);
  end;
end;

//鼠标响应
procedure TCurvePic.ParentMouseDown(ACanvas:TCanvas;CursorNum:Integer; Button: TMouseButton;Shift: TShiftState; APoint:TPoint);
var
  i:Integer;
begin
  if Button=mbLeft then begin
    OldPoint:=APoint;
    ACanvas.Pen:=PicPen;  //设置pen的格式
    ACanvas.Pen.Mode:=pmXor;
    //设置Brush的格式
    ACanvas.Brush:=PicBrush;
    Inc(fCurvePoint.aPointNum); //顶点数量加1
    case fCurvePoint.aPointNum of
      1: //鼠标第一次按下 bezier 起点
        begin
          fCurvePoint.aCurvePoint[0]:=APoint;
          For i:=1 to 3 do fCurvePoint.aCurvePoint[i]:=fCurvePoint.aCurvePoint[0];
        end;
      2: // bezier 终点
        begin
          ACanvas.PolyBezier(fCurvePoint.aCurvePoint);
          fCurvePoint.aCurvePoint[3]:=APoint;
          PicId:=PIC_CURVE;
        end;
      3: //bezier 控制点1
        begin
          ACanvas.PolyBezier(fCurvePoint.aCurvePoint);
          fCurvePoint.aCurvePoint[1]:=APoint;
        end;
      4: //bezier 控制点2
        begin
          ACanvas.PolyBezier(fCurvePoint.aCurvePoint);
          fCurvePoint.aCurvePoint[2]:=APoint;
          //曲线的四点输入完毕 调整总数组中的有关数据
          //SetCurvePicRect;
          //if Choosed then DrawFocusRect(ACanvas);
          //if Assigned(DrawEndEvent) then DrawEndEvent(Self);
        end;
    end;
  end else if Button=mbRight then begin
    if fCurvePoint.aPointNum =1 then begin
      ACanvas.PolyBezier(fCurvePoint.aCurvePoint);
      fCurvePoint.aPointNum:=0;
      PicId:=PIC_NONE;
    end;
  end;
end;

procedure TCurvePic.ParentMouseMove(ACanvas:TCanvas;CursorNum:Integer; Shift: TShiftState;APoint:TPoint);
begin
  if fCurvePoint.aPointNum > 0 then begin //绘制多边形开始
    ACanvas.Pen:=PicPen;  //设置pen的格式
    ACanvas.Pen.Mode:=pmXor;
    //设置Brush的格式
    ACanvas.Brush:=PicBrush;
    case fCurvePoint.aPointNum of
      1:
        begin
          OldPoint:=fCurvePoint.aCurvePoint[3];
          ACanvas.PolyBezier(fCurvePoint.aCurvePoint);
          fCurvePoint.aCurvePoint[3] := APoint;
          ACanvas.PolyBezier(fCurvePoint.aCurvePoint);
        end;
      2:
        begin
          OldPoint:=fCurvePoint.aCurvePoint[1];
          ACanvas.PolyBezier(fCurvePoint.aCurvePoint);
          fCurvePoint.aCurvePoint[1] := APoint;
          ACanvas.PolyBezier(fCurvePoint.aCurvePoint);
        end;
      3:
        begin
          OldPoint:=fCurvePoint.aCurvePoint[2];
          ACanvas.PolyBezier(fCurvePoint.aCurvePoint);
          fCurvePoint.aCurvePoint[2] := APoint;
          ACanvas.PolyBezier(fCurvePoint.aCurvePoint);
        end;
    end;
  end;
end;

procedure TCurvePic.ParentMouseUp(ACanvas:TCanvas;CursorNum:Integer; Button: TMouseButton;  Shift: TShiftState; APoint:TPoint);
begin  //
  if fCurvePoint.aPointNum=4 then begin
    SetCurvePicRect;
    if Choosed then DrawFocusRect(ACanvas);
    if Assigned(DrawEndEvent) then DrawEndEvent(Self);
  end;
end;

//键盘响应
procedure TCurvePic.ParentKeyDown(ACanvas:TCanvas;CursorNum:Integer; var Key: Word; mouse: TPoint; Shift:TShiftState);
begin

end;

procedure TCurvePic.ParentKeyUp(ACanvas:TCanvas;CursorNum:Integer; var Key: Word; mouse: TPoint; Shift: TShiftState);
begin

end;

//图象改变
procedure TCurvePic.PicChangeing(ACanvas:TCanvas; mouseInPos: MOUSE_POS; chooseRect:TRect;
        mouseDownOldX, mouseDownOldY, mouseOldX, mouseOldY, mouseX, mouseY:Integer);
var
  mouseDiffX: Integer;
  mouseDiffY: Integer;
  Center:TPoint;
  ratex,ratey:Single;
  RectW,RectH: Integer; //选择图元的宽度和高度
  tmpPoint:Array of TPoint;
  pp: array[1..3] of TPoint;
  i: Integer;
  procedure ConverPointXY;
  var
    j: Integer;
  begin
    for j:= 0 to fCurvePoint.aPointNum-1 do begin
      tmpPoint[j].x := center.x + Round((fCurvePoint.aCurvePoint[j].x - center.x) * rateX);
      tmpPoint[j].y := center.y + Round((fCurvePoint.aCurvePoint[j].y - center.y) * rateY);
    end;
  end;
  procedure ChangPointXY;  //坐标变换 是否交换起点和钟点
  begin
    //顶点坐标变换
    LpToDp(ACanvas.Handle, tmpPoint[0],fCurvePoint.aPointNum);
    DrawCurvePic(ACanvas, tmpPoint);
  end;
begin
  pp[1].x := mouseDownOldX;
  pp[1].y := mouseDownOldY;
  pp[2].x := mouseOldX;
  pp[2].y := mouseOldY;
  pp[3].x := mouseX;
  pp[3].y := mouseY;
  DPtoLP(ACanvas.Handle, pp[1], 3);
  mouseDownOldX := pp[1].x;
  mouseDownOldY := pp[1].y;
  mouseOldX := pp[2].x;
  mouseOldY := pp[2].y;
  mouseX := pp[3].x;
  mouseY := pp[3].y;
  //设置绘图方式
  ACanvas.Pen.Width := 1;
  ACanvas.Pen.Mode := pmXor;
  ACanvas.Pen.Style := psDot;
  ACanvas.Brush.Style := bsClear;
  //初始化变量值
  RectW:=ChooseRect.Right - ChooseRect.Left;
  RectH:=ChooseRect.Bottom - ChooseRect.Top;
  //设置数组长度
  SetLength(tmpPoint, fCurvePoint.aPointNum);
  //计算选择图元的宽度和高度
  case mouseInPos of
    POS_LEFTTOP: //         :Integer = 1  ; //左上
      begin
        //确定基准点
        Center.X:=ChooseRect.Right;
        Center.y := ChooseRect.Bottom;
        //鼠标当前位置与鼠标Down的差别
        mouseDiffX := mouseOldX - mouseDownOldX;
        mouseDiffY := mouseOldY - mouseDownOldY;
        //计算变化比例
        Ratex := (RectW - mouseDiffX) / RectW;
        Ratey := (RectH - mouseDiffY) / RectH;
        //绘制前一次虚线图元
        ConverPointXY;
        ChangPointXY;
        //鼠标当前位置与鼠标Down的差别
        mouseDiffX := mouseX - mouseDownOldX;
        mouseDiffY := mouseY - mouseDownOldY;
        //计算变化比例
        Ratex := (RectW - mouseDiffX) / RectW;
        Ratey := (RectH - mouseDiffY) / RectH;
        //绘制当前虚线图元
        ConverPointXY;
        ChangPointXY;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -