MMSplit.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:16k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Tel.: +0351-8012255                   =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 20.01.1998 - 18:00:00 $                                      =}
  24. {========================================================================}
  25. unit MMSplit;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29. {$IFDEF WIN32}
  30.     Windows,
  31. {$ELSE}
  32.     WinProcs,
  33.     WinTypes,
  34. {$ENDIF}
  35.     Messages,
  36.     SysUtils,
  37.     Classes,
  38.     Controls,
  39.     Forms,
  40.     Graphics,
  41.     ExtCtrls,
  42.     Menus,
  43.     MMObj,
  44.     MMString,
  45.     MMUtils;
  46. type
  47.   {-- TMMSplitter -------------------------------------------------------}
  48.   TMMSplitter = class(TMMCustomPanel)
  49.   private
  50.     FCursor      : TCursor;
  51.     FOrigin      : TPoint;
  52.     FOffset      : TPoint;
  53.     FUpdate      : integer;
  54.     FSolid       : Boolean;
  55.     FFixed       : Boolean;
  56.     FGrid        : integer;
  57.     FAutoControl : Boolean;
  58.     FMinOffset   : integer;
  59.     FMaxOffset   : integer;
  60.     FSPlitterSize: integer;
  61.     FSizeControl : TWinControl;
  62.     FOnSplit     : TMouseMoveEvent;
  63.     FOnSplitBegin: TNotifyEvent;
  64.     FOnSplitEnd  : TNotifyEvent;
  65.     procedure SetSplitterSize(aValue: integer);
  66.     procedure SetGrid(aValue: integer);
  67.     procedure SetSizeControl(aValue: TWinControl);
  68.     procedure SetFixed(aValue: Boolean);
  69.     procedure UpdateCursor;
  70.     procedure BeginSizing(aRect: TRect);
  71.     procedure DrawSizeRect(var aRect: TRect);
  72.     procedure EndSizing(aRect: TRect);
  73.     procedure WMSize(var Msg); message WM_Size;
  74.     procedure WMMove(var Msg); message WM_Move;
  75.   protected
  76.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  77.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  78.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  79.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  80.   public
  81.     constructor Create(AOwner: TComponent); override;
  82.   published
  83.     property OnClick;
  84.     property OnDblClick;
  85.     property OnDragDrop;
  86.     property OnDragOver;
  87.     property OnEndDrag;
  88.     property OnEnter;
  89.     property OnExit;
  90.     property OnMouseDown;
  91.     property OnMouseMove;
  92.     property OnMouseUp;
  93.     property OnResize;
  94.     {$IFDEF WIN32}
  95.     property OnStartDrag;
  96.     {$ENDIF}
  97.     property Bevel;
  98.     property DragCursor;
  99.     property DragMode;
  100.     property Enabled;
  101.     property Color;
  102.     property Ctl3D;
  103.     property ParentColor;
  104.     property ParentCtl3D;
  105.     property ParentShowHint;
  106.     property PopupMenu;
  107.     property ShowHint;
  108.     property TabOrder;
  109.     property TabStop;
  110.     property Visible;
  111.     property OnSplit: TMouseMoveEvent read FOnSplit write FOnSplit;
  112.     property OnSplitBegin:  TNotifyEvent read FOnSplitBegin write FOnSplitBegin;
  113.     property OnSplitEnd: TNotifyEvent read FOnSplitEnd write FOnSplitEnd;
  114.     property Height default 3;
  115.     property Fixed: Boolean read FFixed write SetFixed default False;
  116.     property AutoControl: Boolean read FAutoControl write FAutoControl default False;
  117.     property MinOffset: integer read FMinOffset write FMinOffset default 0;
  118.     property MaxOffset: integer read FMaxOffset write FMaxOffset default 0;
  119.     property SplitterSize: integer read FSplitterSize write SetSplitterSize default 4;
  120.     property SizeControl: TWinControl read FSizeControl write SetSizeControl;
  121.     property DrawSolid: Boolean read FSolid write FSolid default False;
  122.     property Grid: integer read FGrid write SetGrid default 0;
  123.   end;
  124. implementation
  125. const
  126.      SplitCanvas : TCanvas = nil;
  127. {------------------------------------------------------------------------}
  128. function GetClipDC(Control: TWinControl): hDC;
  129. var
  130.    ClipRect: TRect;
  131.    ClipRgn : hRgn;
  132. begin
  133.    ClipRect := Control.ClientRect;
  134.    MapWindowPoints(Control.Handle, 0 , ClipRect, 2);
  135.    inc(ClipRect.Right);
  136.    inc(ClipRect.Bottom);
  137.    Result := GetDC(0);
  138.    SetViewPortOrgEx(Result, ClipRect.Left, ClipRect.Top, nil);
  139.    ClipRgn := CreateRectRgnIndirect(ClipRect);
  140.    SelectClipRgn(Result, ClipRgn);
  141.    DeleteObject(ClipRgn);
  142. end;
  143. {------------------------------------------------------------------------}
  144. function CreateBrushPattern: TBitmap;
  145. var
  146.    X,Y: integer;
  147. begin
  148.    Result := TBitmap.Create;
  149.    Result.MonoChrome := True;
  150.    Result.Width := 8;
  151.    Result.Height:= 8;
  152.    with Result.Canvas do
  153.    begin
  154.       Brush.Style := bsSolid;
  155.       Brush.Color := clWhite;
  156.       FillRect(Rect(0, 0, 8, 8));
  157.       for Y := 0 to 7 do
  158.           for X := 0 to 7 do
  159.           if (Y mod 2) = (X mod 2) then { toggles between even/odd pixles }
  160.              Pixels[X, Y] := clBlack;   { on even/odd rows }
  161.    end;
  162. end;
  163. {== TMMSplitter =========================================================}
  164. constructor TMMSplitter.Create(AOwner: TComponent);
  165. begin
  166.    inherited Create(AOwner);
  167.    ControlStyle := ControlStyle - [csSetCaption];
  168.    FUpdate := 0;
  169.    FFixed := False;
  170.    FSolid := False;
  171.    FSplitterSize := 3;
  172.    FAutoControl := False;
  173.    FMinOffset := 0;
  174.    FMaxOffset := 0;
  175.    FCursor := Cursor;
  176.    FGrid := 0;
  177.    Caption := '';
  178.    Height := 3;
  179.    Bevel.BevelOuter := bvRaised;
  180.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  181.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  182. end;
  183. {-- TMMSplitter ---------------------------------------------------------}
  184. procedure TMMSplitter.BeginSizing(aRect: TRect);
  185. begin
  186.    if (SplitCanvas = nil) then SplitCanvas := TCanvas.Create;
  187.    with SplitCanvas do
  188.    begin
  189.       Handle       := GetClipDC(Parent);
  190.       if FSolid then
  191.          Brush.Color := clWhite
  192.       else
  193.          Brush.Bitmap:= CreateBrushPattern;
  194.       Pen.Style := psClear;
  195.       Pen.Mode  := pmXor;
  196.    end;
  197.    DrawSizeRect(aRect);
  198. end;
  199. {-- TMMSplitter ---------------------------------------------------------}
  200. procedure TMMSplitter.EndSizing(aRect: TRect);
  201. begin
  202.    { delete SizeRect }
  203.    DrawSizeRect(aRect);
  204.    { reset cursorClipping }
  205.    ClipCursor(nil);
  206.    if (SplitCanvas.Brush.Bitmap <> nil) then
  207.    begin
  208.       SplitCanvas.Brush.Bitmap.Free;
  209.       SplitCanvas.Brush.Bitmap := Nil;
  210.    end;
  211.    ReleaseDC(0, SplitCanvas.Handle);
  212.    SplitCanvas.Handle := 0;
  213.    SplitCanvas.Free;
  214.    SplitCanvas := nil;
  215. end;
  216. {-- TMMSplitter ---------------------------------------------------------}
  217. procedure TMMSplitter.DrawSizeRect(var aRect: TRect);
  218. begin
  219.    if (SplitCanvas <> nil) then
  220.    with SplitCanvas, aRect do
  221.    case Align of
  222.       alTop,
  223.       alBottom: Rectangle(Left, Top, Right, Bottom+1);
  224.       alLeft,
  225.       alRight: Rectangle(Left,Top,Right+1,Bottom);
  226.    end;
  227. end;
  228. {-- TMMSplitter ---------------------------------------------------------}
  229. procedure TMMSplitter.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  230. var
  231.    aRect: TRect;
  232.    ScreenBounds: TRect;
  233.    i: integer;
  234.    Win: TWinControl;
  235. begin
  236.    inherited MouseDown(Button,Shift,X,Y);
  237.    if not FFixed and (FSizeControl <> nil) and (Button = mbLeft) then
  238.    begin
  239.       aRect := Parent.ClientRect;
  240.       case Align of
  241.            alTop,
  242.            alBottom: InflateRect(aRect,0,-FSplitterSize);
  243.            alLeft,
  244.            alRight : InflateRect(aRect,-FSplitterSize,0);
  245.       end;
  246.       MapWindowPoints(Parent.Handle,0,aRect,2);
  247.       if FAutoControl then
  248.       for i := 0 to Parent.ControlCount-1 do
  249.       begin
  250.          Win := TWinControl(Parent.Controls[i]);
  251.          if (Win is TWinControl) and (Win.Align = Align) then
  252.          case Align of
  253.            alTop   : if Win.Top>Top then dec(aRect.Bottom,Win.Height);
  254.            alBottom: if Win.Top+Win.Height<Top+Height then inc(aRect.Top,Win.Height);
  255.            alLeft  : if Win.Left>Left then dec(aRect.Right,Win.Width);
  256.            alRight : if Win.Left+Win.Width<Left+Width then inc(aRect.Left,Win.Width);
  257.          end;
  258.       end;
  259.       ScreenBounds := SizeControl.BoundsRect;
  260.       MapWindowPoints(Parent.Handle,0,ScreenBounds,2);
  261.       with ScreenBounds do
  262.       case Align of
  263.            alTop   : begin
  264.                         aRect.Top := Top+FMinOffset;
  265.                         aRect.Bottom := aRect.Bottom-FMaxOffset;
  266.                      end;
  267.            alBottom: begin
  268.                         aRect.Bottom := Bottom-FMaxOffset;
  269.                         aRect.Top := aRect.Top+FMinOffset;
  270.                      end;
  271.            alLeft  : begin
  272.                         aRect.Left := Left+FMinOffset;
  273.                         aRect.Right := aRect.Right-FMaxOffset;
  274.                      end;
  275.            alRight : begin
  276.                         aRect.Right := Right-FMaxOffset;
  277.                         aRect.Left := aRect.Left+FMinOffset;
  278.                      end;
  279.       end;
  280.       FOrigin := Point(X,Y);
  281.       FOffset := Point(X,Y);
  282.       ClipCursor(@aRect);
  283.       BeginSizing(BoundsRect);
  284.       if assigned(FOnSplitBegin) then FOnSplitBegin(Self);
  285.    end;
  286. end;
  287. {-- TMMSplitter ---------------------------------------------------------}
  288. procedure TMMSplitter.MouseMove(Shift: TShiftState; X, Y: Integer);
  289. var
  290.    aRect : TRect;
  291.    G: integer;
  292. begin
  293.    inherited MouseMove(Shift,X,Y);
  294.    if not FFixed and (FSizeControl <> nil) and (ssLeft in Shift) then
  295.    begin
  296.       G := Max(FGrid,1);
  297.       aRect := BoundsRect;
  298.       case Align of
  299.         alTop,
  300.         alBottom:
  301.         begin
  302.            OffsetRect(aRect,0,FOffset.Y-FOrigin.Y);
  303.            DrawSizeRect(aRect);
  304.            OffsetRect(aRect,0,(Y-FOffset.Y)div G*G);
  305.            FOffset := Point(X,((Y-FOffset.Y)div G*G)+FOffset.Y);
  306.            DrawSizeRect(aRect);
  307.         end;
  308.         alLeft,
  309.         alRight:
  310.         begin
  311.            OffsetRect(aRect,FOffset.X-FOrigin.X,0);
  312.            DrawSizeRect(aRect);
  313.            OffsetRect(aRect,(X-FOffset.X)div G*G,0);
  314.            FOffset := Point(((X-FOffset.X)div G*G)+FOffset.X,Y);
  315.            DrawSizeRect(aRect);
  316.         end;
  317.       end;
  318.       if Assigned(FOnSplit) then FOnSplit(Self,Shift,X,Y);
  319.    end;
  320. end;
  321. {-- TMMSplitter ---------------------------------------------------------}
  322. procedure TMMSplitter.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  323. var
  324.    aRect: TRect;
  325.    G: integer;
  326. begin
  327.    inherited MouseUp(Button,Shift,X,Y);
  328.    if not FFixed and (FSizeControl <> nil) and (Button = mbLeft) then
  329.    begin
  330.       G := Max(FGrid,1);
  331.       aRect := BoundsRect;
  332.       case Align of
  333.         alTop,
  334.         alBottom: OffsetRect(aRect,0,FOffset.Y-FOrigin.Y);
  335.         alLeft,
  336.         alRight: OffsetRect(aRect,FOffset.X-FOrigin.X,0);
  337.       end;
  338.       EndSizing(aRect);
  339.       aRect := FSizeControl.BoundsRect;
  340.       case Align of
  341.         alTop   : inc(aRect.Bottom,(Y-FOrigin.Y)div G*G);
  342.         alBottom: inc(aRect.Top,(Y-FOrigin.Y)div G*G);
  343.         alLeft  : inc(aRect.Right,(X-FOrigin.X)div G*G);
  344.         alRight : inc(aRect.Left,(X-FOrigin.X)div G*G);
  345.       end;
  346.       inc(FUpdate);
  347.       FSizeControl.BoundsRect := aRect;
  348.       dec(FUpdate);
  349.       if assigned(FOnSplitEnd) then FOnSplitEnd(Self);
  350.    end;
  351. end;
  352. {-- TMMSplitter ---------------------------------------------------------}
  353. procedure TMMSplitter.SetGrid(aValue: integer);
  354. begin
  355.    if (aValue <> FGrid) then
  356.    begin
  357.       FGrid := Max(aValue,0);
  358.    end;
  359. end;
  360. {-- TMMSplitter ---------------------------------------------------------}
  361. procedure TMMSplitter.SetSplitterSize(aValue: integer);
  362. begin
  363.    if (aValue <> FSplitterSize) and (aValue > 0) then
  364.    begin
  365.       FSplitterSize := aValue;
  366.       inc(FUpdate);
  367.       SetSizeControl(FSizeControl);
  368.       dec(FUpdate);
  369.    end;
  370.    {$IFDEF WIN32}
  371.    {$IFDEF TRIAL}
  372.    {$DEFINE _HACK1}
  373.    {$I MMHACK.INC}
  374.    {$ENDIF}
  375.    {$ENDIF}
  376. end;
  377. {-- TMMSplitter ---------------------------------------------------------}
  378. procedure TMMSplitter.UpdateCursor;
  379. begin
  380.    if not FFixed then
  381.       Cursor := FCursor
  382.    else
  383.       Cursor := crDefault;
  384. end;
  385. {-- TMMSplitter ---------------------------------------------------------}
  386. procedure TMMSplitter.SetFixed(aValue: Boolean);
  387. begin
  388.    if (aValue <> FFixed) then
  389.    begin
  390.       FFixed := aValue;
  391.       UpdateCursor;
  392.    end;
  393. end;
  394. {-- TMMSplitter ---------------------------------------------------------}
  395. procedure TMMSplitter.SetSizeControl(aValue: TWinControl);
  396. begin
  397.    if (aValue = nil) then
  398.    begin
  399.       FSizeControl := nil;
  400.       Align := alNone;
  401.       FCursor := crDefault;
  402.       UpdateCursor;
  403.       exit;
  404.    end;
  405.    {$IFDEF WIN32}
  406.    {$IFDEF TRIAL}
  407.    {$DEFINE _HACK2}
  408.    {$I MMHACK.INC}
  409.    {$ENDIF}
  410.    {$ENDIF}
  411.    if (aValue.Align = alNone) or (aValue.Align = alClient) then
  412.    begin
  413.       SetSizeControl(nil);
  414.       raise Exception.Create('Splitter: Control''s align must be left, right, top or bottom');
  415.    end;
  416.    inc(FUpdate);
  417.    Align := aValue.Align;
  418.    case aValue.Align of
  419.          alTop: begin
  420.                    FCursor := crsVSplit;
  421.                    Top := aValue.Top+aValue.Height;
  422.                    Height := FSplitterSize;
  423.                 end;
  424.       alBottom: begin
  425.                    FCursor := crsVSplit;
  426.                    Top := aValue.Top-FSplitterSize;
  427.                    Height := FSplitterSize;
  428.                 end;
  429.         alLeft: begin
  430.                    FCursor := crsHSplit;
  431.                    Left := aValue.Left+aValue.Width;
  432.                    Width := FSplitterSize;
  433.                 end;
  434.        alRight: begin
  435.                    FCursor := crsHSplit;
  436.                    Left := aValue.Left-FSplitterSize;
  437.                    Width := FSplitterSize;
  438.                 end;
  439.    end;
  440.    dec(FUpdate);
  441.    FSizeControl := aValue;
  442.    UpdateCursor;
  443. end;
  444. {-- TMMSplitter ---------------------------------------------------------}
  445. procedure TMMSplitter.Notification(AComponent: TComponent; Operation: TOperation);
  446. begin
  447.    if (Operation = opRemove) and (AComponent = FSizeControl) then
  448.        SetSizeControl(nil);
  449.    inherited Notification(AComponent,Operation);
  450. end;
  451. {-- TMMSplitter ---------------------------------------------------------}
  452. procedure TMMSplitter.WMSize(var Msg);
  453. begin
  454.    inherited;
  455.    if FUpdate = 0 then SetSizeControl(FSizeControl);
  456. end;
  457. {-- TMMSplitter ---------------------------------------------------------}
  458. procedure TMMSplitter.WMMove(var Msg);
  459. begin
  460.    inherited;
  461.    if FUpdate = 0 then SetSizeControl(FSizeControl);
  462. end;
  463. end.