dviewer.pas

来自「KSDev.BlockEngine.v3.03.rar 界面控件」· PAS 代码 · 共 1,449 行 · 第 1/3 页

PAS
1,449
字号
          { Draw middle tic }
          Pt := PaperToScreen(Tics + TicsStep / 2, 0);
          MoveTo(Pt.X, RulerMargin * 3);
          LineTo(Pt.X, RulerSize - RulerMargin);
          { Draw left and right tics }
          Pt := PaperToScreen(Tics + TicsStep / 4, 0);
          MoveTo(Pt.X, RulerMargin * 3);
          LineTo(Pt.X, RulerSize - RulerMargin);
          Pt := PaperToScreen(Tics + TicsStep / 2 + TicsStep / 4, 0);
          MoveTo(Pt.X, RulerMargin * 3);
          LineTo(Pt.X, RulerSize - RulerMargin);

          Tics := Tics + TicsStep;
        end;
        { Draw mouse X }
        Pen.Color := clHighlight;
        MoveTo(FMousePos.X, RulerMargin);
        LineTo(FMousePos.X, RulerSize - RulerMargin);
      end;
    end;

    Canvas.Draw(0, 0, Buffer);

    { Vertical }
    Buffer.Width := RulerSize;
    Buffer.Height := ClientHeight;
    with Buffer.Canvas do
    begin
      R := Classes.Rect(0, 0, Buffer.Width, Buffer.Height);
      Brush.Style := bsSolid;
      Brush.Color := clBtnFace;
      FillRect(R);
      if Document <> nil then
      begin
        { Calc rulers vars }
        InflateRect(R, -RulerMargin, -RulerMargin);
        with Document.Paper do
        begin
          Pt := PaperToScreen(0, 0);
          R.Top := Pt.Y;
          Pt := PaperToScreen(Width, Height);
          R.Bottom := Pt.Y;
        end;
        Brush.Color := clWindow;
        FillRect(R);

        { Draw tics }
        Pen.Color := clBlack;
        Tics := - Trunc(PageY / TicsStep) * TicsStep;
        { Set font }
        Brush.Style := bsClear;
        Font.Name := 'Arial';
        Font.Size := 6;
        while Tics < WorkHeight do
        begin
          { Draw big tic }
          Pt := PaperToScreen(0, Tics);
          MoveTo(RulerMargin, Pt.Y);
          LineTo(RulerSize - RulerMargin, Pt.Y);
          { Draw text }
          if (Document <> nil) and (Document.UnitType = Centimeter) then
            TextOut(RulerMargin, Pt.Y + 2, IntToStr(Round(Tics / 10)))
          else
            TextOut(RulerMargin, Pt.Y + 2, IntToStr(Trunc(Tics)));
          { Draw middle tic }
          Pt := PaperToScreen(0, Tics + TicsStep / 2);
          MoveTo(RulerMargin * 3, Pt.Y);
          LineTo(RulerSize - RulerMargin, Pt.Y);
          { Draw left and right tics }
          Pt := PaperToScreen(0, Tics + TicsStep / 4);
          MoveTo(RulerMargin * 3, Pt.Y);
          LineTo(RulerSize - RulerMargin, Pt.Y);
          Pt := PaperToScreen(0, Tics + TicsStep / 2 + TicsStep / 4);
          MoveTo(RulerMargin * 3, Pt.Y);
          LineTo(RulerSize - RulerMargin, Pt.Y);

          Tics := Tics + TicsStep;
        end;

        { Draw mouse X }
        Pen.Color := clHighlight;
        MoveTo(RulerMargin, FMousePos.Y);
        LineTo(RulerSize - RulerMargin, FMousePos.Y);
      end;
    end;
    Canvas.Draw(0, 0, Buffer);
  finally
    Buffer.Free;
  end;

  { Draw gripper }
  SelectClipRgn(Canvas.Handle, 0);
  Canvas.Brush.Color := clBtnFace;
  Canvas.FillRect(Classes.Rect(0, 0, RulerSize, RulerSize));
end;

procedure TBlockViewer.PaintPaper;
var
  P, P1: TGPPen;
  B: TGPBrush;
  ShadowWidth: single;
  SaveState: cardinal;
  L, X, Y: Float;
