如何截其他控制的事件? ( 积分: 100 )

  • 主题发起人 主题发起人 kzy7517
  • 开始时间 开始时间
K

kzy7517

Unregistered / Unconfirmed
GUEST, unregistred user!
我准备写个类或控件,该类或控件可以指定界面上的Edit控件,当这些Edit控件发生onKeyPress、onChange等事件时,就转为调用自已写的类或控件中的事件。但不想在各个Edit控件中来写这些事件来调这个类或控件的方法,不知有何好的方法。
例如:我指定Edit1、Edit2要纳入管理,不用在Edit1和Edit2的onChange事件中写任何代码,当这两个Edit发生onChange事件时,自动调用我的类中的onEditChange事件(自己写的方法)。
 
参看 子类化
 
子类化?
我并不是想从TEdit或从TCustomEdit继承,而是另外写个类,能够截取其他控件的事件。
 
不需要写类都可以做.
1, 在消息中拦截.
2, 写个Edit1Change(Sender: TObject);方法, 需要拦截的,就把这个方法付给对应的Edit的OnChange属性即可.可以做到动态赋值.
 
你可以用WindowProc属性,但是必须保存原来的的值并进行调用。。。
如果有其他东西也使用了这个属性的话,就也不安全了。。。
 
duhai_lee
1、请问有没有例子看看。
2、第二种方法不是我要的方法。我需要的方法是对原界面上的Edit等控件不添加任何代码(包插事件代码),只需要根据我的类中指定的Edit控件名,当这些控件发生相应的事件时,就直接执行我自已的方法。因为我是做的公用的东东,不能让下面的开发员将每个界面中的Edit等控件去添件各种事件的代码。
 
使用方法如下:
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.
 
后退
顶部