4

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?

JosephStyons
  • 57,317
  • 63
  • 160
  • 234

5 Answers5

9

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
  • 6,471
  • 28
  • 39
6

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
  • 4,691
  • 1
  • 25
  • 23
  • 1 - modified the constructor of the modeless form to accept a THandle 2 - call it with that new constructor 3 - post the message to that new handle 4 - Works great! – JosephStyons May 13 '09 at 20:26
2

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
  • 15,366
  • 2
  • 36
  • 53
1

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
  • 7,849
  • 4
  • 37
  • 49
  • 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 May 13 '09 at 20:22
1

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
  • 602
  • 3
  • 13