begin
  if FDisableUpdate then Exit;
  if Document = nil then Exit;
  SetGraphics;
  if Clipped then
    if ClipRgn <> nil then
      Graphics.SetClip(ClipRgn);

  Graphics.SetSmoothingMode(SmoothingModeInvalid);

  case FViewKind of
    vkPage:
      begin
        { Draw background }
        B := TGPSolidBrush.Create($FF707070);
        Graphics.FillRectangle(B, ViewX, ViewY, ViewWidth, ViewHeight);
        B.Free;
        { Draw shadow }
        B := TGPSolidBrush.Create($FF202020);
        ShadowWidth := GetRealValue(3);
        Graphics.FillRectangle(B, PageX + PageWidth, PageY + ShadowWidth, ShadowWidth, PageHeight);
        Graphics.FillRectangle(B, PageX + ShadowWidth, PageY + PageHeight, PageWidth - ShadowWidth, ShadowWidth);
        B.Free;
        { Draw paper }
        B := TGPSolidBrush.Create(aclWhite);
        Graphics.FillRectangle(B, PageX, PageY, PageWidth, PageHeight);
        B.Free;
        { OnPaint }
        if Assigned(OnPaint) then
          OnPaint(Self, Graphics, MakeFloatRect2(PageX, PageY, PageWidth, PageHeight));
        { Draw grid }
        if FShowGrid then
        begin
          if FGridKind = gkAuto then
          begin
            X := 0;
            P := TGPPen.Create($FFDDDDDD, GetRealValue(1));
            P1 := TGPPen.Create($FFEEEEEE, GetRealValue(1));
            while X < PageWidth do
            begin
              Graphics.DrawLine(P, PageX + X, PageY, PageX + X, PageY + PageHeight);
              X := X + TicsStep / 4;
              if X > PageWidth then Break;
              Graphics.DrawLine(P1, PageX + X, PageY, PageX + X, PageY + PageHeight);
              X := X + TicsStep / 4;
              if X > PageWidth then Break;
              Graphics.DrawLine(P1, PageX + X, PageY, PageX + X, PageY + PageHeight);
              X := X + TicsStep / 4;
              if X > PageWidth then Break;
              Graphics.DrawLine(P1, PageX + X, PageY, PageX + X, PageY + PageHeight);
              X := X + TicsStep / 4;
            end;
            X := 0;
            while X < PageHeight do
            begin
              Graphics.DrawLine(P, PageX, PageY + X, PageX + PageWidth, PageY + X);
              X := X + TicsStep / 4;
              if X > PageHeight then Break;
              Graphics.DrawLine(P1, PageX, PageY + X, PageX + PageWidth, PageY + X);
              X := X + TicsStep / 4;
              if X > PageHeight then Break;
              Graphics.DrawLine(P1, PageX, PageY + X, PageX + PageWidth, PageY + X);
              X := X + TicsStep / 4;
              if X > PageHeight then Break;
              Graphics.DrawLine(P1, PageX, PageY + X, PageX + PageWidth, PageY + X);
              X := X + TicsStep / 4;
            end;
            P1.Free;
            P.Free;
          end;
          if (FGridKind = gkFixed) and (GetPixelValue(FGridHSize) > 3) and (GetPixelValue(FGridVSize) > 3)then
          begin
            L := GetRealValue(1);
            B := TGPSolidBrush.Create($FFBBBBBB);
            X := FGridHSize;
            while X < PageWidth do
            begin
              Y := FGridVSize;
              while Y < PageHeight do
              begin
                Graphics.FillRectangle(B, PageX + X, PageY + Y, L, L);
                Y := Y + FGridVSize;
              end;
              X := X + FGridHSize;
            end;
            B.Free;
          end;
        end;
        { Draw border }
        P := TGPPen.Create(aclBlack, GetRealValue(1));
        Graphics.DrawRectangle(P, PageX, PageY, PageWidth, PageHeight);
        P.Free;
      end;
    vkBlank:
      begin
        { Draw view }
        B := TGPSolidBrush.Create(aclWhite);
        Graphics.FillRectangle(B, ViewX, ViewY, ViewWidth, ViewHeight);
        B.Free;
        { OnPaint }
        if Assigned(OnPaint) then
          OnPaint(Self, Graphics, MakeFloatRect2(ViewX, ViewY, ViewWidth, ViewHeight));
        { Draw grid }
        if FShowGrid then
        begin
          if FGridKind = gkAuto then
          begin
            X := 0;
            P := TGPPen.Create($FFDDDDDD, GetRealValue(1));
            P1 := TGPPen.Create($FFEEEEEE, GetRealValue(1));
            while (X < ViewX + ViewWidth) do
            begin
              Graphics.DrawLine(P, PageX + X, ViewY, PageX + X, ViewY + ViewHeight);
              X := X + TicsStep / 4;
              Graphics.DrawLine(P1, PageX + X, ViewY, PageX + X, ViewY + ViewHeight);
              X := X + TicsStep / 4;
              Graphics.DrawLine(P1, PageX + X, ViewY, PageX + X, ViewY + ViewHeight);
              X := X + TicsStep / 4;
              Graphics.DrawLine(P1, PageX + X, ViewY, PageX + X, ViewY + ViewHeight);
              X := X + TicsStep / 4;
            end;
            X := 0;
            while (X < ViewY + ViewHeight) do
            begin
              Graphics.DrawLine(P, ViewX, PageY + X, ViewX + ViewWidth, PageY + X);
              X := X + TicsStep / 4;
              Graphics.DrawLine(P1, ViewX, PageY + X, ViewX + ViewWidth, PageY + X);
              X := X + TicsStep / 4;
              Graphics.DrawLine(P1, ViewX, PageY + X, ViewX + ViewWidth, PageY + X);
              X := X + TicsStep / 4;
              Graphics.DrawLine(P1, ViewX, PageY + X, ViewX + ViewWidth, PageY + X);
              X := X + TicsStep / 4;
            end;
            P1.Free;
            P.Free;
          end;
          if (FGridKind = gkFixed) and (GetPixelValue(FGridHSize) > 3) and (GetPixelValue(FGridVSize) > 3)then
          begin
            L := GetRealValue(1);
            B := TGPSolidBrush.Create($FFBBBBBB);
            X := FGridHSize;
            while (X < ViewWidth) or (X < WorkWidth) do
            begin
              Y := FGridVSize;
              while Y < PageHeight do
              begin
                Graphics.FillRectangle(B, PageX + X, PageY + Y, L, L);
                Y := Y + FGridVSize;
              end;
              X := X + FGridHSize;
            end;
            B.Free;
          end;
        end;
      end;
  end;

  // check region
  if Clipped then
  begin
{    B := TGPSolidBrush.Create($FF000000 or Random($FFFFFF));
    if ClipRgn <> nil then
    begin
      Graphics.FillRegion(B, ClipRgn);
    end;
    B.Free;}
  end;

  { Draw Document }
  SaveState := Graphics.Save;
  try
    { Set transform }
    Graphics.TranslateTransform(PageX, PageY);
    if FSmooth then
    begin
      Graphics.SetSmoothingMode(SmoothingModeAntiAlias);
      Graphics.SetPixelOffsetMode(PixelOffsetModeHighQuality);
    end
    else
    begin
      Graphics.SetPixelOffsetMode(PixelOffsetModeNone);
    end;

    { Drawing Document }
    PaintBlockDocument;
  finally
    Graphics.Restore(SaveState)
  end;
end;

procedure TBlockViewer.PaintBlockDocument;
begin
  if FDisableUpdate then Exit;
  Document.Draw(Graphics);
end;

procedure TBlockViewer.PaintBlockDocumentToCanvas(Canvas: TCanvas);
var
  G: TGPGraphics;
begin
  if Document = nil then Exit;

  G := TGPGraphics.Create(Canvas.Handle, 0, 0);
  try
    G.SetPageUnit(UnitTypeToGPUnit(Document.UnitType));
    G.SetSmoothingMode(SmoothingModeAntiAlias);

    Document.BlockRoot.DesignState := Document.BlockRoot.DesignState - [dsDesignMode];
    Document.Draw(G);
    Document.BlockRoot.DesignState := Document.BlockRoot.DesignState + [dsDesignMode];
  finally
    G.Free;
  end;
end;

procedure TBlockViewer.WMRepaint(var Msg: TMessage);
var
  UpdateAll: boolean;
  P1, P2: FloatPoint;
  Rcts: array [0..1000] of TRect;
  i, RCount: integer;
  R: TRect;

 procedure ProcessPaintMessages;
 var
   RMsg: TMsg;
 begin
   while PeekMessage(RMsg, Handle, WM_REPAINT, WM_REPAINT, PM_REMOVE) do
   begin
     if UpdateAll then Continue;
     if RMsg.WParam <> 0 then
     begin
       P1 := ScreenToPaper(TSmallPoint(RMsg.WParam).Y - 2, TSmallPoint(RMsg.WParam).X - 2);
       P2 := ScreenToPaper(TSmallPoint(RMsg.LParam).Y + 2, TSmallPoint(RMsg.LParam).X + 2);
       ClipRgn.Union(MakeRect(P1.X, P1.Y, P2.X - P1.X, P2.Y - P1.Y));
       Rcts[RCount] := Classes.Rect(TSmallPoint(RMsg.WParam).Y, TSmallPoint(RMsg.WParam).X,
         TSmallPoint(RMsg.LParam).Y, TSmallPoint(RMsg.LParam).X);
       Inc(RCount);
     end
     else
       UpdateAll := true;
   end;
 end;
begin
  if FDisableUpdate then Exit;
  if not IsWindowVisible(Handle) then Exit;

  if Msg.WParam <> 0 then
  begin
    UpdateAll := false;

    P1 := ScreenToPaper(TSmallPoint(Msg.WParam).Y, TSmallPoint(Msg.WParam).X);
    P2 := ScreenToPaper(TSmallPoint(Msg.LParam).Y, TSmallPoint(Msg.LParam).X);
    ClipRgn := TGPRegion.Create(MakeRect(P1.X, P1.Y, P2.X - P1.X, P2.Y - P1.Y));

    Rcts[0] := Classes.Rect(TSmallPoint(Msg.WParam).Y, TSmallPoint(Msg.WParam).X,
      TSmallPoint(Msg.LParam).Y, TSmallPoint(Msg.LParam).X);
    RCount := 1;
  end
  else
    UpdateAll := true;

  ProcessPaintMessages;

  if UpdateAll then
    UpdateBlockDocument
  else
  begin
    Clipped := true;
    try
      ClipRgn.Translate(PageX, PageY);
      PaintPaper;

      for i := 0 to RCount - 1 do
      begin
        R := Rcts[i];

        if FShowRulers then
          IntersectRect(R, R, Classes.Rect(RulerSize, RulerSize, ClientWidth, ClientHeight));

        BitBlt(Canvas.Handle, R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top,
          Scene.Canvas.Handle, R.Left, R.Top, SRCCOPY);
      end;
    finally
      ClipRgn.Free;
      ClipRgn := nil;
      Clipped := false;
    end;
  end;
end;

procedure TBlockViewer.UpdateBlockDocument;
begin
  PaintPaper;
  if FShowRulers then
    BitBlt(Canvas.Handle, RulerSize, RulerSize, ClientWidth - RulerSize,
      ClientWidth - RulerSize, Scene.Canvas.Handle, RulerSize, RulerSize, SRCCOPY)
  else
    BitBlt(Canvas.Handle, 0, 0, ClientWidth, ClientWidth, Scene.Canvas.Handle,
      0, 0, SRCCOPY);
end;

procedure TBlockViewer.UpdateBlockDocumentRect(Left, Top, Right, Bottom: Float);
var
  R: TRect;
begin
  Clipped := true;
  try
    ClipRgn := TGPRegion.Create(MakeRect(PageX + Left - DevicePixel, PageY + Top - DevicePixel, Right - Left + DevicePixel * 2, Bottom - Top + DevicePixel * 2));
    PaintPaper;
  finally
    ClipRgn.Free;
    ClipRgn := nil;
    Clipped := false;
  end;

  R.TopLeft := PaperToScreen(Left, Top);
  R.BottomRight := PaperToScreen(Right, Bottom);
  InflateRect(R, 2, 2);
  if FShowRulers then
    IntersectRect(R, R, Classes.Rect(RulerSize, RulerSize, ClientWidth, ClientHeight));

  BitBlt(Canvas.Handle, R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top,
    Scene.Canvas.Handle, R.Left, R.Top, SRCCOPY);
end;

procedure TBlockViewer.UpdateSceneRect(Left, Top, Right, Bottom: Float);
var
  R: TRect;
begin
  R.TopLeft := PaperToScreen(Left, Top);
  R.BottomRight := PaperToScreen(Right, Bottom);
  InflateRect(R, 2, 2);
  if FShowRulers then
    IntersectRect(R, R, Classes.Rect(RulerSize, RulerSize, ClientWidth, ClientHeight));

  BitBlt(Canvas.Handle, R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top,
    Scene.Canvas.Handle, R.Left, R.Top, SRCCOPY);
end;

procedure TBlockViewer.DoGetGraphics(Sender: TObject; var G: TGPGraphics);
begin
  G := Graphics;
end;

procedure TBlockViewer.DoRepaintEvent(Sender: TObject);
begin
  PostMessage(Handle, WM_REPAINT, 0, 0);
end;

procedure TBlockViewer.DoRepaintRectEvent(Sender: TObject; Left, Top, Right,
  Bottom: Float);
var
  R: TRect;
begin
  R.TopLeft := PaperToScreen(Left, Top);
  R.BottomRight := PaperToScreen(Right, Bottom);
  InflateRect(R, 10, 10);
  PostMessage(Handle, WM_REPAINT, Cardinal(SmallPoint(R.Top, R.Left)), Cardinal(SmallPoint(R.Bottom, R.Right)));
end;

procedure TBlockViewer.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
  inherited;

  FMousePos := Point(X, Y);
  if FShowRulers then
  begin
    PaintRulers;
  end;
end;

procedure TBlockViewer.WMEraseBkgnd(var Msg: TWMEraseBkgnd);
begin
  Msg.Result := 1;
end;

procedure TBlockViewer.UpdateAll;
begin
  if csLoading in ComponentState then Exit;

⌨️ 快捷键说明

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