Reputation: 1567
I've copied code from this article: Controlling the number of application instances
However, the message being sent by SendMessage is not being 'caught' by the main form.
This is the code in the DPR file, where we are registering the message, and then broadcasting it if an instance of the application is already running:
var
Mutex: THandle;
begin
MyMsg := RegisterWindowMessage('Show_Main_Form');
Mutex := CreateMutex(nil, True, 'B8C24BD7-4CFB-457E-841E-1978A8ED0B16');
if (Mutex = 0) or (GetLastError = ERROR_ALREADY_EXISTS) then
begin
SendMessage(HWND_BROADCAST, MyMsg, 0, 0);
end
This is code from the main form:
var
fmMain: TfmMain;
MyMsg: Cardinal;
implementation
uses
uSettings;
{$R *.dfm}
procedure TfmMain.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
if (Msg.Message = MyMsg) then
begin
beep;
Application.Restore;
Application.MainForm.Visible := True;
SetForeGroundWindow(Application.MainForm.Handle);
Handled := True;
end;
end;
procedure TfmMain.FormCreate(Sender: TObject);
begin
Application.OnMessage := AppMessage;
end;
The problem is that the procedure AppMessage does not get called. What is wrong?
Upvotes: 2
Views: 1467
Reputation: 612864
OnMessage
is used to intercept queued messages. However, this message is sent rather than queued. You need to override the form's window procedure in order to receive it:
Add this to the protected part of your form's type declaration:
procedure WndProc(var Message: TMessage); override;
Implement it like this:
procedure TfmMain.WndProc(var Message: TMessage);
begin
inherited;
if Message.Msg = MyMsg then
begin
Beep;
Application.Restore;
Application.MainForm.Visible := True;
SetForeGroundWindow(Application.MainForm.Handle);
end;
end;
Since this form is presumably the single instance of the application's main form you might replace the body of the message handler with this:
Application.Restore;
Visible := True;
SetForeGroundWindow(Handle);
I would also comment that broadcasting such a message seems a little risky to me. You'll be sending that message to every top-level window in the system. I think that has definite potential to cause problems if you encounter a program that reacts to that message when it should not.
Were it me I would identify the window which you intend to target, and send the message directly to that window. And I would use SendMessageTimeout
to be robust to the scenario where the target app is not responding. In that scenario, SendMessage
will never return and the sending application will also become hung.
Upvotes: 3