2016-03-03 58 views
2

我已经从本文复制的代码发送的消息: Controlling the number of application instances应用程序主形式不接收经由的SendMessage

然而,由SendMessage消息发送的消息没有被主要形式“抓住”。

这是DPR文件中的代码,我们正在注册的消息,然后播放它,如果应用程序的实例已在运行:

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 

这是从主窗体代码:

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; 

问题是程序AppMessage没有被调用。哪里不对?

回答

3

OnMessage用于拦截排队的消息。但是,此消息是发送而不是排队。你需要重写才能窗体的窗口过程来接受它:

添加到您的窗体类型声明的保护部分:

procedure WndProc(var Message: TMessage); override; 

这样实现:

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; 

由于这种形式可能是应用程序主要形式的单一实例,您可以用此代替消息处理程序的主体:

Application.Restore; 
Visible := True; 
SetForeGroundWindow(Handle); 

我也会评论说播放这样的消息对我来说似乎有点冒险。您将发送该消息到系统中的每个顶级窗口。我认为如果你遇到一个对那条信息不应该做出反应的程序,那么它就有可能导致问题。

如果我是我,我会识别您打算瞄准的窗口,并将消息直接发送到该窗口。而且我会使用SendMessageTimeout以在目标应用程序无响应的情况下健壮。在这种情况下,SendMessage将永远不会返回并且发送应用程序也将挂起。

+0

> *“一个对该消息作出反应的程序..”*>风险是其他一些应用程序也注册了'Show_Main_Form'消息。虽然不是很高,但我认为,尽管如此,这个消息可能不是通用的.. –

+0

@Sertac写得很差的程序可能会对某条消息做出回应,而不会检查消息的值。 –

+1

重写'WndProc()'的另一种方法是调用['Application.HookMainWindow()'](http://docwiki.embarcadero.com/Libraries/en/Vcl.Forms.TApplication.HookMainWindow),它将安装消息挂钩到“TApplication”窗口过程中。由于它也是一个顶级窗口,它也将接收广播的消息。 –

相关问题