⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 designhookutils.pas

📁 delphi 运行进行设计模式,象delphi的编辑环境一样
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{******************************************************************************
TFrom DesignHook接口的实现.

wr960204 武稀松
2007.9.10
******************************************************************************}
unit DesignHookUtils;

interface
uses
  Windows, SysUtils, Messages, Classes, Controls, Forms, ComObj, ActiveX,
  Graphics;

//开始设计.设计整个窗口里,以窗口为Owner的控件
function BeginDesign(Form: TCustomForm): IDesignerHook; overload;
//开始设计.设计窗口里,Root控件为Owner的控件
function BeginDesign(Form: TCustomForm; Root: TWinControl): IDesignerHook; overload;
//终止设计
procedure EndDesign(Form : TCustomForm);

implementation

//点到区的转化
function PointToRect(pt1, pt2: TPoint): TRect;
begin
  if pt1.X < pt2.X then
  begin
    Result.Left := pt1.X;
    Result.Right := pt2.X;
  end
  else
  begin
    Result.Left := pt2.X;
    Result.Right := pt1.X;
  end;
  if pt1.Y < pt2.Y then
  begin
    Result.Top := pt1.Y;
    Result.Bottom := pt2.Y;
  end
  else
  begin
    Result.Top := pt2.Y;
    Result.Bottom := pt1.Y;
  end;
end;

const
  GrabHandleSize    = 4;
type
  TDesignerHook = class;

  TCrackComponent = class(TComponent);
  TCrackControl = class(TControl);

  //管理FrameSize的.免得要遍历释放每个FrameSize
  TGrabHandleManager = class(TComponent)
  private
    FDesigner: TDesignerHook;
  public
    constructor Create(ADesigner: TDesignerHook);
  end;

  //IDesignerHook的实现部分
  TDesignerHook = class(TInterfacedObject, IDesignerNotify, IDesignerHook)
  private
    FGrabHandleManager: TGrabHandleManager;
    FForm: TCustomForm;
    FRoot: TWinControl;
    FControls: TList;
    FDraggingControl: TControl;
    FDragging: Boolean;
    FBeforDragPos: TPoint;

    FSelecting: Boolean;
    FPointStart, FPointEnd: TPoint;
    FOldRect: TRect;
    FNewRect: TRect;


    FMouseRect: TRect;//鼠标被限制的范围
    procedure MouseLock(Sender: TControl);//锁定鼠标到某一个范围
    procedure MouseFree();//释放对鼠标的锁定

    function OnMessage(Sender: TControl; var Message: TMessage): Boolean;
    procedure Remove(AControl: TControl); overload;
    procedure Remove(Index: Integer); overload;
    procedure Clear();
    function Add(AControl: TControl): TControl;
    procedure ShowGrabHandle(const Show: boolean);
    procedure ClearGrabHandle(AControl: TControl);
    procedure SetDragging(const Value: Boolean);
    function GetControlCount: Integer;
    function GetControls(Index: Integer): TControl;
    procedure AddRectControls(Parent: TWinControl; Rect: TRect);
    function OwnerCheck(Sender: TControl; CheckOnwer: TComponent): Boolean;

    procedure MouseDown(Sender: TControl; Button: TMouseButton; Shift: TShiftState; X: Integer;
      Y: Integer); virtual;
    procedure MouseUp(Sender: TControl; Button: TMouseButton; Shift: TShiftState; X: Integer;
      Y: Integer); virtual;
    procedure MouseMove(Sender: TControl; Shift: TShiftState; X: Integer; Y: Integer); virtual;
    procedure KeyDown(Sender: TControl; var Key: Word; Shift: TShiftState); virtual;
  public
    constructor Create();
    destructor Destroy; override;

    property Dragging: Boolean read FDragging write SetDragging;
    property ControlCount: Integer read GetControlCount;
    property Controls[Index: Integer]: TControl read GetControls;
  public
    { IDesignerNotify 的接口}
    procedure Modified;
    procedure Notification(AnObject: TPersistent; Operation: TOperation);
  public
    { IDesignerHook 的接口}
    function GetCustomForm: TCustomForm;
    procedure SetCustomForm(Value: TCustomForm);
    function GetIsControl: Boolean;
    procedure SetIsControl(Value: Boolean);
    function IsDesignMsg(Sender: TControl; var Message: TMessage): Boolean;
    procedure PaintGrid;
    procedure PaintMenu;
    procedure ValidateRename(AComponent: TComponent;
      const CurName, NewName: string);
    function UniqueName(const BaseName: string): string;
    function GetRoot: TComponent;

    property IsControl: Boolean read GetIsControl write SetIsControl;
    property Form: TCustomForm read GetCustomForm write SetCustomForm;
  end;

  //小黑点的方向性
  TGrabHandleDirect = (fdLeftUp, fdUp, fdRightUp, fdRight,
    fdRightDown, fdDown, fdLeftDown, fdLeft);

  //就是选中时空间边上那八个小黑点
  TGrabHandle = class(TCustomControl)
  private
    FManager: TGrabHandleManager;
    FControl: TControl;
    FDirect: TGrabHandleDirect;
    FDesigner: TDesignerHook;
    procedure Pos();
    function GetDesigner: TDesignerHook;
  protected
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer;
      Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X: Integer;
      Y: Integer); override;
    procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  public
    constructor Create(AManager: TComponent; AControl: TControl; ADirect: TGrabHandleDirect);
    destructor Destroy; override;

    property Designer: TDesignerHook read GetDesigner;
  end;

