我有一个非常大的设置表单,我想用类中的数据填充。所以我做了很多的Delphi:如何在不调用onchange事件的情况下在TEdit/TMaskEdit中设置文本
Edt1.text := ASettings.FirstThing;
我想避免
Edt1.onchange := nil;
Edt1.text := ASettings.FirstThing;
Edt1.onchange := edt1Onchange;
如何更改文本框中的文本和回避onchange事件。
我有一个非常大的设置表单,我想用类中的数据填充。所以我做了很多的Delphi:如何在不调用onchange事件的情况下在TEdit/TMaskEdit中设置文本
Edt1.text := ASettings.FirstThing;
我想避免
Edt1.onchange := nil;
Edt1.text := ASettings.FirstThing;
Edt1.onchange := edt1Onchange;
如何更改文本框中的文本和回避onchange事件。
我已经使用了类似更改OnChange处理程序的内容,但更常见的是,我使用了一个标志。
updatingFromCode := true;
Edt1.Text := ASettings.FirstThing;
updatingFromCode := false;
然后
procedure TForm1.OnChange(...);
begin
if updatingFromCode then
Exit;
...
此外,而不是硬编码的OnChange的实际的OnChange过程中,我将存储编辑控件的当前值,然后重新设置(这将工作,如果它没有设置,或者如果另一个地方改变了它等)
oldOnChange := Edt1.OnChange;
Edt1.OnChange := nil;
Edt1.Text := ASettings.FirstThing;
Edt1.OnChange := oldOnChange;
据我所知,如果您的对象的OnChange设计为在Text属性更改时触发,则必须坚持将事件临时设置为零。我自己,我做这种方式(在一个try最后):
Edt1.onchange := nil;
try
Edt1.text := ASettings.FirstThing;
finally
Edt1.onchange := edt1Onchange;
end;
你也可以做一些程序来为您处理:
procedure SetTextWithoutOnChange(anEdit: TEdit; str: String);
var
anEvent: TNotifyEvent;
begin
anEvent := anEdit.OnChange;
anEdit.OnChange := nil;
try
anEdit.Text := str;
finally
anEdit.OnChange := anEvent;
end;
end;
你可能会考虑使用一个对象来管理NIL处理事件并恢复以前安装的事件处理程序。假设要恢复的事件恰好是在设计时分配的事件/碰巧有“适合的名称” - 你应该总是保存/恢复当前分配的处理程序,以确保安全。
这将提供比SetTextWithoutOnChange()程序更加可重复使用的工具:
TSuspendEvent = class
private
fObject: TObject;
fEvent: String;
fHandler: TMethod;
public
constructor Create(const aObject: TObject; aEvent: String);
destructor Destroy; override;
end;
constructor TSuspendEvent.Create(const aObject: TObject; aEvent: String);
const
NILEvent : TMethod = (Code: NIL; Data: NIL);
begin
inherited Create;
fObject := aObject;
fEvent := aEvent;
fHandler := GetMethodProp(aObject, aEvent);
SetMethodProp(aObject, aEvent, NILEvent);
end;
destructor TSuspendEvent.Destroy;
begin
SetMethodProp(fObject, fEvent, fHandler);
inherited;
end;
在使用,这看起来是这样的:
with TSuspendEvent.Create(Edit1, 'OnChange') do
try
Edit1.Text := 'Reset!';
finally
Free;
end;
对于“你不要使用'与'人群' - 通过一切手段宣布自己一个额外的本地变量,并使用它,如果它可以帮助你在夜间更容易入睡。:)
或者,使其更方便地使用和消除“与”,我会做TSuspendEvent类的接口对象,敷在产生一个接口引用它的功能及其使用的是可以允许“住在范围”,as exemplified by my AutoFree() implementation. In fact, you could use AutoFree() as-is已经管理这个:
AutoFree(TSuspendEvent.Create(Edit1, 'OnChange'));
Edit1.Text := 'Reset!';
Dsabling事件一个超出单一程序的范围,期限,需要更多的管理比任何帮助工具,很可能是能够我认为这是以一种通用的方式提供的,至少不是没有特定的手段显式存储事件,而不是自动。
如果你只是包裹TSuspendEvent里面它自己的界面产生功能,千篇一律的AutoFree(),你可以进一步简化这:
SuspendEvent(Edit1, 'OnChange');
Edit1.Text := 'Reset!';
最后一点,我认为这应该很容易看出,如果需要,可以简单地扩展以支持在单个调用中暂停对象上的多个事件,例如:
SuspendEvent(Edit1, ['OnChange', 'OnEnter']);
哇,这似乎很多工作,尽管可能值得。我会记住这一点,并可能在某一天实施它,谢谢! – 2010-06-24 13:25:58
这不是很多工作,真的大约需要3分钟,而“AutoFree”大约需要10分钟),结果是在您使用结果的项目的整个生命周期内将继续累计节约成本(代码完全是generi c - 小'g')。 – Deltics 2010-06-24 21:09:22
我知道这是一个古老的问题,但我想我会添加我的解决方案,而不涉及前面的答案中列出的任何复杂的过程,以防它出现在另一个搜索中。
问题是onChange事件本身。我根本不使用它来处理文本字段。
删除所有OnChange并使用OnExit代替并将其绑定到OnKeyUp。
所有的编辑都有一个共同的祖先TCustomEdit。
我一般使用称为CustomEditKeyUp一种方法和指向一个表上的所有编辑这个单一的方法(TEDIT,TLabeledEdit等等)
type THack = class(TCustomEdit);
procedure TForm1.CustomeEditKeyUP(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (Key=VK_RETURN) and (Sender is TCustomEdit) then
{This is just to isolate the one occasion when they press the
enter but don't exit immediately}
if Assigned(THack(Sender).OnExit) then THack(Sender).OnExit(Sender);
end;
出于某种原因,所述的OnExit处于TCustomEdit私人所以黑客是需要的。如果您知道编辑内容来自OnExit公开的其他路线,则投射方式不同,而且Hack不是必需的。
然后为每个编辑的控制,如果你想以编程方式更改值没有它发射使用特定的OnExit
procedure TForm1.MyEditExit(Sender: TObject);
begin
if MyEdit.Modified then
begin
{Do Something here}
MyEdit.Modified := false;
end;
end;
“的OnExit”
....
MyEdit.Text :='I've changed it'
MyEdit.Modified := false;
....
对我来说,最大的好处就是,当我解析输入为一个有效的数字,我只需要这样做一次编辑完成后,而不是每个退格,删除插入等所有包围的尝试,除了各种格式函数错误,因为他们不明白空间等。对于数据库e tc,通话次数会大大减少。
这是我的两个通便。
你不能也使用发件人参数吗?据推测,他希望OnChange能够在有人将文本输入框中时触发,而不是在从单独的过程中填充文本时(如自动填充类型)。在这种情况下,我是否认为你可以拥有TForm1.OnChange(发件人:TObject),然后做“如果发件人为TEdit”(做其他)(什么都不做)“?那么你没有所有额外的东西在代码中设置和取消设置变量 – 2010-05-13 00:18:10
编号OnChange事件的发送者将永远是TEdit,无论用户是更新文本还是可编程地发送.VCL从未将发送者参数设置为零 – 2010-06-23 21:03:46