Autor |
Beitrag |
Jakob Schöttl
Beiträge: 929
Erhaltene Danke: 1
Delphi 7 Professional
|
Verfasst: Mi 03.01.07 15:56
Hi,
ich will grad ein Programm machen (ehrlich gesagt nachmachen), das das aktive Fenster Topmost bzw. nicht Topmost macht.
Dazu hab ich folgenden Quelltext zum auspobieren geschrieben. Leider funktioniert er nicht, und ich weiß nicht, wo der Fehler ist.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TForm1.Button1Click(Sender: TObject); var wh: HWND; style: DWORD; begin wh := GetForegroundWindow; if wh > 0 then begin style := GetWindowLong(wh,GWL_EXSTYLE); if (style and WS_EX_TOPMOST) = WS_EX_TOPMOST then begin ShowMessage('gerade noch topmost'); style := style and not WS_EX_TOPMOST; end else begin showMessage('gerade noch nicht topmost'); style := style or WS_EX_TOPMOST; end; SetWindowLong(wh,GWL_EXSTYLE,style); end; end; |
Hoffentlich findet jemand meinen Fehler.
|
|
Reinhard Kern
Beiträge: 591
Erhaltene Danke: 14
|
Verfasst: Mi 03.01.07 16:45
Jakob Schöttl hat folgendes geschrieben: | Hi,
ich will grad ein Programm machen (ehrlich gesagt nachmachen), das das aktive Fenster Topmost bzw. nicht Topmost macht.
Dazu hab ich folgenden Quelltext zum auspobieren geschrieben. Leider funktioniert er nicht, und ich weiß nicht, wo der Fehler ist.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TForm1.Button1Click(Sender: TObject); var wh: HWND; style: DWORD; begin wh := GetForegroundWindow; if wh > 0 then begin style := GetWindowLong(wh,GWL_EXSTYLE); if (style and WS_EX_TOPMOST) = WS_EX_TOPMOST then begin ShowMessage('gerade noch topmost'); style := style and not WS_EX_TOPMOST; end else begin showMessage('gerade noch nicht topmost'); style := style or WS_EX_TOPMOST; end; SetWindowLong(wh,GWL_EXSTYLE,style); end; end; |
Hoffentlich findet jemand meinen Fehler. |
Hallo,
nach meinem jetzigen Kenntnisstand kann das so nicht funktionieren: GetForegroundWindow liefert das gewünschte Window, egal welches, aber SetWindowLong kann nur Werte setzen in Windows, die zum eigenen Prozess gehören. Das ist Folge der Abschottung zwischen Prozessen, dient also der Sicherheit. Unter 16bit-Anwendungen ging das und geht das auch heute noch.
Zu umgehen ist das etwa so (für SetForegroundWindow):
Delphi-Quelltext 1: 2: 3: 4: 5:
| FGThread := GetWindowThreadProcessID (GetForegroundWindow,nil); OtherThread := GetWindowThreadProcessID (FIWindow,nil); AttachThreadInput (FGThread,OtherThread,true); SetForegroundWindow (FIWindow); AttachThreadInput (FGThread,OtherThread,false); |
Es kann sein, dass in zukünftigen Versionen die Schotten weiter dicht gemacht werden. In einem wirklich sicheren System siehst du nur deine eigene Anwendung, der Rest geht dich nichts an.
Gruss Reinhard
|
|
Jakob Schöttl
Beiträge: 929
Erhaltene Danke: 1
Delphi 7 Professional
|
Verfasst: Do 04.01.07 13:07
ja, das kann sein.
Aber in diesem Fall muss der Fehler wo anders liegen, weil ich nähmlich das Ereignis OnClick meines Buttons verwende. Ich hab schon überprüft. Die Handles von Form1 (meinem eigenen) und GetForegroundWindow stimmen überein, weil mein Fenster auch im Vordergrund ist. Und trotzdem geht es nicht.
Das auslesen des attributes TopMost funktioniert richtig!
Es muss also meiner Meinung an ungefähr folgendem liegen (Auszüge von oben):
Delphi-Quelltext 1:
| style := style and not WS_EX_TOPMOST; |
Delphi-Quelltext 1:
| style := style or WS_EX_TOPMOST; |
Delphi-Quelltext 1:
| SetWindowLong(wh,GWL_EXSTYLE,style); |
|
|
Jakob Schöttl
Beiträge: 929
Erhaltene Danke: 1
Delphi 7 Professional
|
Verfasst: Do 04.01.07 14:05
Also, obwohl ich glaube ich in der Logik keinen Fehler hatte, geht es so nicht.
Aber jetzt hab ich eine Möglichkeit gefunden, das problem anders zu lösen, nähmlich doch mit SetWindowPos:
Delphi-Quelltext 1:
| SetWindowPos(wh,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE + SWP_NOMOVE); |
bzw.
Delphi-Quelltext 1:
| SetWindowPos(wh,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE + SWP_NOMOVE); |
... und das geht übrigens auch (noch) mit externen Anwendungs-Fenstern.
|
|
Reinhard Kern
Beiträge: 591
Erhaltene Danke: 14
|
Verfasst: Do 04.01.07 19:14
Jakob Schöttl hat folgendes geschrieben: | Also, obwohl ich glaube ich in der Logik keinen Fehler hatte, geht es so nicht.
Aber jetzt hab ich eine Möglichkeit gefunden, das problem anders zu lösen, nähmlich doch mit SetWindowPos:
Delphi-Quelltext 1:
| SetWindowPos(wh,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE + SWP_NOMOVE); |
bzw.
Delphi-Quelltext 1:
| SetWindowPos(wh,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE + SWP_NOMOVE); |
... und das geht übrigens auch (noch) mit externen Anwendungs-Fenstern. |
Hallo, zu deiner Beruhigung:
Microsoft selbst empfiehlt, Fenster mit SetWindowPos auf Top zu setzen (KB von 1993), allerdings mit einer anderen Begründung: MDI-Fenster können nicht den Stil WS_EX_TOPMOST haben. Wahrscheinlich ist SetWindowPos auch deshalb noch eine der wenigen Funktionen, denen der Zugriff auf fremde Fenster erlaubt ist.
Gruss Reinhard
|
|
Jakob Schöttl
Beiträge: 929
Erhaltene Danke: 1
Delphi 7 Professional
|
Verfasst: Do 04.01.07 20:13
Gut, hier hab ich jetzt mein Programm zum Download reingestellt. Wenns das Forum hier nicht gäbe, würde ich noch lange nach der Lösung meines Problems suchen...
|
|
|