function BeginDesign(Form: TCustomForm): IDesignerHook;
begin
  Result := BeginDesign(Form, Form);
end;

function BeginDesign(Form: TCustomForm; Root: TWinControl): IDesignerHook;
var
  Designer          : TDesignerHook;
  I                 : Integer;
begin
  Designer := TDesignerHook.Create();
  Designer.Form := Form;
  Designer.FRoot := Root;

  Result := Designer as IDesignerHook;
  Form.Designer := Result;
  TCrackComponent(Form).SetDesigning(True, False);
  TCrackComponent(Root).SetDesigning(True, True);

end;

procedure EndDesign(Form : TCustomForm);
begin
  TCrackComponent(Form).SetDesigning(False, True);
  Form.Designer := nil;
end;

{ TDesignerHook }

function TDesignerHook.Add(AControl: TControl): TControl;
var
  D                 : TGrabHandleDirect;
  FrameSize         : TGrabHandle;
begin
  Result := AControl;
  FControls.Add(AControl);
  for D := fdLeftUp to fdLeft do
  begin
    FrameSize := TGrabHandle.Create(FGrabHandleManager, AControl, D);
  end;

end;

procedure TDesignerHook.AddRectControls(Parent: TWinControl; Rect: TRect);
  function InRect(R1, R2: TRect): Boolean;
  begin
    Result := False;
    if not IntersectRect(R1, R1, R2) then
      Exit;
    Result := not IsRectEmpty(R1);
  end;
var
  I                 : Integer;
begin
  Clear();
  for I := 0 to Parent.ControlCount - 1 do
    if InRect(Rect, Parent.Controls[I].BoundsRect) and
      OwnerCheck(Parent.Controls[I], FRoot) then
    begin
      Add(Parent.Controls[I]);
    end;

end;

procedure TDesignerHook.Clear;
var
  I                 : Integer;
begin
  for I := FControls.Count - 1 downto 0 do
    Remove(I);
end;

procedure TDesignerHook.ClearGrabHandle(AControl: TControl);
var
  I                 : Integer;
begin
  for I := FGrabHandleManager.ComponentCount - 1 downto 0 do
    if (FGrabHandleManager.Components[I] is TGrabHandle)
      and (TGrabHandle(FGrabHandleManager.Components[I]).FControl = AControl) then
      TGrabHandle(FGrabHandleManager.Components[I]).Free;
end;

constructor TDesignerHook.Create;
begin
  FGrabHandleManager := TGrabHandleManager.Create(Self);
  FControls := TList.Create;
end;

destructor TDesignerHook.Destroy;
begin
  if FForm <> nil then
    TCrackComponent(FForm).SetDesigning(False, True);
  
  FGrabHandleManager.Free;
  FControls.Free;
  inherited Destroy;
end;

function TDesignerHook.GetControlCount: Integer;
begin
  Result := FControls.Count;
end;

function TDesignerHook.GetControls(Index: Integer): TControl;
begin
  Result := TControl(FControls[Index]);
end;

function TDesignerHook.GetCustomForm: TCustomForm;
begin
  Result := FForm;
end;

function TDesignerHook.GetIsControl: Boolean;
begin
  Result := TCrackControl(FForm).IsControl;
end;

function TDesignerHook.GetRoot: TComponent;
begin
  Result := FForm;
end;

function TDesignerHook.OnMessage(Sender: TControl;
  var Message: TMessage): Boolean;
var
  CtrlIndex, I      : Integer;
begin
  Result := ((Message.Msg >= WM_MOUSEFIRST) and (Message.Msg <= WM_MOUSELAST))
    or ((Message.Msg >= WM_KEYFIRST) and (Message.Msg <= WM_KEYLAST));

  case Message.Msg of
    WM_LBUTTONDOWN:
      MouseDown(
        Sender,
        mbLeft,
        KeysToShiftState(TWMMouse(Message).Keys),
        TWMMouse(Message).XPos,
        TWMMouse(Message).YPos
        );
    WM_MOUSEMOVE:
      begin
        MouseMove(
          Sender,
          KeysToShiftState(TWMMouse(Message).Keys),
          TWMMouse(Message).XPos,
          TWMMouse(Message).YPos);

      end;
    WM_LBUTTONUP:
      begin
        MouseUp(
          Sender,
          mbLeft,
          KeysToShiftState(TWMMouse(Message).Keys),
          TWMMouse(Message).XPos,
          TWMMouse(Message).YPos);
      end;
    WM_KEYDOWN:
      begin
        KeyDown(
          Sender,
          TWMKey(Message).CharCode,
          KeyDataToShiftState(TWMKey(Message).KeyData)
          );
      end;
  end;
  if Sender = FForm then
    Result := False;

end;

function TDesignerHook.IsDesignMsg(Sender: TControl;
  var Message: TMessage): Boolean;
begin
  Result := False;
  if (Sender is TGrabHandle) then
    Exit;

  case Message.Msg of
    WM_MOUSEFIRST..WM_MOUSELAST,
      WM_KEYFIRST..WM_KEYLAST:
      Result := OnMessage(Sender, Message);
  end;
end;

procedure TDesignerHook.KeyDown(Sender: TControl; var Key: Word;
  Shift: TShiftState);
var
  I                 : Integer;
begin
  if (ControlCount = 0)
    or ((not (ssShift in Shift)) and (not (ssCtrl in Shift)))
    or (Key in [VK_CONTROL, VK_SHIFT])
    then
    Exit;
  if (ControlCount = 1) and (Controls[0] = FForm) then
    Exit;

  if ssCtrl in Shift then
  begin
    case Key of
      VK_UP:
        begin
          ShowGrabHandle(False);
          try
            for I := 0 to ControlCount - 1 do
            begin
              Controls[I].Top := Controls[I].Top - 1;
            end;
          finally
            ShowGrabHandle(True);
          end;
        end;
      VK_DOWN:
        begin
          ShowGrabHandle(False);
          try
            for I := 0 to ControlCount - 1 do
            begin
              Controls[I].Top := Controls[I].Top + 1;
            end;
          finally
            ShowGrabHandle(True);
          end;
        end;
      VK_LEFT:
        begin
          ShowGrabHandle(False);
          try
            for I := 0 to ControlCount - 1 do
            begin
              Controls[I].Left := Controls[I].Left - 1;
            end;
          finally
            ShowGrabHandle(True);
          end;
        end;
      VK_RIGHT:
        begin
          ShowGrabHandle(False);
          try
            for I := 0 to ControlCount - 1 do
            begin
              Controls[I].Left := Controls[I].Left + 1;
            end;
          finally
            ShowGrabHandle(True);
          end;
        end;
    end;
  end
  else
  begin
    case Key of
      VK_UP:
        begin
          ShowGrabHandle(False);
          try
            for I := 0 to ControlCount - 1 do
            begin
              if Controls[I].Height - 1 > 1 then
                Controls[I].Height := Controls[I].Height - 1;
            end;
          finally
            ShowGrabHandle(True);
          end;
        end;
      VK_DOWN:
        begin
          ShowGrabHandle(False);
          try
            for I := 0 to ControlCount - 1 do
            begin
              if Controls[I].Height + 1 > 1 then
                Controls[I].Height := Controls[I].Height + 1;
            end;
          finally
            ShowGrabHandle(True);
          end;
        end;
      VK_LEFT:
        begin
          ShowGrabHandle(False);
          try
            for I := 0 to ControlCount - 1 do
            begin
              if Controls[I].Width - 1 > 1 then

                Controls[I].Width := Controls[I].Width - 1;
            end;
          finally
            ShowGrabHandle(True);
          end;
        end;
      VK_RIGHT:
        begin
          ShowGrabHandle(False);
          try
            for I := 0 to ControlCount - 1 do
            begin
              if Controls[I].Width + 1 > 1 then
                Controls[I].Width := Controls[I].Width + 1;
            end;
          finally
            ShowGrabHandle(True);
          end;
        end;
    end;
  end;
end;

procedure TDesignerHook.Modified;
begin
end;

procedure TDesignerHook.MouseDown(Sender: TControl; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  CtrlIndex, I      : Integer;
begin
  if Dragging then
    Exit;

  CtrlIndex := FControls.IndexOf(Sender);

  if (ssShift in Shift) then //按Shift多选
  begin
    if (Sender = FRoot)or(Sender = FForm) then //多选不能添加Root或者Form
      Exit;

    if CtrlIndex = -1 then
    begin
      Add(Sender);
      Dragging := False;
    end
    else
    begin
      Remove(Sender);

⌨️ 快捷键说明

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