MMSplit.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:16k
- {========================================================================}
- {= (c) 1995-98 SwiftSoft Ronald Dittrich =}
- {========================================================================}
- {= All Rights Reserved =}
- {========================================================================}
- {= D 01099 Dresden = Tel.: +0351-8012255 =}
- {= Loewenstr.7a = info@swiftsoft.de =}
- {========================================================================}
- {= Actual versions on http://www.swiftsoft.de/mmtools.html =}
- {========================================================================}
- {= This code is for reference purposes only and may not be copied or =}
- {= distributed in any format electronic or otherwise except one copy =}
- {= for backup purposes. =}
- {= =}
- {= No Delphi Component Kit or Component individually or in a collection=}
- {= subclassed or otherwise from the code in this unit, or associated =}
- {= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
- {= without express permission from SwiftSoft. =}
- {= =}
- {= For more licence informations please refer to the associated =}
- {= HelpFile. =}
- {========================================================================}
- {= $Date: 20.01.1998 - 18:00:00 $ =}
- {========================================================================}
- unit MMSplit;
- {$I COMPILER.INC}
- interface
- uses
- {$IFDEF WIN32}
- Windows,
- {$ELSE}
- WinProcs,
- WinTypes,
- {$ENDIF}
- Messages,
- SysUtils,
- Classes,
- Controls,
- Forms,
- Graphics,
- ExtCtrls,
- Menus,
- MMObj,
- MMString,
- MMUtils;
- type
- {-- TMMSplitter -------------------------------------------------------}
- TMMSplitter = class(TMMCustomPanel)
- private
- FCursor : TCursor;
- FOrigin : TPoint;
- FOffset : TPoint;
- FUpdate : integer;
- FSolid : Boolean;
- FFixed : Boolean;
- FGrid : integer;
- FAutoControl : Boolean;
- FMinOffset : integer;
- FMaxOffset : integer;
- FSPlitterSize: integer;
- FSizeControl : TWinControl;
- FOnSplit : TMouseMoveEvent;
- FOnSplitBegin: TNotifyEvent;
- FOnSplitEnd : TNotifyEvent;
- procedure SetSplitterSize(aValue: integer);
- procedure SetGrid(aValue: integer);
- procedure SetSizeControl(aValue: TWinControl);
- procedure SetFixed(aValue: Boolean);
- procedure UpdateCursor;
- procedure BeginSizing(aRect: TRect);
- procedure DrawSizeRect(var aRect: TRect);
- procedure EndSizing(aRect: TRect);
- procedure WMSize(var Msg); message WM_Size;
- procedure WMMove(var Msg); message WM_Move;
- protected
- procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
- procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
- procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- public
- constructor Create(AOwner: TComponent); override;
- published
- property OnClick;
- property OnDblClick;
- property OnDragDrop;
- property OnDragOver;
- property OnEndDrag;
- property OnEnter;
- property OnExit;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property OnResize;
- {$IFDEF WIN32}
- property OnStartDrag;
- {$ENDIF}
- property Bevel;
- property DragCursor;
- property DragMode;
- property Enabled;
- property Color;
- property Ctl3D;
- property ParentColor;
- property ParentCtl3D;
- property ParentShowHint;
- property PopupMenu;
- property ShowHint;
- property TabOrder;
- property TabStop;
- property Visible;
- property OnSplit: TMouseMoveEvent read FOnSplit write FOnSplit;
- property OnSplitBegin: TNotifyEvent read FOnSplitBegin write FOnSplitBegin;
- property OnSplitEnd: TNotifyEvent read FOnSplitEnd write FOnSplitEnd;
- property Height default 3;
- property Fixed: Boolean read FFixed write SetFixed default False;
- property AutoControl: Boolean read FAutoControl write FAutoControl default False;
- property MinOffset: integer read FMinOffset write FMinOffset default 0;
- property MaxOffset: integer read FMaxOffset write FMaxOffset default 0;
- property SplitterSize: integer read FSplitterSize write SetSplitterSize default 4;
- property SizeControl: TWinControl read FSizeControl write SetSizeControl;
- property DrawSolid: Boolean read FSolid write FSolid default False;
- property Grid: integer read FGrid write SetGrid default 0;
- end;
- implementation
- const
- SplitCanvas : TCanvas = nil;
- {------------------------------------------------------------------------}
- function GetClipDC(Control: TWinControl): hDC;
- var
- ClipRect: TRect;
- ClipRgn : hRgn;
- begin
- ClipRect := Control.ClientRect;
- MapWindowPoints(Control.Handle, 0 , ClipRect, 2);
- inc(ClipRect.Right);
- inc(ClipRect.Bottom);
- Result := GetDC(0);
- SetViewPortOrgEx(Result, ClipRect.Left, ClipRect.Top, nil);
- ClipRgn := CreateRectRgnIndirect(ClipRect);
- SelectClipRgn(Result, ClipRgn);
- DeleteObject(ClipRgn);
- end;
- {------------------------------------------------------------------------}
- function CreateBrushPattern: TBitmap;
- var
- X,Y: integer;
- begin
- Result := TBitmap.Create;
- Result.MonoChrome := True;
- Result.Width := 8;
- Result.Height:= 8;
- with Result.Canvas do
- begin
- Brush.Style := bsSolid;
- Brush.Color := clWhite;
- FillRect(Rect(0, 0, 8, 8));
- for Y := 0 to 7 do
- for X := 0 to 7 do
- if (Y mod 2) = (X mod 2) then { toggles between even/odd pixles }
- Pixels[X, Y] := clBlack; { on even/odd rows }
- end;
- end;
- {== TMMSplitter =========================================================}
- constructor TMMSplitter.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- ControlStyle := ControlStyle - [csSetCaption];
- FUpdate := 0;
- FFixed := False;
- FSolid := False;
- FSplitterSize := 3;
- FAutoControl := False;
- FMinOffset := 0;
- FMaxOffset := 0;
- FCursor := Cursor;
- FGrid := 0;
- Caption := '';
- Height := 3;
- Bevel.BevelOuter := bvRaised;
- ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
- if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.BeginSizing(aRect: TRect);
- begin
- if (SplitCanvas = nil) then SplitCanvas := TCanvas.Create;
- with SplitCanvas do
- begin
- Handle := GetClipDC(Parent);
- if FSolid then
- Brush.Color := clWhite
- else
- Brush.Bitmap:= CreateBrushPattern;
- Pen.Style := psClear;
- Pen.Mode := pmXor;
- end;
- DrawSizeRect(aRect);
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.EndSizing(aRect: TRect);
- begin
- { delete SizeRect }
- DrawSizeRect(aRect);
- { reset cursorClipping }
- ClipCursor(nil);
- if (SplitCanvas.Brush.Bitmap <> nil) then
- begin
- SplitCanvas.Brush.Bitmap.Free;
- SplitCanvas.Brush.Bitmap := Nil;
- end;
- ReleaseDC(0, SplitCanvas.Handle);
- SplitCanvas.Handle := 0;
- SplitCanvas.Free;
- SplitCanvas := nil;
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.DrawSizeRect(var aRect: TRect);
- begin
- if (SplitCanvas <> nil) then
- with SplitCanvas, aRect do
- case Align of
- alTop,
- alBottom: Rectangle(Left, Top, Right, Bottom+1);
- alLeft,
- alRight: Rectangle(Left,Top,Right+1,Bottom);
- end;
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- var
- aRect: TRect;
- ScreenBounds: TRect;
- i: integer;
- Win: TWinControl;
- begin
- inherited MouseDown(Button,Shift,X,Y);
- if not FFixed and (FSizeControl <> nil) and (Button = mbLeft) then
- begin
- aRect := Parent.ClientRect;
- case Align of
- alTop,
- alBottom: InflateRect(aRect,0,-FSplitterSize);
- alLeft,
- alRight : InflateRect(aRect,-FSplitterSize,0);
- end;
- MapWindowPoints(Parent.Handle,0,aRect,2);
- if FAutoControl then
- for i := 0 to Parent.ControlCount-1 do
- begin
- Win := TWinControl(Parent.Controls[i]);
- if (Win is TWinControl) and (Win.Align = Align) then
- case Align of
- alTop : if Win.Top>Top then dec(aRect.Bottom,Win.Height);
- alBottom: if Win.Top+Win.Height<Top+Height then inc(aRect.Top,Win.Height);
- alLeft : if Win.Left>Left then dec(aRect.Right,Win.Width);
- alRight : if Win.Left+Win.Width<Left+Width then inc(aRect.Left,Win.Width);
- end;
- end;
- ScreenBounds := SizeControl.BoundsRect;
- MapWindowPoints(Parent.Handle,0,ScreenBounds,2);
- with ScreenBounds do
- case Align of
- alTop : begin
- aRect.Top := Top+FMinOffset;
- aRect.Bottom := aRect.Bottom-FMaxOffset;
- end;
- alBottom: begin
- aRect.Bottom := Bottom-FMaxOffset;
- aRect.Top := aRect.Top+FMinOffset;
- end;
- alLeft : begin
- aRect.Left := Left+FMinOffset;
- aRect.Right := aRect.Right-FMaxOffset;
- end;
- alRight : begin
- aRect.Right := Right-FMaxOffset;
- aRect.Left := aRect.Left+FMinOffset;
- end;
- end;
- FOrigin := Point(X,Y);
- FOffset := Point(X,Y);
- ClipCursor(@aRect);
- BeginSizing(BoundsRect);
- if assigned(FOnSplitBegin) then FOnSplitBegin(Self);
- end;
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.MouseMove(Shift: TShiftState; X, Y: Integer);
- var
- aRect : TRect;
- G: integer;
- begin
- inherited MouseMove(Shift,X,Y);
- if not FFixed and (FSizeControl <> nil) and (ssLeft in Shift) then
- begin
- G := Max(FGrid,1);
- aRect := BoundsRect;
- case Align of
- alTop,
- alBottom:
- begin
- OffsetRect(aRect,0,FOffset.Y-FOrigin.Y);
- DrawSizeRect(aRect);
- OffsetRect(aRect,0,(Y-FOffset.Y)div G*G);
- FOffset := Point(X,((Y-FOffset.Y)div G*G)+FOffset.Y);
- DrawSizeRect(aRect);
- end;
- alLeft,
- alRight:
- begin
- OffsetRect(aRect,FOffset.X-FOrigin.X,0);
- DrawSizeRect(aRect);
- OffsetRect(aRect,(X-FOffset.X)div G*G,0);
- FOffset := Point(((X-FOffset.X)div G*G)+FOffset.X,Y);
- DrawSizeRect(aRect);
- end;
- end;
- if Assigned(FOnSplit) then FOnSplit(Self,Shift,X,Y);
- end;
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- var
- aRect: TRect;
- G: integer;
- begin
- inherited MouseUp(Button,Shift,X,Y);
- if not FFixed and (FSizeControl <> nil) and (Button = mbLeft) then
- begin
- G := Max(FGrid,1);
- aRect := BoundsRect;
- case Align of
- alTop,
- alBottom: OffsetRect(aRect,0,FOffset.Y-FOrigin.Y);
- alLeft,
- alRight: OffsetRect(aRect,FOffset.X-FOrigin.X,0);
- end;
- EndSizing(aRect);
- aRect := FSizeControl.BoundsRect;
- case Align of
- alTop : inc(aRect.Bottom,(Y-FOrigin.Y)div G*G);
- alBottom: inc(aRect.Top,(Y-FOrigin.Y)div G*G);
- alLeft : inc(aRect.Right,(X-FOrigin.X)div G*G);
- alRight : inc(aRect.Left,(X-FOrigin.X)div G*G);
- end;
- inc(FUpdate);
- FSizeControl.BoundsRect := aRect;
- dec(FUpdate);
- if assigned(FOnSplitEnd) then FOnSplitEnd(Self);
- end;
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.SetGrid(aValue: integer);
- begin
- if (aValue <> FGrid) then
- begin
- FGrid := Max(aValue,0);
- end;
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.SetSplitterSize(aValue: integer);
- begin
- if (aValue <> FSplitterSize) and (aValue > 0) then
- begin
- FSplitterSize := aValue;
- inc(FUpdate);
- SetSizeControl(FSizeControl);
- dec(FUpdate);
- end;
- {$IFDEF WIN32}
- {$IFDEF TRIAL}
- {$DEFINE _HACK1}
- {$I MMHACK.INC}
- {$ENDIF}
- {$ENDIF}
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.UpdateCursor;
- begin
- if not FFixed then
- Cursor := FCursor
- else
- Cursor := crDefault;
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.SetFixed(aValue: Boolean);
- begin
- if (aValue <> FFixed) then
- begin
- FFixed := aValue;
- UpdateCursor;
- end;
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.SetSizeControl(aValue: TWinControl);
- begin
- if (aValue = nil) then
- begin
- FSizeControl := nil;
- Align := alNone;
- FCursor := crDefault;
- UpdateCursor;
- exit;
- end;
- {$IFDEF WIN32}
- {$IFDEF TRIAL}
- {$DEFINE _HACK2}
- {$I MMHACK.INC}
- {$ENDIF}
- {$ENDIF}
- if (aValue.Align = alNone) or (aValue.Align = alClient) then
- begin
- SetSizeControl(nil);
- raise Exception.Create('Splitter: Control''s align must be left, right, top or bottom');
- end;
- inc(FUpdate);
- Align := aValue.Align;
- case aValue.Align of
- alTop: begin
- FCursor := crsVSplit;
- Top := aValue.Top+aValue.Height;
- Height := FSplitterSize;
- end;
- alBottom: begin
- FCursor := crsVSplit;
- Top := aValue.Top-FSplitterSize;
- Height := FSplitterSize;
- end;
- alLeft: begin
- FCursor := crsHSplit;
- Left := aValue.Left+aValue.Width;
- Width := FSplitterSize;
- end;
- alRight: begin
- FCursor := crsHSplit;
- Left := aValue.Left-FSplitterSize;
- Width := FSplitterSize;
- end;
- end;
- dec(FUpdate);
- FSizeControl := aValue;
- UpdateCursor;
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.Notification(AComponent: TComponent; Operation: TOperation);
- begin
- if (Operation = opRemove) and (AComponent = FSizeControl) then
- SetSizeControl(nil);
- inherited Notification(AComponent,Operation);
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.WMSize(var Msg);
- begin
- inherited;
- if FUpdate = 0 then SetSizeControl(FSizeControl);
- end;
- {-- TMMSplitter ---------------------------------------------------------}
- procedure TMMSplitter.WMMove(var Msg);
- begin
- inherited;
- if FUpdate = 0 then SetSizeControl(FSizeControl);
- end;
- end.