16. maj 2002 - 15:49Der er
23 kommentarer og 2 løsninger
Kun 1 instans, og hvis findes, så hvis eksisterende
Jeg sidder og laver lidt på et program som der kun må køre 1 instans af. Det er heller ikke noget problem, men jeg vil gerne ha' at hvis man starter programmet igen, så sætter den bare fokus på det allerede åbne program. Hvis det åbne program er minimeret så kan jeg godt få det til at virke, men hvis programmet bare ligger bag nogle andre ting, så kan jeg ikke så det frem foran alle de andre programmer.
Jeg bruger følgende kode:
.dpr filen:
program Project1;
uses Forms, Windows, Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
begin {Attempt to create a named mutex} CreateMutex(nil, false, 'ReportViewer'); {if it failed then there is another instance} if GetLastError = ERROR_ALREADY_EXISTS then begin {Send all windows our custom message - only our other} {instance will recognise it, and restore itself} SendMessage(HWND_BROADCAST, RegisterWindowMessage('ReportViewer'), 0, 0); {Lets quit} Halt(0); end; Application.Initialize; {Tell Delphi to un-hide it's hidden application window} {This allows our instance to have a icon on the task bar} Application.ShowMainForm := true; ShowWindow(Application.Handle, SW_RESTORE); Application.CreateForm(TForm1, Form1); Application.Run; end.
type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.DFM}
var OldWindowProc : Pointer; {Variable for the old windows proc} MyMsg : DWord; {custom systemwide message}
function NewWindowProc(WindowHandle : hWnd; TheMessage : LongInt; ParamW : LongInt; ParamL : LongInt) : LongInt stdcall; begin if TheMessage = MyMsg then begin {Tell the application to restore, let it restore the form} SendMessage(Application.handle, WM_SYSCOMMAND, SC_RESTORE, 0); SetForegroundWindow(Application.Handle); {We handled the message - we are done} Result := 0; exit; end; {Call the original winproc} Result := CallWindowProc(OldWindowProc, WindowHandle, TheMessage, ParamW, ParamL); end;
procedure TForm1.FormCreate(Sender: TObject); begin sleep(5000); {Register a custom windows message} MyMsg := RegisterWindowMessage('ReportViewer'); {Set form1's windows proc to ours and remember the old window proc} OldWindowProc := Pointer(SetWindowLong(Form1.Handle, GWL_WNDPROC, LongInt(@NewWindowProc))); end;
procedure TForm1.FormDestroy(Sender: TObject); begin {Set form1's window proc back to it's original procedure} SetWindowLong(Form1.Handle, GWL_WNDPROC, LongInt(OldWindowProc)); end;
end.
Jeg har prøvet at smide en SetForegroundWindow ind et par forskellige steder, men det har ikke rigtig noget effekt.
Den moderne arbejdsplads er i stigende grad afhængig af mødelokaler til at fremme samarbejde, men dette skift medfører også stigende sikkerhedsudfordringer.
ups så ikke lige de havde kikket på nogle af de funktioner ;) jeg kan se at du har prøvet. SetForegroundWindow(Application.Handle); men du bliver jo nødtil at angive handlet på den første aplication, og ikke den der kører nu, for ellers vil du jo bare bringe den anden aplication frem i Z rækken. (hvor den sikkert allerede er øvererst).
uses Forms, Windows, Dialogs, Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
type TGlobalData = record H : hWnd; end; pGlobalData = ^TGlobalData; const Name : PChar = 'Pelles BlackBox Heste Kode'; var MapHandle : THandle; GlobalData : pGlobalData; begin MapHandle := CreateFileMapping(HWND($FFFFFFFF), nil,PAGE_READWRITE,0,1024, Name); GlobalData := MapViewOfFile( MapHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TGlobalData)); if GetLastError <> ERROR_ALREADY_EXISTS then begin Application.Initialize; Application.CreateForm(TForm1, Form1); GlobalData^.H := Application.MainForm.Handle; Application.Run;
UnMapViewOfFile( GlobalData ); CloseHandle(MapHandle); end else begin MessageDlg('Skod hest !'#13'Der må kun være een instancs i luften af gangen !!!', mtError, [mbOK],0); Form1.Show; SetForegroundWindow (Form1Handle); end; end.
hmmn .. skal man også teste sin kode ? Og ikke bare hugge fra noget jeg har lavet til Pelle (pellelil) ?
Nå DET her er testet
program Project1;
uses Forms, Windows, Dialogs, Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
type TGlobalData = record H : hWnd; end; pGlobalData = ^TGlobalData; const Name : PChar = 'Pelles BlackBox Heste Kode'; var MapHandle : THandle; GlobalData : pGlobalData; begin MapHandle := CreateFileMapping(HWND($FFFFFFFF), nil,PAGE_READWRITE,0,1024, Name); GlobalData := MapViewOfFile( MapHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TGlobalData)); if GetLastError <> ERROR_ALREADY_EXISTS then begin Application.Initialize; Application.CreateForm(TForm1, Form1); GlobalData^.H := Application.MainForm.Handle; Application.Run;
UnMapViewOfFile( GlobalData ); CloseHandle(MapHandle); end else begin MessageDlg('Skod hest !'#13'Der må kun være een instancs i luften af gangen !!!', mtError, [mbOK],0); SetForegroundWindow (GlobalData^.H); end; end.
Havde ellers prøvet med GlobalData^.H men fik en Access Violation først ;)
Nå, men din nye kode virker - næsten. Din kode virker ikke hvis vinduet er minimeret, men virker godt nok hvis den bare ligger bagved nogle andre programmer. Altså lige modsat af hvad min egen kode kunne :)
Så er det jo "bare" at mixe de 2 stumper sammen !? ;)
Jens: Tak for eksemplet, men det virker altså stadig kun hvis vinduet er minimeret :(
Hvis vi ikke kan få det her til at virke ordentlig, så må vi ændre det til at den lukker den allerede åbne applikation og så starter den igen. Vil bare helst ha' det andet til at virke :)
if IsIconic(application.handle) then ShowWindow (application.Handle, SW_SHOWNORMAL); SetForegroundWindow (application.Handle);
Men hvis du har win2000 eller xp så vil den bare blinke i startmenu'en. Jeg er ikke sikker på at det lader sig gøre i 2000 og næsten sikker på at det ikke er muligt i xp
det jeg gør er at minimere winduet først (også selvom det er minimeret), derefter restore jeg det igen, og det virker, for så vil det altid komme i forgrunden ;)
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.