Avatar billede snowball Novice
16. maj 2002 - 15:49 Der 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.

.pas filen:

unit Unit1;

interface

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

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.

Nogen forslag !? :)

Snowball
Avatar billede snowball Novice
16. maj 2002 - 15:50 #1
Hov, der kom lige et h for meget med i overskriften ;)

Snowball
Avatar billede siz23 Nybegynder
16. maj 2002 - 16:33 #2
hvad med nogle af disse funktioner.
SetForegroundWindow()
BringWindowToTop()
SetActiveWindow()

håber du kunne bruge det.
Avatar billede siz23 Nybegynder
16. maj 2002 - 16:37 #3
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).
Avatar billede snowball Novice
16. maj 2002 - 16:38 #4
Hvor vil du sætte den ind !? Har som sagt prøvet med SetForegroundWindow uden held.

Snowball
Avatar billede hermandsen Juniormester
16. maj 2002 - 22:53 #5
Application.BringToFront ?
Avatar billede borrisholt Novice
17. maj 2002 - 07:34 #6
prøv det her :

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);
    Form1.Show;
    SetForegroundWindow (Form1Handle);
  end;
end.


Jens B
Avatar billede snowball Novice
17. maj 2002 - 08:04 #7
Jens: Hvor får du din Form1Handle fra !? :)

Snowball
Avatar billede borrisholt Novice
17. maj 2002 - 08:08 #8
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.


I morgen er det iøvrigt store heste dag !

Jens B
Avatar billede snowball Novice
17. maj 2002 - 08:13 #9
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 !? ;)

Snowball
Avatar billede borrisholt Novice
17. maj 2002 - 08:15 #10
så brug ShowWindow

jens B
Avatar billede snowball Novice
17. maj 2002 - 08:18 #11
Den bruger jeg jo selv i min egen kode, og det virker jo ikke helt !

Du tænker på ShowWindow (GlobalData^.H, SW_RESTORE); ik' !?

Snowball
Avatar billede borrisholt Novice
17. maj 2002 - 08:20 #12
hvad med SW_SHOW   

Jens B
Avatar billede snowball Novice
17. maj 2002 - 08:23 #13
Nope, virker stadig ikke !

Snowball
Avatar billede borrisholt Novice
17. maj 2002 - 08:28 #14
Så pros en message WM_HESt til din form :

.....
    CloseHandle(MapHandle);
  end
  else
    PostMessage( GlobalData^.H, WM_HEST, 0, 0);
end.

Overe i din form så :

const
  WM_HEST = WM_USER + $0001;


også lyt efter WM_HEST:

procedure WMHest(var Message: TMessage); message WM_HEST;


procedure TForm1.WMHest(var Message: TMessage);
begin
  ShowWindow (Handle, SW_SHOWNORMAL);
  Show;
  SetForegroundWindow (Handle);
end;

Det virker !

Jens B
Avatar billede snowball Novice
17. maj 2002 - 08:41 #15
hhmm....Hvor vil du sætte nedenstående ind !?

const
  WM_HEST = WM_USER + $0001;

Lige meget hvor jeg sætter den ind så skriver: Undeclared Indentifier: WM_HEST

Snowball
Avatar billede borrisholt Novice
17. maj 2002 - 08:45 #16
her

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  SysTray, Menus;

const
  WM_HEST = WM_USER + $0001;
type
  TForm1 = class(TForm)


jens B
Avatar billede snowball Novice
17. maj 2002 - 08:48 #17
Nu ved jeg ikke lige hvordan du tester, men hos mig virker det altså stadig ikke helt :)

Kan du ikke prøve og lave et komplet eksempel !? ;)

Snowball
Avatar billede snowball Novice
17. maj 2002 - 10:17 #18
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 :)

Snowball
Avatar billede tormork Nybegynder
18. maj 2002 - 00:14 #19
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
Avatar billede snowball Novice
18. maj 2002 - 00:17 #20
hhmm....Programmet skal netop køre under Win2k !

Så må vi nok hellere gå over til at den skal lukke det eksisterende program og så lade den nye køre videre !

Snowball
Avatar billede siz23 Nybegynder
18. maj 2002 - 12:46 #21
ok dette er en lidt suspect måde at gøre det på. men det virker ;)
og den er meget inspireret af jens B eksemble.

project1.dpr
-------------------------------------------------------
program Project1;

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

{$R *.RES}

type
  TGlobalData = record
    H : hWnd;
  end;
  pGlobalData = ^TGlobalData;
const
  Name : PChar = 'Pelles BlackBox Heste Kode';
  WM_HEST = WM_USER + $0001;

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
      PostMessage( GlobalData^.H, WM_HEST, 0, 0);
      UnMapViewOfFile( GlobalData );
      CloseHandle(MapHandle);
  end;
end.
-------------------------------------------------------



unit1.pas
-------------------------------------------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;
const
  WM_HEST = WM_USER + $0001;
type
  TForm1 = class(TForm)
  private
    { Private declarations }
  public
  procedure WMHest(var Message: TMessage); message WM_HEST;
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.WMHest(var Message: TMessage);
begin
    Application.Minimize;
    Application.Restore;
end;

end.
---------------------------------------------------



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 ;)
Avatar billede siz23 Nybegynder
18. maj 2002 - 12:50 #22
btw: mit største problem med jens b eksembel var, at min minimize knap ikke virkede, efter den havde restoret vinduet... lidt suspect synes jeg.
Avatar billede snowball Novice
18. maj 2002 - 12:56 #23
OK. Jeg kan dog først afprøve det på tirsdag da jeg ikke har koden herhjemme !

Snowball
Avatar billede snowball Novice
21. maj 2002 - 08:51 #24
Det virker !

Jeg har hverken minimize eller maximize knap på min form, så det er ikke noget problem. Dog var det ikke en fejl jeg kunne fremprovokere.

Snowball
Avatar billede siz23 Nybegynder
21. maj 2002 - 14:29 #25
goodie, takker for points.
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester