当用户在Programm中添加或更改某些内容时,我在FormQuery上检查是否进行了某些修改并且未完成保存,并且警告用户如果退出该用户,所有数据将丢失。
问题是我一次检查一个组件。编辑已修改,但DateTimePicker则没有。
我的问题是:如果可能,如何用一个命令检查表单上的内容是否有所更改?有控制权吗?
更新
我正在考虑是否存在通用的东西,像这样的东西,但是对于每个可由用户以任何方式更改的控制器。
将4个TEdit拖放到窗体上,并放置一个TLabel。
procedure TForm1.SomethingChanged(Sender: TObject);
begin
Label1.Caption:='SOMETHING CHANGED!';
end;
在TForm.Create上,我这样做:
procedure TForm1.FormCreate(Sender: TObject);
var i : integer;
Child : TComponent;
begin
for i := 0 to ComponentCount-1 do
begin
Child := Components[i];
if Child is TEdit then
TEdit(Child).OnChange:=SomethingChanged;
if Child is TDateTimePicker then
TDateTimePicker(Child).OnChange:=SomethingChanged;
if Child is TComboBox then
TComboBox(Child).OnChange:=SomethingChanged;
end;
end;
我可以为所有控件(例如Editors,DateTimePickers,ComboBoxes等)创建此控件,但我当时想也许有一些很酷的“秘密”更聪明的方法可以做到这一点。
谢谢
更新2
现在我还有另一个问题,如果可能的话,不知道。假设其中一个TEdit的onChange事件定义如下:
procedure TForm1.Edit1Change(Sender: TObject);
begin
Label2.Caption:='THIS WAS EDIT1CHANGE';
end;
当应用程序启动时,这将重置为我的自定义onChange事件,并且永远不会运行该事件。
是否可以通过某种方式链接onChange事件?
就像我有一个地方,我只检查是否发生了某些变化……但是我允许TEdit执行它的“正常” onChange事件。
谢谢
答案 0 :(得分:2)
我认为关键在于这些组件主要是TWinControl的后代,所以为什么不挂接到它们的OnChange消息CM_CHANGED,这样就不会像您所说的那样发生OnChange事件链接问题(我希望涉及事件时,Delphi带有C#+ =运算符之类的东西。
您将需要以下课程来实现
1。 TListener
TListener = class
private
FOnChangeHappend: TNotifyEvent;
FWinControl: TWinControl;
FMsgToListen: Cardinal;
FOldWndProc: System.Classes.TWndMethod;
procedure FWindowProc(var Message: TMessage);
public
constructor Create(aWinControl: TWinControl; aMsg: Cardinal);
Destructor Destroy;
property OnChangeHappend: TNotifyEvent read FOnChangeHappend write FOnChangeHappend;
end;
{ TListener }
constructor TListener.Create(aWinControl: TWinControl; aMsg: Cardinal);
begin
FMsgToListen := aMsg;
FWinControl := aWinControl;
FOldWndProc := aWinControl.WindowProc;
aWinControl.WindowProc := FWindowProc;
end;
destructor TListener.Destroy;
begin
if Assigned(FOldWndProc) then
FWinControl.WindowProc := FOldWndProc;
inherited Destroy;
end;
procedure TListener.FWindowProc(var Message: TMessage);
begin
if ((Message.Msg = FMsgToListen) and (Assigned(FOnChangeHappend))) then
begin
FOnChangeHappend(FWinControl);
end;
FOldWndProc(Message);
end;
2。 TListenerList
TListenerList = class
private
FListners: TObjectList<TListener>;
FOnChangeHappend: TNotifyEvent;
public
constructor Create;
Destructor Destroy;
procedure ListenTo(aWinControl: TWinControl; aMsg: Cardinal);
property OnChangeHappend: TNotifyEvent read FOnChangeHappend write FOnChangeHappend;
end;
{ TListenerList }
constructor TListenerList.Create;
begin
FListners := TObjectList<TListener>.Create;
FListners.OwnsObjects := True;
end;
destructor TListenerList.Destroy;
begin
FListners.Free;
end;
procedure TListenerList.ListenTo(aWinControl: TWinControl; aMsg: Cardinal);
var
aListener: TListener;
begin
aListener := TListener.Create(aWinControl, aMsg);
aListener.OnChangeHappend := FOnChangeHappend;
Flistners.Add(aListener);
end;
您可以在表单的OnCreate事件中使用它
procedure TForm8.FormCreate(Sender: TObject);
begin
FListenerList := TListenerList.Create();
FListenerList.OnChangeHappend := TextChanged;
FListenerList.ListenTo(DBEdit1, CM_CHANGED);
FListenerList.ListenTo(DBMemo1, CM_CHANGED);
FListenerList.ListenTo(DBComboBox1, CM_CHANGED);
FListenerList.ListenTo(DBCheckBox1, CM_CHANGED);
FListenerList.ListenTo(DBRichEdit1, CM_CHANGED);
FListenerList.ListenTo(Memo1, CM_CHANGED);
FListenerList.ListenTo(Edit1, CM_CHANGED);
FListenerList.ListenTo(ComboBox1, CM_CHANGED);
FListenerList.ListenTo(DateTimePicker1, CM_CHANGED);
FListenerList.ListenTo(CheckBox1, CM_CHANGED);
end;
procedure TForm8.TextChanged(Sender: TObject);
begin
memo2.Lines.Add(TWinControl(Sender).Name + 'Changed');
end;
,但此消息有限制。例如,如果编辑控件的文本为“ Hello”,而您想删除它(按返回键),则将触发Listener事件五次(每个字母一个),因此在记录时应使用CM_ENTER和CM_EXIT消息输入每个TWinControl的值时(具有焦点),然后将其与退出时的值进行比较(失去焦点)。
此方法适用于任何TWinControl后代(用户可以与之交互的几乎所有控件)
答案 1 :(得分:1)
如果使用dbedit,dbcombobax ..您可以进行控制。
因为
您必须将它们链接到表或查询。
您必须将数据源用于链接。
if table1.state=dsedit then
begin
end;
如果使用编辑,则定义一个变量。
在所有字段的onchange
事件中将值分配给变量。然后检查此变量。
procedure Tform1.editChange (Sender: TObject);
begin
variable_change:= 'YES';
end;
if variable_change = 'YES' then
begin
end;