JosephStyons
JosephStyons

Reputation: 58785

Delphi custom message handlers

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?

Upvotes: 4

Views: 16808

Answers (5)

KevinRF
KevinRF

Reputation: 602

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

Upvotes: 1

Frederik Slijkerman
Frederik Slijkerman

Reputation: 6529

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.

Upvotes: 9

skamradt
skamradt

Reputation: 15548

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.

Upvotes: 2

Jim
Jim

Reputation: 4711

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.

Upvotes: 6

CheGueVerra
CheGueVerra

Reputation: 7983

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;

Upvotes: 1

Related Questions