www.pudn.com > virdisk_source.rar > TFlatSplitterUnit.pas


unit TFlatSplitterUnit; 
 
{***************************************************************} 
{  TFlatsplitter                                                } 
{  Copyright ©1999 Lloyd Kinsella.                              } 
{                                                               } 
{  FlatStyle is Copyright ©1998-99 Maik Porkert.                } 
{***************************************************************} 
 
interface 
 
{$I Version.inc} 
 
uses Messages, Windows, SysUtils, Classes, Controls, Forms, Menus, Graphics, 
     StdCtrls, ExtCtrls, FlatUtilitys; 
 
type 
  TSplitterStatus = (ssIn, ssOut); 
 
type 
  THack = class(TWinControl); 
 
  TFlatSplitter = class(TGraphicControl) 
  private 
    FUseAdvColors: Boolean; 
    FAdvColorBorder: TAdvColors; 
    FAdvColorFocused: TAdvColors; 
    FBorderColor: TColor; 
    FFocusedColor: TColor; 
    FLineDC: HDC; 
    FDownPos: TPoint; 
    FSplit: Integer; 
    FMinSize: NaturalNumber; 
    FMaxSize: Integer; 
    FControl: TControl; 
    FNewSize: Integer; 
    FActiveControl: TWinControl; 
    FOldKeyDown: TKeyEvent; 
    FLineVisible: Boolean; 
    FOnMoved: TNotifyEvent; 
    FStatus: TSplitterStatus; 
    procedure AllocateLineDC; 
    procedure DrawLine; 
    procedure ReleaseLineDC; 
    procedure UpdateSize(X, Y: Integer); 
    procedure FocusKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); 
    procedure SetColors (Index: Integer; Value: TColor); 
    procedure SetAdvColors (Index: Integer; Value: TAdvColors); 
    procedure SetUseAdvColors (Value: Boolean); 
    procedure CMSysColorChange (var Message: TMessage); message CM_SYSCOLORCHANGE; 
    procedure CMParentColorChanged (var Message: TWMNoParams); message CM_PARENTCOLORCHANGED; 
    procedure CMEnter(var Message: TMessage); message CM_MOUSEENTER; 
    procedure CMExit(var Message: TMessage); message CM_MOUSELEAVE; 
  protected 
    procedure CalcAdvColors; 
    procedure Paint; override; 
    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 StopSizing; 
  public 
    constructor Create(AOwner: TComponent); override; 
  published 
    property AdvColorBorder: TAdvColors index 0 read FAdvColorBorder write SetAdvColors default 50; 
    property AdvColorFocused: TAdvColors index 1 read FAdvColorFocused write SetAdvColors default 50; 
    property UseAdvColors: Boolean read FUseAdvColors write SetUseAdvColors default False; 
    property Color default $00E0E9EF; 
    property FocusedColor: TColor index 0 read FFocusedColor write SetColors default $0053D2FF; 
    property BorderColor: TColor index 1 read FBorderColor write SetColors default $00555E66; 
    property MinSize: NaturalNumber read FMinSize write FMinSize default 30; 
    property OnMoved: TNotifyEvent read FOnMoved write FOnMoved; 
    property Align default alLeft; 
    property Enabled; 
    property ParentColor; 
    property ParentShowHint; 
    property ShowHint; 
    property Visible; 
   {$IFDEF D4CB4} 
    property Anchors; 
    property BiDiMode; 
    property Constraints; 
    property ParentBiDiMode; 
   {$ENDIF} 
  end; 
 
implementation 
 
constructor TFlatSplitter.Create(AOwner: TComponent); 
begin 
  inherited Create(AOwner); 
  Align := alLeft; 
  Width := 5; 
  Cursor := crHSplit; 
  FMinSize := 30; 
  FStatus := ssOut; 
  Color := $00E0E9EF; 
  FocusedColor := $0053D2FF; 
  BorderColor := $00555E66; 
end; 
 
procedure TFlatSplitter.AllocateLineDC; 
begin 
  FLineDC := GetDCEx(Parent.Handle, 0, DCX_CACHE or DCX_CLIPSIBLINGS or DCX_LOCKWINDOWUPDATE); 
