Entwickler-Ecke
Windows API - Fensterhandle finden / SingleInstance / SetForeGroundWindow
Singlepin - Do 14.08.14 19:15
Titel: Fensterhandle finden / SingleInstance / SetForeGroundWindow
Hallo Gemeinde,
mein Problem ist folgendes, um den doppelten Programmstart zu verhindern hatte ich bisher folgendes.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
| var Flash: FLASHWINFO; Initialization
hFMapping:=CreateFileMapping(INVALID_HANDLE_VALUE,NIL,PAGE_READWRITE, 0,sizeof(Application.Handle), appName); if hFMapping<>0 then begin if GetLastError=ERROR_ALREADY_EXISTS then begin FSpeicher:=MapViewOfFile(hFMapping,FILE_MAP_READ,0,0,0); FHandle:=FSpeicher^; UnmapViewOfFile(FSpeicher); Windows.ShowWindow(FHandle,SW_Normal); Windows.SetForegroundWindow(FHandle); halt; end else begin FSpeicher:=MapViewOfFile(hFMapping,FILE_MAP_WRITE,0,0,0); FSpeicher^:=Application.Handle; UnmapViewOfFile(FSpeicher); end; end else begin Application.MessageBox('Fehler beim Erstellen des Mapping','Abbruch',MB_OK); Halt; end; |
Mit Win7 geht
Delphi-Quelltext
1: 2:
| Windows.ShowWindow(FHandle,SW_Normal); Windows.SetForegroundWindow(FHandle); |
nicht mehr.
Dafür möchte ich jetzt, daß das Programm in der Taskleiste blinkt.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| var Flash: FLASHWINFO; Initialization
hFMapping:=CreateFileMapping(INVALID_HANDLE_VALUE,NIL,PAGE_READWRITE, 0,sizeof(Application.Handle), appName); if hFMapping<>0 then begin if GetLastError=ERROR_ALREADY_EXISTS then begin FSpeicher:=MapViewOfFile(hFMapping,FILE_MAP_READ,0,0,0); UnmapViewOfFile(FSpeicher); FHandle:=FindWindow(NIL,PChar('Programmname')); FillChar(Flash, SizeOf(Flash), 0); Flash.cbSize:=SizeOf(Flash); Flash.hwnd:=FHandle; Flash.uCount:=5; Flash.dwTimeOut:=2000; Flash.dwFlags:=FLASHW_ALL; FlashWindowEx(Flash); halt; end else begin FSpeicher:=MapViewOfFile(hFMapping,FILE_MAP_WRITE,0,0,0); FSpeicher^:=Application.Handle; UnmapViewOfFile(FSpeicher); end; end else begin Application.MessageBox('Fehler beim Erstellen des Mapping','Abbruch',MB_OK); Halt; end; |
Das geht zwar, aber mich stört
Delphi-Quelltext
1:
| FHandle:=FindWindow(NIL,PChar('Programmname')); |
Wie komme ich zum richtigen Handle?
Moderiert von Narses: Titel erweitert.Moderiert von Narses: Topic aus Sonstiges (Delphi) verschoben am Fr 15.08.2014 um 09:38
jaenicke - Do 14.08.14 19:45
Das einfachste ist ein Broadcast an eine von allen Instanzen mit RegisterWindowMessage erstellten Botschaft. Die kann dann die erste Instanz auswerten und sich selbst um die Anzeige kümmern. Oder diese könnte auch einfach z.B. einen Balloon Hint auf dem Tray Icon anzeigen oder so, sprich selbst viel mehr machen als nur blinken lassen.
Und du kannst auch weitere Infos übergeben (Parameter, ...).
An das Fensterhandle kannst du (wenn du es doch damit machen möchtest) kommen, indem du nicht anhand des Fenstertitels vorgehst, sondern über den Klassennamen gehst. Der sollte natürlich dann gut gewählt sein, sprich eindeutig.
Nebenbei:
Statt das in Initialization zu machen und dann mit Halt das Programm gegen einen Baum zu fahren kannst du auch einfach im Projektquelltext das Application.Run nur ausführen, wenn nicht schon eine Instanz lief...
Das ist viel eleganter und sauberer.
Singlepin - Do 14.08.14 20:18
Danke jaenicke
für die schnelle Antwort.
Die Anregungen werde ich mal durchgehen.
In diesem Fall dachte ich, das ich über das Applikatinshande das Fensterhandle ermitteln kann und fertig.
Die Frage ist wie.
Delete - Do 14.08.14 20:35
Singlepin hat folgendes geschrieben : |
...
Das geht zwar, aber mich stört
Delphi-Quelltext 1:
| FHandle:=FindWindow(NIL,PChar('Programmname')); |
Wie komme ich zum richtigen Handle? |
Delphi-Quelltext
1:
| FHandle:= FindWindow( Pchar(string(TForm2.Classname)), Nil ); |
jaenicke - Do 14.08.14 22:58
hathor hat folgendes geschrieben : |
Delphi-Quelltext 1:
| FHandle:=Windows.FindWindow(NIL,PChar(UpperCase(ExtractFileName(ParamStr(0))))); | |
Was hat der Dateiname der Exe mit dem Fenstertitel zu tun? :gruebel:
mandras - Fr 15.08.14 09:16
Ich habe da was aus meiner Mottenkiste ausgegraben um unter Win7 ein Fenster in den Vordergrund zu bekommen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure WinToTop (Handle: hWnd); var ThreadID1, ThreadID2: integer; begin if Handle = GetForeGroundWindow then exit; ThreadID1 := GetWindowThreadProcessID (GetForeGroundWindow, Nil); ThreadID2 := GetWindowThreadProcessID (Handle, Nil); if ThreadID1 <> ThreadID2 then begin AttachThreadInput (ThreadID1, ThreadID2, true); SetForeGroundWindow (Handle); AttachThreadInput (ThreadID1, ThreadID2, false); end else SetForeGroundWindow (Handle); if IsIconic (Handle) then ShowWindow (handle, sw_restore) else ShowWindow (handle, sw_Show); end; |
Vielleicht hilft es ja
Delete - So 17.08.14 00:17
Ich habe es oben geändert in:
Delphi-Quelltext
1:
| FHandle:= FindWindow( Pchar(string(TForm1.Classname)), Nil ); |
Singlepin - Fr 22.08.14 15:28
Ich bin einen Schritt weiter.
mit
Delphi-Quelltext
1: 2: 3: 4:
| FHandle:=FindWindow(NIL,PChar('Artikel suche')); AllowSetForegroundWindow(FHandle); Windows.ShowWindow(FHandle,SW_Normal); Windows.SetForegroundWindow(FHandle); |
bekomme ich meine Anwendung in den Vordergrund.
Somit besteht mein Problem nur noch darin, daß ich mit
Delphi-Quelltext
1:
| FSpeicher^:=Application.Handle; |
seit Windows 7 nicht mehr das richtige Handle in meinem MemoryMappedFile speichere.
Wie schon gesagt ich möchte nicht mit FindWindow nach dem "Falschen" suchen sondern das richtige Handle einfach auslesen.
jaenicke - Fr 22.08.14 16:00
Das Application-Handle ist (bis Delphi 2007 oder mit MainFormOnTaskbar auf False) das Fenster, das den Taskleistenknopf anzeigt. Das hat aber eigentlich nichts mit dem angezeigten Fenster zu tun. Meinst du vielleicht Application.MainForm.Handle?
Singlepin - Fr 22.08.14 16:47
Hallo Jaenicke,
bei Application.MainForm.Handle gibt es einen Laufzeitfehler, aber Application.MainFormHandle ist die Lösung.
Nun muß ich das Ganze nur noch richtig verstehen.
Danke für die Hilfe.
jaenicke - Fr 22.08.14 18:41
Singlepin hat folgendes geschrieben : |
bei Application.MainForm.Handle gibt es einen Laufzeitfehler |
Dann gibt es in dem Moment noch kein Hauptformular, sprich es ist noch nicht fertig erzeugt.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!