RVResize.pas
上传用户:daoqigc
上传日期:2021-04-20
资源大小:2795k
文件大小:13k
源码类别:

RichEdit

开发平台:

Delphi

  1. {*******************************************************}
  2. {                                                       }
  3. {       RichView                                        }
  4. {       TRVItemResizer: helps to resize RichView        }
  5. {       item.                                           }
  6. {                                                       }
  7. {       Copyright (c) Sergey Tkachenko                  }
  8. {       svt@trichview.com                               }
  9. {       http://www.trichview.com                        }
  10. {                                                       }
  11. {*******************************************************}
  12. unit RVResize;
  13. interface
  14. uses Windows, Classes, Graphics, Controls, DLines, RVItem;
  15. type
  16.   TRVResizeHandleIndex = (rvrhLeftTop, rvrhRightTop, rvrhRightBottom, rvrhLeftBottom,
  17.     rvrhTop, rvrhRight, rvrhBottom, rvrhLeft);
  18.   TRVResizeHandlesPosition = (rvhpInside, rvhpOutside);
  19.   TRVItemResizer = class
  20.     private
  21.       FWidth, FHeight: Integer;
  22.       FDrawItem: TRVDrawLineInfo;
  23.       FDrawItemNo, FItemNo: Integer;
  24.       FDragging, FDragCancelled: Boolean;
  25.       FDx, FDy: Integer;
  26.       FDragRect: TRect;
  27.       FDraggedResizeHandle: TRVResizeHandleIndex;
  28.       FItem: TCustomRVItemInfo;
  29.       FPosition: TRVResizeHandlesPosition;
  30.       function IsCornerResizeHandle(Index: TRVResizeHandleIndex): Boolean;
  31.       procedure GetResizeHandleShift(Index: TRVResizeHandleIndex; var DX, DY: Integer);
  32.     public
  33.       constructor Create(ADrawItem: TRVDrawLineInfo; AItem: TCustomRVItemInfo; ADrawItemNo: Integer);
  34.       procedure Draw(Canvas: TCanvas; HOffs, VOffs: Integer);
  35.       procedure GetResizeHandleCoords(Index: TRVResizeHandleIndex; Shifted: Boolean; var X, Y: Integer);
  36.       function GetResizeHandleAt(X, Y, HOffs, VOffs: Integer;
  37.         var Index: TRVResizeHandleIndex): Boolean;
  38.       function MouseDown(X, Y, HOffs, VOffs: Integer): Boolean;
  39.       procedure MouseUp(X, Y, HOffs, VOffs: Integer);
  40.       procedure DragTo(Shift: TShiftState; X, Y, HOffs, VOffs: Integer);
  41.       function GetResizeHandleCursor(Index: TRVResizeHandleIndex): TCursor;
  42.       procedure XorDrawing(Canvas: TCanvas; HOffs, VOffs: Integer);
  43.       procedure CancelDrag;
  44.       procedure UpdateItem(ADrawItem: TRVDrawLineInfo; AItem: TCustomRVItemInfo; ADrawItemNo: Integer);
  45.       property Dragging: Boolean read FDragging;
  46.       property DragCancelled: Boolean read FDragCancelled;
  47.       property ItemNo: Integer read FItemNo;
  48.       property DrawItemNo: Integer read FDrawItemNo;
  49.       property DrawItem: TRVDrawLineInfo read FDrawItem;
  50.       property Width: Integer read FWidth;
  51.       property Height: Integer read FHeight;
  52.       property Position: TRVResizeHandlesPosition read FPosition write FPosition;
  53.   end;
  54. const
  55.   RichViewResizeHandleSize = 6; // must be even number
  56. implementation
  57. uses RVERVData;
  58. {============================== TRVItemResizer ================================}
  59. constructor TRVItemResizer.Create(ADrawItem: TRVDrawLineInfo;
  60.   AItem: TCustomRVItemInfo; ADrawItemNo: Integer);
  61. begin
  62.   inherited Create;
  63.   UpdateItem(ADrawItem, AItem, ADrawItemNo);
  64. end;
  65. {------------------------------------------------------------------------------}
  66. procedure TRVItemResizer.UpdateItem(ADrawItem: TRVDrawLineInfo;
  67.   AItem: TCustomRVItemInfo; ADrawItemNo: Integer);
  68. begin
  69.   FDrawItem := ADrawItem;
  70.   FDrawItemNo := ADrawItemNo;
  71.   FWidth := FDrawItem.Width;
  72.   FHeight := FDrawItem.Height;
  73.   FItemNo := FDrawItem.ItemNo;
  74.   FItem := AItem;
  75. end;
  76. {------------------------------------------------------------------------------}
  77. procedure TRVItemResizer.Draw(Canvas: TCanvas; HOffs, VOffs: Integer);
  78.   {.................................................}
  79.   procedure DrawResizeHandle(X,Y: Integer);
  80.   var size: Integer;
  81.   begin
  82.     size := RichViewResizeHandleSize;
  83.     dec(X, size div 2);
  84.     dec(Y, size div 2);
  85.     Canvas.Pen.Mode  := pmCopy;
  86.     Canvas.Rectangle(X,Y,X+size,Y+size);
  87.     inc(X);
  88.     inc(Y);
  89.     dec(size,2);
  90.     Canvas.Pen.Mode  := pmNot;
  91.     while size>1 do begin
  92.       Canvas.Rectangle(X,Y,X+size,Y+size);
  93.       inc(X);
  94.       inc(Y);
  95.       dec(size,2);
  96.     end;
  97.   end;
  98.   {.................................................}
  99. var i: TRVResizeHandleIndex;
  100.    Left, Top, X, Y: Integer;
  101. begin
  102.    Left := FDrawItem.Left-HOffs;
  103.    Top  := FDrawItem.Top -VOffs;
  104.    Canvas.Pen.Width := 1;
  105.    Canvas.Pen.Color := clBlack;
  106.    Canvas.Pen.Style := psSolid;
  107.    Canvas.Brush.Style := bsClear;
  108.    for i := Low(TRVResizeHandleIndex) to High(TRVResizeHandleIndex) do begin
  109.      GetResizeHandleCoords(i, True, X, Y);
  110.      DrawResizeHandle(Left+X,Top+Y);
  111.    end;
  112.    Canvas.Pen.Mode  := pmCopy;
  113. end;
  114. {------------------------------------------------------------------------------}
  115. function TRVItemResizer.GetResizeHandleAt(X, Y, HOffs, VOffs: Integer;
  116.   var Index: TRVResizeHandleIndex): Boolean;
  117. var i: TRVResizeHandleIndex;
  118.     HX, HY, Delta: Integer;
  119. begin
  120.   dec(X, FDrawItem.Left-HOffs);
  121.   dec(Y, FDrawItem.Top-VOffs);
  122.   Delta := (RichViewResizeHandleSize+1) div 2;
  123.   for i := Low(TRVResizeHandleIndex) to High(TRVResizeHandleIndex) do begin
  124.     GetResizeHandleCoords(i, True, HX, HY);
  125.     Result := (abs(HX-X)<=Delta) and (abs(HY-Y)<=Delta);
  126.     if Result then begin
  127.       Index := i;
  128.       exit;
  129.     end;
  130.   end;
  131.   Result := False;
  132. end;
  133. {------------------------------------------------------------------------------}
  134. procedure TRVItemResizer.GetResizeHandleCoords(Index: TRVResizeHandleIndex;
  135.   Shifted: Boolean; var X, Y: Integer);
  136. var DX, DY: Integer;
  137. begin
  138.   case Index of
  139.     rvrhLeftTop:
  140.       begin
  141.         X := 0;
  142.         Y := 0;
  143.       end;
  144.     rvrhRightTop:
  145.       begin
  146.         X := FWidth;
  147.         Y := 0;
  148.       end;
  149.     rvrhRightBottom:
  150.       begin
  151.         X := FWidth;
  152.         Y := FHeight;
  153.       end;
  154.     rvrhLeftBottom:
  155.       begin
  156.         X := 0;
  157.         Y := FHeight;
  158.       end;
  159.     rvrhTop:
  160.       begin
  161.         X := FWidth div 2;
  162.         Y := 0;
  163.       end;
  164.     rvrhRight:
  165.       begin
  166.         X := FWidth;
  167.         Y := FHeight div 2;
  168.       end;
  169.     rvrhBottom:
  170.       begin
  171.         X := FWidth div 2;
  172.         Y := FHeight;
  173.       end;
  174.     rvrhLeft:
  175.       begin
  176.         X := 0;
  177.         Y := FHeight div 2;
  178.       end;
  179.   end;
  180.   if Shifted then begin
  181.     GetResizeHandleShift(Index, DX, DY);
  182.     inc(X, DX);
  183.     inc(Y, DY);
  184.   end;
  185. end;
  186. {------------------------------------------------------------------------------}
  187. procedure TRVItemResizer.GetResizeHandleShift(Index: TRVResizeHandleIndex;
  188.   var DX, DY: Integer);
  189. var delta: Integer;
  190.     APosition: TRVResizeHandlesPosition;
  191. begin
  192.   APosition := Position;
  193.   if (FWidth<RichViewResizeHandleSize*2) or
  194.      (FHeight<RichViewResizeHandleSize*2) then
  195.     APosition := rvhpOutside;
  196.   case APosition of
  197.     rvhpInside:
  198.       delta := RichViewResizeHandleSize div 2;
  199.     rvhpOutside:
  200.       delta := -RichViewResizeHandleSize div 2;
  201.     else
  202.       delta := 0;
  203.   end;
  204.   case Index of
  205.     rvrhLeft, rvrhLeftTop, rvrhLeftBottom:
  206.       DX := delta;
  207.     rvrhRight, rvrhRightTop, rvrhRightBottom:
  208.       DX := -delta;
  209.     else
  210.       DX := 0;
  211.   end;
  212.   case Index of
  213.     rvrhLeftTop, rvrhRightTop, rvrhTop:
  214.       DY := delta;
  215.     rvrhLeftBottom, rvrhRightBottom, rvrhBottom:
  216.       DY := -delta;
  217.     else
  218.       DY := 0;
  219.   end;
  220. end;
  221. {------------------------------------------------------------------------------}
  222. function TRVItemResizer.GetResizeHandleCursor(
  223.   Index: TRVResizeHandleIndex): TCursor;
  224. begin
  225.   case Index of
  226.     rvrhLeftTop, rvrhRightBottom:
  227.       Result := crSizeNWSE;
  228.     rvrhRightTop, rvrhLeftBottom:
  229.       Result := crSizeNESW;
  230.     rvrhTop, rvrhBottom:
  231.       Result := crSizeNS;
  232.     else
  233.       Result := crSizeWE;
  234.   end;
  235. end;
  236. {------------------------------------------------------------------------------}
  237. function TRVItemResizer.MouseDown(X, Y, HOffs, VOffs: Integer): Boolean;
  238. var Index: TRVResizeHandleIndex;
  239.     HX, HY: Integer;
  240. begin
  241.   Result := GetResizeHandleAt(X, Y, HOffs, VOffs, Index);
  242.   if not Result then
  243.     exit;
  244.   FDragging := True;
  245.   FDraggedResizeHandle := Index;
  246.   GetResizeHandleCoords(Index, False, HX, HY);
  247.   dec(X, FDrawItem.Left-HOffs);
  248.   dec(Y, FDrawItem.Top-VOffs);
  249.   FDx := X-HX;
  250.   FDy := Y-HY;
  251.   FDragRect := Rect(0,0,FDrawItem.Width, FDrawItem.Height);
  252.   FDragCancelled := False;
  253. end;
  254. {------------------------------------------------------------------------------}
  255. procedure TRVItemResizer.DragTo(Shift: TShiftState; X, Y, HOffs, VOffs: Integer);
  256.   {........................................}
  257.   procedure AdjustRect(L,T,R,B: Boolean);
  258.   var XRatio, YRatio: Double;
  259.       Delta: Integer;
  260.       OriginalWidth, OriginalHeight: Integer;
  261.   begin
  262.     with FDragRect do begin
  263.       if (Left>=Right-1) then begin
  264.         if L then
  265.           Left := Right-2;
  266.         if R then
  267.           Right := Left+2;
  268.       end;
  269.       if (Top>=Bottom-1) then begin
  270.         if T then
  271.           Top := Bottom-2;
  272.         if B then
  273.           Bottom := Top+2;
  274.       end;
  275.       if ssCtrl in Shift then begin
  276.         if L then
  277.           Right := FDrawItem.Width-Left;
  278.         if T then
  279.           Bottom := FDrawItem.Height-Top;
  280.         if R then
  281.           Left := FDrawItem.Width-Right;
  282.         if B then
  283.           Top := FDrawItem.Height-Bottom;
  284.       end;
  285.       if (ssShift in Shift) or
  286.          (RichViewEditDefaultProportionalResize and IsCornerResizeHandle(FDraggedResizeHandle)) then begin
  287.         OriginalWidth  := FDrawItem.Width;
  288.         OriginalHeight := FDrawItem.Height;
  289.         if FItem is TRVRectItemInfo then begin
  290.           dec(OriginalWidth, TRVRectItemInfo(FItem).Spacing*2);
  291.           dec(OriginalHeight, TRVRectItemInfo(FItem).Spacing*2);          
  292.         end;
  293.         if (OriginalWidth>0) and (OriginalHeight>0) then begin
  294.           XRatio := (Right-Left)/OriginalWidth;
  295.           YRatio := (Bottom-Top)/OriginalHeight;
  296.           if XRatio>YRatio then begin
  297.             Delta := Round(XRatio*OriginalHeight)-(Bottom-Top);
  298.             if ssCtrl in Shift then begin
  299.               dec(Top, Delta div 2);
  300.               inc(Bottom, Delta div 2);
  301.               end
  302.             else if T then
  303.               dec(Top, Delta)
  304.             else
  305.               inc(Bottom, Delta);
  306.             end
  307.           else begin
  308.             Delta := Round(YRatio*OriginalWidth)-(Right-Left);
  309.             if ssCtrl in Shift then begin
  310.               dec(Left, Delta div 2);
  311.               inc(Right, Delta div 2);
  312.               end
  313.             else if L then
  314.               dec(Left, Delta)
  315.             else
  316.               inc(Right, Delta);
  317.           end;
  318.         end;
  319.       end;
  320.     end;
  321.   end;
  322.   {........................................}
  323. begin
  324.   dec(X, FDx);
  325.   dec(Y, FDy);
  326.   dec(X, FDrawItem.Left-HOffs);
  327.   dec(Y, FDrawItem.Top-VOffs);
  328.   FDragRect := Rect(0,0,FDrawItem.Width, FDrawItem.Height);
  329.   case FDraggedResizeHandle of
  330.     rvrhLeftTop:
  331.       begin
  332.         FDragRect.Left := X;
  333.         FDragRect.Top  := Y;
  334.         AdjustRect(True, True, False, False);
  335.       end;
  336.     rvrhRightTop:
  337.       begin
  338.         FDragRect.Right := X;
  339.         FDragRect.Top  := Y;
  340.         AdjustRect(False, True, True, False);
  341.       end;
  342.     rvrhRightBottom:
  343.       begin
  344.         FDragRect.Right := X;
  345.         FDragRect.Bottom  := Y;
  346.         AdjustRect(False, False, True, True);
  347.       end;
  348.     rvrhLeftBottom:
  349.       begin
  350.         FDragRect.Left := X;
  351.         FDragRect.Bottom  := Y;
  352.         AdjustRect(True, False, False, True);        
  353.       end;
  354.     rvrhTop:
  355.       begin
  356.         FDragRect.Top  := Y;
  357.         AdjustRect(False, True, False, False);
  358.       end;
  359.     rvrhRight:
  360.       begin
  361.         FDragRect.Right := X;
  362.         AdjustRect(False, False, True, False);
  363.       end;
  364.     rvrhBottom:
  365.       begin
  366.         FDragRect.Bottom  := Y;
  367.         AdjustRect(False, False, False, True);
  368.       end;
  369.     rvrhLeft:
  370.       begin
  371.         FDragRect.Left := X;
  372.         AdjustRect(True, False, False, False);
  373.       end;
  374.   end;
  375. end;
  376. {------------------------------------------------------------------------------}
  377. procedure TRVItemResizer.XorDrawing(Canvas: TCanvas; HOffs, VOffs: Integer);
  378. begin
  379.   with Canvas do begin
  380.     Pen.Mode := pmNot;
  381.     Pen.Width := 1;
  382.     Brush.Style := bsClear;
  383.     Pen.Style := psDot;
  384.     with FDragRect do
  385.       Rectangle(FDrawItem.Left+Left-HOffs,
  386.         FDrawItem.Top+Top-VOffs,
  387.         FDrawItem.Left+Right-HOffs,
  388.         FDrawItem.Top+Bottom-VOffs);
  389.     Pen.Mode := pmCopy;
  390.   end;
  391. end;
  392. {------------------------------------------------------------------------------}
  393. procedure TRVItemResizer.MouseUp(X, Y, HOffs, VOffs: Integer);
  394. begin
  395.   if not FDragCancelled then begin
  396.     FWidth := FDragRect.Right-FDragRect.Left;
  397.     FHeight := FDragRect.Bottom-FDragRect.Top;
  398.   end;
  399.   FDragging := False;
  400.   FDragCancelled := False;
  401. end;
  402. {------------------------------------------------------------------------------}
  403. procedure TRVItemResizer.CancelDrag;
  404. begin
  405.   FDragging := False;
  406.   FDragCancelled := True;
  407. end;
  408. {------------------------------------------------------------------------------}
  409. function TRVItemResizer.IsCornerResizeHandle(Index: TRVResizeHandleIndex): Boolean;
  410. begin
  411.   Result := Index in [rvrhLeftTop, rvrhRightTop, rvrhRightBottom, rvrhLeftBottom];
  412. end;
  413. end.