views:

705

answers:

5

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  A: 

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;
CheGueVerra
Sorry, the CEA_REFRESH was copied from my actual code, whereas the WM_REFRESH_MSG was generic, for the purposes of the question. They do actually match in the code.
JosephStyons
+4  A: 

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.

Jim
1 - modified the constructor of the modeless form to accept a THandle2 - call it with that new constructor3 - post the message to that new handle4 - Works great!
JosephStyons
+2  A: 

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.

skamradt
+2  A: 

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.

Frederik Slijkerman
+1  A: 

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

KevinRF