end; 
 
procedure TFlatSplitter.DrawLine; 
var 
  P: TPoint; 
begin 
  FLineVisible := not FLineVisible; 
  P := Point(Left, Top); 
  if Align in [alLeft, alRight] then 
    P.X := Left + FSplit 
  else 
    P.Y := Top + FSplit; 
  with P do 
    PatBlt(FLineDC, X, Y, Width, Height, PATINVERT); 
end; 
 
procedure TFlatSplitter.ReleaseLineDC; 
begin 
  ReleaseDC(Parent.Handle, FLineDC); 
end; 
 
procedure TFlatSplitter.Paint; 
var 
  R: TRect; 
begin 
  R := ClientRect; 
  if FStatus = ssIn then 
  begin 
    Canvas.Brush.Color := FFocusedColor; 
    Canvas.FillRect(R); 
    Frame3D(Canvas,R,FBorderColor,FBorderColor,1); 
  end; 
  if FStatus = ssOut then 
  begin 
    Canvas.Brush.Color := Color; 
    Canvas.FillRect(R); 
    Frame3D(Canvas,R,FBorderColor,FBorderColor,1); 
  end; 
end; 
 
procedure TFlatSplitter.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 
 
function FindControl: TControl; 
var 
  P: TPoint; 
  I: Integer; 
begin 
  Result := nil; 
  P := Point(Left, Top); 
  case Align of 
    alLeft: Dec(P.X); 
    alRight: Inc(P.X, Width); 
    alTop: Dec(P.Y); 
    alBottom: Inc(P.Y, Height); 
  else 
    Exit; 
  end; 
  for I := 0 to Parent.ControlCount - 1 do 
  begin 
    Result := Parent.Controls[I]; 
    if PtInRect(Result.BoundsRect, P) then 
      Exit; 
  end; 
  Result := nil; 
end; 
 
var 
  I: Integer; 
begin 
  inherited; 
  if Button = mbLeft then 
  begin 
    FControl := FindControl; 
    FDownPos := Point(X, Y); 
    if Assigned(FControl) then 
    begin 
      if Align in [alLeft, alRight] then 
      begin 
        FMaxSize := Parent.ClientWidth - FMinSize; 
        for I := 0 to Parent.ControlCount - 1 do 
          with Parent.Controls[I] do 
            if Align in [alLeft, alRight] then 
              Dec(FMaxSize, Width); 
            Inc(FMaxSize, FControl.Width); 
        end 
else 
begin 
FMaxSize := Parent.ClientHeight - FMinSize; 
for I := 0 to Parent.ControlCount - 1 do 
with Parent.Controls[I] do 
if Align in [alTop, alBottom] then Dec(FMaxSize, Height); 
Inc(FMaxSize, FControl.Height); 
end; 
UpdateSize(X, Y); 
AllocateLineDC; 
with ValidParentForm(Self) do 
if ActiveControl <> nil then 
begin 
FActiveControl := ActiveControl; 
FOldKeyDown := THack(FActiveControl).OnKeyDown; 
THack(FActiveControl).OnKeyDown := FocusKeyDown; 
end; 
DrawLine; 
end; 
end; 
end; 
 
procedure TFlatSplitter.UpdateSize(X, Y: Integer); 
var 
  S: Integer; 
begin 
  if Align in [alLeft, alRight] then 
    FSplit := X - FDownPos.X 
  else 
    FSplit := Y - FDownPos.Y; 
  S := 0; 
  case Align of 
    alLeft: S := FControl.Width + FSplit; 
    alRight: S := FControl.Width - FSplit; 
    alTop: S := FControl.Height + FSplit; 
    alBottom: S := FControl.Height - FSplit; 
  end; 
  FNewSize := S; 
  if S < FMinSize then 
    FNewSize := FMinSize 
  else 
    if S > FMaxSize then 
      FNewSize := FMaxSize; 
  if S <> FNewSize then 
  begin 
    if Align in [alRight, alBottom] then 
      S := S - FNewSize 
    else 
      S := FNewSize - S; 
    Inc(FSplit, S); 
  end; 
