问题
When a user double-clicks a dbgrid, I show a non-modal form.
When they close that form, I want to refresh the grid.
To accomplish that, I have tried the following:
1 - Define a custom message constant:
const
WM_REFRESH_MSG = WM_USER + 1; //defined in a globally available unit
2 - In the OnClose event of my non-modal form, I have this:
procedure TMyNonModalForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
PostMessage(Self.Handle,WM_REFRESH_MSG,0,0);
end;
3 - In the private declarations of the form that holds the dbGrid, I have this:
procedure OnRefreshRequest(var Msg: TMessage); message WM_REFRESH_MSG;
...
procedure TMyFormWithADBGrid.OnRefreshRequest(var Msg: TMessage);
begin
RefreshGrid;
end;
After doing these things, the PostMessage fires fine, but the OnRefreshRequest procedure never runs. What am I doing wrong?
回答1:
Aside from the message name in the other answer, you are posting a message to Self.Handle while Self is going away. You probably meant to post to a different handle (the window that launched the modeless one). Give your modeless window access to that handle when you create it, and post the message there instead.
回答2:
Note that WM_USER is not the correct constant to base your own messages on, unless you are writing a custom control directly descending from TWinControl. Use WM_APP instead.
Also, it's considered good style to use UM_ for User Message instead of WM_ because that prefix is supposed to be reserved for the Windows header files.
回答3:
The post message needs to be sent to the other window handle, not the self.handle that you have listed. One way to do this would be to create a new property on your non-modal form and assign it the handle of the other form just before you show your non-modal one.
Other than that, and implementing the WM_REFRESH_MSG properly (CheGueVerra has it correct) it should work fine.
回答4:
You might try and change the end of the declaration to match the message you are trying to send.
procedure OnRefreshRequest(var Msg: TMessage); message WM_CEA_REFRESH;
Should be this
procedure OnRefreshRequest(var Msg: TMessage); message WM_REFRESH_MSG;
回答5:
I've uploaded an example of "What would Kevin do?" to Embarcadero's newsgroup forum embarcadero.public.attachments.
Basically it's a custom event that the main form (or whatever form/object you want) subscribes to when the non-modal form closes. In the main (or whatever) form...
var
NonModalForm :TfmNonModalForm;
begin
NonModalForm := TfmNonModalForm.Create(nil);
NonModalForm.Execute(NonModalFormClosingListener);
In the Execute method
procedure TfmNonModalForm.Execute(YourListenerMethod: THeyIClosedEvent);
begin
FHeyIClosedEvent := YourListenerMethod;
Show();
end;
If you can't get to the forum and need the additional code, leave a comment and I'll post the missing pieces.
Good luck
来源:https://stackoverflow.com/questions/860119/delphi-custom-message-handlers