使用方法如下:
Manager1.Add(Edit1); //添加Edit到管理中
Manager1.Delete(0); //从管理中删除Edit
///////////////////////////////
unit EditManagerUtils;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, StdCtrls, Forms;
type
TItem = class;
TManager = class;
TItem = class(TComponent)
private
FManager: TManager;
FEditor: TEdit;
FOldWndProc: TWndMethod;
protected
procedure DoChange(Sender: TObject);
procedure DoKeyPress(Sender: TObject; var Key: Char);
procedure Notification(AComponent: TComponent; Operation: TOperation);
override;
procedure EditorWndProc(var Message: TMessage);
public
constructor Create(AOwner: TManager; Editor: TEdit);
destructor Destroy; override;
end;
TManager = class(TComponent)
private
FItemList: TList;
FOnChange: TNotifyEvent;
FOnKeyPress: TKeyPressEvent;
function GetCount: Integer;
function GetItems(Index: Integer): TItem;
protected
procedure Notification(AComponent: TComponent; Operation: TOperation);
override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function Add(Editor: TEdit): Integer;
procedure Delete(Index: Integer);
property Count: Integer read GetCount;
property Items[Index: Integer]: TItem read GetItems; default;
published
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
Procedure Register();
implementation
Procedure Register();
begin
RegisterComponents('standart',[TManager]);
end;
{ TManager }
function TManager.Add(Editor: TEdit): Integer;
begin
Result := FItemList.Add(TItem.Create(Self, Editor));
end;
constructor TManager.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FItemList := TList.Create;
end;
procedure TManager.Delete(Index: Integer);
begin
if (Index = -1) or (Index >= Count) then
Exit;
Self[Index].Free;
end;
destructor TManager.Destroy;
begin
FItemList.Free;
inherited Destroy;
end;
function TManager.GetCount: Integer;
begin
Result := FItemList.Count;
end;
function TManager.GetItems(Index: Integer): TItem;
begin
Result := TItem(FItemList[Index]);
end;
procedure TManager.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) and (AComponent is TItem) then
FItemList.Delete(FItemList.IndexOf(AComponent));
end;
{ TItem }
constructor TItem.Create(AOwner: TManager; Editor: TEdit);
begin
inherited Create(AOwner);
FManager := AOwner;
FEditor := Editor;
FOldWndProc := Editor.WindowProc;
Editor.WindowProc := EditorWndProc;
Editor.FreeNotification(Self);
Editor.ControlStyle := Editor.ControlStyle + [csNoStdEvents]; //禁止触发常规的事件
end;
destructor TItem.Destroy;
begin
if (FEditor <> nil)and(Assigned(FOldWndProc)) then
FEditor.WindowProc := FOldWndProc;
inherited Destroy;
end;
procedure TItem.DoChange(Sender: TObject);
begin
if Assigned(FManager.FOnChange) then
FManager.FOnChange(Sender);
end;
procedure TItem.DoKeyPress(Sender: TObject; var Key: Char);
begin
if Assigned(FManager.FOnKeyPress) then
FManager.FOnKeyPress(Sender, Key);
end;
type
TCrackWinCtrl = class(TWinControl)
end;
procedure TItem.EditorWndProc(var Message: TMessage);
var
Form : TCustomForm;
ch : Char;
CharCode : Word;
begin
case Message.Msg of
CN_COMMAND: //触发OnChange
begin
case TWMCommand(Message).NotifyCode of
EN_CHANGE:
begin
DoChange(FEditor);
end;
else
FOldWndProc(Message);
end;
end;
CM_TEXTCHANGED: //触发OnChange
begin
if not FEditor.HandleAllocated or (GetWindowLong(FEditor.Handle, GWL_STYLE) and
ES_MULTILINE <> 0) then DoChange(FEditor);
end;
WM_CHAR: //触发OnKeyPress
begin
Form := GetParentForm(FEditor);
if (Form <> nil) and (Pointer(Form) <> Pointer(FEditor)) and (Form.KeyPreview) and
TCrackWinCtrl(Form).DoKeyPress(TWMKey(Message)) then
Exit;
with TWMKey(Message) do
begin
Ch := Char(CharCode);
DoKeyPress(FEditor, Ch);
CharCode := Word(Ch);
if Char(CharCode) = #0 then Exit;
end;
FOldWndProc(Message);
end;
//其他消息以此类推
else
FOldWndProc(Message);
end;
end;
procedure TItem.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) and (AComponent = FEditor) then
begin
FEditor.WindowProc := FOldWndProc;
FOldWndProc := nil;
FEditor := nil;
Destroy();
end;
end;
end.