end; 
 
procedure TFlatSplitter.MouseMove(Shift: TShiftState; X, Y: Integer); 
begin 
  inherited; 
  if Assigned(FControl) then 
  begin 
    DrawLine; 
    UpdateSize(X, Y); 
    DrawLine; 
  end; 
end; 
 
procedure TFlatSplitter.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 
begin 
  inherited; 
  if Assigned(FControl) then 
  begin 
    DrawLine; 
    case Align of 
      alLeft: FControl.Width := FNewSize; 
      alTop: FControl.Height := FNewSize; 
      alRight: 
        begin 
          Parent.DisableAlign; 
          try 
            FControl.Left := FControl.Left + (FControl.Width - FNewSize); 
            FControl.Width := FNewSize; 
          finally 
            Parent.EnableAlign; 
          end; 
        end; 
      alBottom: 
        begin 
          Parent.DisableAlign; 
          try 
            FControl.Top := FControl.Top + (FControl.Height - FNewSize); 
            FControl.Height := FNewSize; 
          finally 
            Parent.EnableAlign; 
          end; 
        end; 
    end; 
    StopSizing; 
  end; 
end; 
 
procedure TFlatSplitter.FocusKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); 
begin 
  if Key = VK_ESCAPE then 
    StopSizing 
  else 
    if Assigned(FOldKeyDown) then 
      FOldKeyDown(Sender, Key, Shift); 
end; 
 
procedure TFlatSplitter.StopSizing; 
begin 
  if Assigned(FControl) then 
  begin 
    if FLineVisible then DrawLine; 
    FControl := nil; 
    ReleaseLineDC; 
    if Assigned(FActiveControl) then 
    begin 
      THack(FActiveControl).OnKeyDown := FOldKeyDown; 
      FActiveControl := nil; 
    end; 
  end; 
  if Assigned(FOnMoved) then 
    FOnMoved(Self); 
end; 
 
procedure TFlatSplitter.CMEnter(var Message: TMessage); 
begin 
  if FStatus <> ssIn then 
  begin 
    FStatus := ssIn; 
    Repaint; 
  end; 
end; 
 
procedure TFlatSplitter.CMExit(var Message: TMessage); 
begin 
  if FStatus <> ssOut then 
  begin 
    FStatus := ssOut; 
    Repaint; 
  end; 
end; 
 
procedure TFlatSplitter.SetColors (Index: Integer; Value: TColor); 
begin 
  case Index of 
    0: FFocusedColor := Value; 
    1: FBorderColor := Value; 
  end; 
  Invalidate; 
end; 
 
procedure TFlatSplitter.CalcAdvColors; 
begin 
  if FUseAdvColors then 
  begin 
    FBorderColor := CalcAdvancedColor(Color, FBorderColor, FAdvColorBorder, darken); 
    FFocusedColor := CalcAdvancedColor(Color, FFocusedColor, FAdvColorFocused, darken); 
  end; 
end; 
 
procedure TFlatSplitter.SetAdvColors(Index: Integer; Value: TAdvColors); 
begin 
  case Index of 
    0: FAdvColorBorder := Value; 
    1: FAdvColorFocused := Value; 
  end; 
  CalcAdvColors; 
  Invalidate; 
end; 
 
procedure TFlatSplitter.SetUseAdvColors (Value: Boolean); 
begin 
  if Value <> FUseAdvColors then 
  begin 
    FUseAdvColors := Value; 
    ParentColor := Value; 
    CalcAdvColors; 
    Invalidate; 
  end; 
end; 
 
procedure TFlatSplitter.CMSysColorChange (var Message: TMessage); 
begin 
  if FUseAdvColors then 
  begin 
    ParentColor := True; 
    CalcAdvColors; 
  end; 
  Invalidate; 
end; 
 
procedure TFlatSplitter.CMParentColorChanged (var Message: TWMNoParams); 
begin 
  inherited; 
  if FUseAdvColors then 
  begin 
    ParentColor := True; 
    CalcAdvColors; 
  end; 
  Invalidate; 
end; 
 
end.