Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Single instance: SendMessage i ShowMainForm:=False

1 view
Skip to first unread message

Sergej Srepfler

unread,
Dec 4, 2011, 5:01:23 PM12/4/11
to
Naletio sam na jednu glupost oko koje moj mozak odbija pronaci
rjesenje
Stoga vas molim za misao vodilju

Tema: Single instance only
Cilj:
- Zelim da mi ponovo pokretanje aplikacije otvori vec pokrenutu
aplikaciju
( u ovom slucaju treba otvoriti Form2 vec pokrenute aplikacije, a nova
aplikacija prestaje s radom)
Problem:
- U staroj aplikaciji je ShowMainForm:=False, pa SendMessage nikad
nije stigao do mog handlera
Napomena:
-Ako je ikako moguce, volio bih ostaviti ShowMainForm:=False (pravi
program se stavlja u systray)

Ako pricam gluposti, RTFM odgovor je OK, samo me uputite na
literaturu.

Okolina: Delphi 7
Kod za SendMessage je sa delphi.about.com (malo modificiran)

Pojednostavljena verzija setupa je ova

-------------------
program Project1;

uses
Windows,
Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

var
Mutex : THandle;

begin
// Allow only one instance to run
MyMsg := RegisterWindowMessage('WM_Test');
Mutex := CreateMutex(nil, True, 'mutex_Test');
if (Mutex = 0) OR (GetLastError = ERROR_ALREADY_EXISTS) then begin
SendMessage(HWND_BROADCAST, MyMsg, 0, 0);
end
else begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm2, Form2);
Form1.AppInit;
Application.Run;
if Mutex <> 0 then
CloseHandle(Mutex);
end;
end.
-------------
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
public
{ Public declarations }
procedure AppInit;
end;

var
Form1: TForm1;
MyMsg: Cardinal;

implementation

uses Unit2;


{$R *.dfm}

procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
if Msg.Message = MyMsg then begin
// U principu ovo treba napraviti Form2.Show;
// no ne znam da li radi jer ne dodje do ovdje
Application.Restore;
SetForeGroundWindow(Application.MainForm.Handle);
Handled := true;
end;
end;

procedure TForm1.AppInit;
begin
// Hide main window
Application.ShowMainForm:=False;
// run on startup
Form2.Show;
end; {AppInit}

procedure TForm1.FormCreate(Sender: TObject);
begin
// Register message to the application
Application.OnMessage := AppMessage;
end;

end.
-------------------
unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, StdCtrls;

type
TForm2 = class(TForm)
btn1: TButton;
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.btn1Click(Sender: TObject);
begin
Application.Terminate;
end;

end.



Tomislav

unread,
Dec 5, 2011, 3:06:21 AM12/5/11
to
Meni ovo sljaka, ali nemam ShowMainForm:=False;

procedure TOneInstance.WMain(var Message: TMessage);
begin
if not(csDesigning in ComponentState)
and (Message.Msg=WM_2ND_INST_ACTIVATE)
then begin
Application.Minimize;
Application.Restore;
Application.BringToFront;
end
else DefWindowProc(fHWND,Message.Msg,Message.WParam,Message.LParam);
end;

Stanislav Vlasic

unread,
Dec 8, 2011, 9:45:32 AM12/8/11
to
On Sun, 4 Dec 2011 14:01:23 -0800 (PST), Sergej Srepfler
<sergej....@gmail.com> wrote:

/cut

Davno, davno sam radio nesto slicno. Pokretanje exe-a app 1 (console
app) je rezultiralo zatvaranje app 2 (u biti slanje stringa) koja je u
trayu.

Ovo nije kompajlirano i nije testirano (samo c/p) ali je radilo prije
6-7 godina... :)

Evo koda:

app1:

const
WM_MYMESSAGE = WM_USER + 1000;

CMD_QUIT = 'QUIT';

function SendToTray(Cmd: String): Boolean;
var
H: HWND;
L: Atom;
begin
H := FindWindow('TVSDrvMapTrayForm', 'VSDrvMapTrayForm');
if H <> 0 then begin
L := GlobalAddAtom(PChar(UpperCase(Cmd)));
SendMessage(H, WM_MYMESSAGE, 0, L); { send atom handle }
GlobalDeleteAtom(L); { free after use }
Result := True;
end else
Result := False;
end;


U kodu pozivanje fje:

SendToTray(CMD_QUIT);


app2:

const
WM_MYMESSAGE = WM_USER + 1000;

public
procedure MyMessage(var T:TMessage); message WM_MYMESSAGE;

procedure TVSDrvMapTrayForm.MyMessage(var T:TMessage); { message
WM_MYMESSAGE }
var
P:Array [0..255] of char;
begin
T.Msg:= WM_MYMESSAGE;
GlobalGetAtomName(T.LParam, P,255); { "receive" string }
StartCommand(P);
end;

StartCommand je procedura sa 1 string varijablom. P je string koji si
poslao iz app 1.

Ivan@work

unread,
Dec 9, 2011, 7:34:06 AM12/9/11
to
Ako ti se ne da programirati JEDI ima gotovo rješenje: TJclAppInstances.
Stavi komponentu na formu i u OnCmdLineReceived ubaci kod koji prikazuje
drugu formu (Form2.Show).

Sergej Srepfler

unread,
Dec 9, 2011, 10:40:01 PM12/9/11
to
On 8 pro, 09:45, Stanislav Vlasic <svlasic_majmunce@_gmail.com> wrote:
> On Sun, 4 Dec 2011 14:01:23 -0800 (PST), Sergej Srepfler
>
Da, ovo lici na rjesenje. Uglavnom .- shvatio sam sto me pati:
%&*$# OnMessage BI TREBAO hvatati sve poruke, ALI... to ne radi.
Na ovom linku je to lijepo opisano:
http://www.delphicorner.f9.co.uk/articles/apps7.htm

Cim sam zamijenio originalni
Application.OnMessage := AppMessage;
sa
Application.HookMainWindow(AppMessage);

stvar je pocela dobivati smisao (citaj usao je u dio koda gdje treba
raditi ono sto treba).

Rjesenje koje sam ja iskemijao je malkice slozenije od ovog, tako da
cu ga pogledati sa zanimanjem. Hvala.

Sergej Srepfler

unread,
Dec 9, 2011, 10:41:01 PM12/9/11
to
Trenutno mi ovo ne odgovara, ali dobro je znati. Hvala na infu.
0 new messages