delphi在application.run之前发送消息

时间:2014-03-07 09:29:24

标签: delphi

我正在开发一个防止多个实例的应用程序。我尝试使用wm_copydata向第一个应用程序实例发送消息,它不起作用,但我可以通过WM_SYSCOMMAND发送消息

if not checkInstance.RestoreIfRunning(Application.Handle,oldHandle, 1) then
begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(Tfrm_main, frm_main);
  Application.Run;
end
else
begin

stringToSend := 'My Message';

aCopyData.dwData := 0; //use it to identify the message contents
aCopyData.cbData := 1 + Length(stringToSend) ;
aCopyData.lpData := PChar(stringToSend) ;

SendMessage(oldHandle,WM_COPYDATA,longint(oldHandle),longint(@aCopyData));
end;

....

mainform:

private
procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;
.
.
.
procedure mainForm.WMCopyData(var Msg: TWMCopyData);
begin
ShowMessage('received!');
end;

2 个答案:

答案 0 :(得分:1)

看起来您正在将消息发送到错误的窗口。或者另一种查看方式,您正试图在错误的窗口中处理消息。

你有:

if not checkInstance.RestoreIfRunning(Application.Handle, oldHandle, 1) then

当然,我们看不到checkInstance.RestoreIfRunning背后的代码,但我的蜘蛛意识告诉我oldHandle中返回的句柄是应用程序句柄而不是主窗口句柄。让我怀疑的是:

  1. 您将Application.Handle传递给RestoreIfRunning,因此可能是第二个应用程序尝试运行时看到的句柄。
  2. 您成功获得WM_SYSCOMMAND响应,可能是为了恢复应用程序的第一个实例,但这是由应用程序窗口过程处理的消息。
  3. 因此,在应用程序窗口过程而不是主窗体窗口过程中处理消息,一切都应该很好。使用Application.HookMainWindow来实现这一目标。

答案 1 :(得分:-1)

这是一个解决方案

<强> Unit1.pas

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private declarations }
  public
    procedure WMApp(var msg: TMessage); message WM_APP;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.WMApp(var msg: TMessage);
begin
  Application.Restore;
end;

end.

执行:项目 - 查看来源

Project1.dpr

program Project1;

uses
  Vcl.Forms,
  Windows,
  Messages,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}
var
  Hwnd: THandle;

begin
  Hwnd := FindWindow('TForm1', nil);

  if Hwnd = 0 then
  begin
    Application.Initialize;
    Application.MainFormOnTaskbar := True;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
  end else
  begin
    if not IsWindowVisible(Hwnd) then
      PostMessage(Hwnd, WM_APP, 0, 0);
    SetForegroundWindow(Hwnd);
  end;
end.

全部