You could send the needed CM_Exit in the OnCloseQuery event of your form.
procedure TMyForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if Assigned(ActiveControl) then
SendMessage(ActiveControl.Handle, CM_EXIT,0,0);
end;
Question
I've noticed that if a form with data aware controls is closed from the title bar and the active control has had its data changed that change never makes it into the underlying data source. I've traced this to the CM_EXIT message never getting fired for the control.
How can I ensure that no matter which control last had focus these changes get pushed to the data source?
Solution
You could send the needed CM_Exit in the OnCloseQuery event of your form.
procedure TMyForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if Assigned(ActiveControl) then
SendMessage(ActiveControl.Handle, CM_EXIT,0,0);
end;
OTHER TIPS
I usually handle this by testing all data set components. If they're in the Modified
state, then I simply call Post
on them.
You can do this in the OnCloseQuery
for the form.
On your OnClose
event handler just add the line below:
Perform(WM_NEXTDLGCTL, 0, 0);
It will make the focus go to the next component in the TabOrder
and, by removing the focus from the current component, will send the value to the field.
Just FYI. A cross platform way of forcing the control to exit is:
SelectNext(ActiveControl, True, True);
This will work for any control that has at lease one other sibling in the same parent container.
I think the right way is to call UpdateRecord
on the underlying dataset components (e.g. in OnCloseQuery
). This will update the data from the controls.
If you call Post
instead, this will internally call UpdateRecord
as well. This is why Marcus' answer will work too.