📄 designhookutils.pas
字号:
{******************************************************************************
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 + -