Seite 1 von 1
Fenster focus erzwingen
Verfasst: Freitag 5. Januar 2007, 23:02
von basti33
Hallo,
ich suche nach einer Möglichkeit, mit der sich der Fokus eines Fensters erzwingen lässt, auch wenn der Anwender ein anderes Fenster im Vordergrund hat. Ich brauche dies in einem Programm, das sich in gewissen Intervallen beim Benutzer melden soll und in der Zwischenzeit im Hintergrund oder minimiert läuft. SetFocus() funktioniert nicht, denn es bewirkt gar keine Veränderung.
Danke
Re: Fenster focus erzwingen
Verfasst: Samstag 6. Januar 2007, 00:17
von gerold
basti33 hat geschrieben:ich suche nach einer Möglichkeit, mit der sich der Fokus eines Fensters erzwingen lässt
Hi basti33!
Die Fensterverwaltung ist Sache des Betriebsystems oder des Windowmanagers (oder so ähnlich)... und nicht die eines einzelnen Programmes.
Unter Windows ist die API-Funktion ``SetForegroundWindow`` dafür verantwortlich, ein Fenster in den Vordergrund zu bringen.:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
import wx
import win32gui
import win32con
import time
from thread import start_new_thread
wx.SetDefaultPyEncoding("iso-8859-1")
class MyFrame(wx.Frame):
def __init__(self, parent = None, id = -1, title = "Ich bin ganz oben auf..."):
wx.Frame.__init__(
self, parent, id, title, style = wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP
)
panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
panel.SetSizer(vbox)
vbox.Add((0, 0), 1)
btn_close = wx.Button(panel, -1, u"Schließen")
btn_close.Bind(wx.EVT_BUTTON, lambda evt: self.Close())
vbox.Add(btn_close, 0, wx.ALIGN_CENTER | wx.ALL, 10)
vbox.Add((0, 0), 1)
self.Show()
self.MakeModal() # Muss nicht unbedingt sein. Kann aber helfen, wenn
# mehrere Fenster (Frames) mit im Spiel sind.
# Nur zum Demonstrieren --> Thread, der ein paar Sekunden wartet und
# dann das Fenster aktiviert, falls es den Fokus noch nicht hatte.
start_new_thread(self.nach_oben_damit, ())
def nach_oben_damit(self):
hwnd = self.GetHandle()
time.sleep(2)
win32gui.SetForegroundWindow(hwnd)
def main():
"""Hauptprozedur"""
app = wx.PySimpleApp()
f = MyFrame()
app.MainLoop()
if __name__ == "__main__":
main()
mfg
Gerold

Verfasst: Samstag 6. Januar 2007, 22:18
von basti33
Hallo Gerold,
ich habe es genauso gemacht wie du beschrieben hast, bekomme jedoch immer diese aussagelose Fehlermeldung
Traceback (most recent call last):
File "C:\Dokumente und Einstellungen\Basti\Desktop\Vokabeltrainer_13.py", line 243, in UeberpruefeAntwort
winxpgui.SetForegroundWindow(hwnd)
pywintypes.error: (0, 'SetForegroundWindow', 'No error message is available')
Ich weiß nicht, was ich da falsch mach, ich verwende auf jeden Fall auch
Code: Alles auswählen
hwnd = self.GetHandle()
winxpgui.SetForegroundWindow(hwnd)
Ich habe es auch schon mit winxpgui versucht, aber da ändert sich auch nichts. Ich hoffe du oder irgendwer anders kann mir weiter helfen.
Danke
PS: Wäre toll wenn noch jemand eine Lösung für Linux wüsste!
Verfasst: Samstag 6. Januar 2007, 22:39
von gerold
basti33 hat geschrieben:ich habe es genauso gemacht wie du beschrieben hast, bekomme jedoch immer diese aussagelose Fehlermeldung
Hi basti33!
Funktioniert mein Beispiel?
Es könnte sein, dass du versuchst ein Unterfenster und kein Hauptfenster (wx.Frame) nach oben zu bekommen.
Vielleicht versuchst du ja auch etwas nach oben zu bekommen, was noch nicht angezeigt wird. Aber ausschlaggeben ist eigentlich zuerst mal, ob mein Beispiel, so wie es oben steht, funktioniert, oder nicht.
mfg
Gerold

Verfasst: Samstag 6. Januar 2007, 23:31
von basti33
Ja, es funktioniert. Aber weil das Fenster als Style wx.STAY_ON_TOP angegeben hat ist es immer im Vordergrund, was es aber nicht soll. Vielleicht liegt hier ein Missverständnis vor, aber ich möchte ein Fenter, das nach einer gewissen Zeit in den Vordergrund kommt, auch wenn es von einem anderen Programm, wie z.B. einem Browser überlagert ist. Wenn ich wx.STAY_ON_TOP entferne kommt dieser Traceback:
Unhandled exception in thread started by <bound method MyFrame.nach_oben_damit of <__main__.MyFrame; proxy of <Swig Object of type 'wxFrame *' at 0x46e2a78> >>
Traceback (most recent call last):
File "<Module1>", line 47, in nach_oben_damit
pywintypes.error: (0, 'SetForegroundWindow', 'No error message is available')
Danke für die Mühe
Verfasst: Sonntag 7. Januar 2007, 00:07
von gerold
basti33 hat geschrieben:Ja, es funktioniert. Aber weil das Fenster als Style wx.STAY_ON_TOP angegeben hat ist es immer im Vordergrund, was es aber nicht soll.
Hi basti33!
Wenn ich im Beispiel die Initialisierung ändere....
Code: Alles auswählen
wx.Frame.__init__(
self, parent, id, title, #style = wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP
)
...und den den Thread vier Sekunden schlafen lege...
Code: Alles auswählen
def nach_oben_damit(self):
hwnd = self.GetHandle()
time.sleep(4)
self.Restore()
win32gui.SetForegroundWindow(hwnd)
...dann wird nach exakt vier Sekunden das Fenster in den Vordergrund geholt. Egal ob es bereits den Fokus hat, oder nicht. Damit auch ein minimiertes Fenster angezeigt wird, habe ich noch ``self.Restore()`` mit eingebaut.
Irgendwie kann ich deine Fehler nicht nachvollziehen.
Meine Umgebung:
- Windows XP SP2
- Python 2.4.4
- wxPython 2.8.0.1 (msw-unicode)
- pywin32-210
mfg
Gerold

Verfasst: Sonntag 7. Januar 2007, 00:50
von basti33
Hallo,
es funktioniert solange das Fenster von keinem anderen überdeckt ist problemlos. Wenn ich aber z.B. den Internet Explorer darüber habe, kommt wieder besagte Fehlermeldung. Ich weiß nicht, woran das liegen soll. Meine Liste mit der eingesetzten Software weicht nur in dem Punkt von deiner ab, dass ich Python 2.5 verwende.
Hier noch einmal die Meldung:
Unhandled exception in thread started by <bound method Hauptmenue.Schlafzeit of <__main__.Hauptmenue; proxy of <Swig Object of type 'wxFrame *' at 0x37e1740> >>
Traceback (most recent call last):
File "C:\Dokumente und Einstellungen\Basti\Desktop\Vokabeltrainer_13.py", line 256, in Schlafzeit
win32gui.SetForegroundWindow(hwnd)
pywintypes.error: (0, 'SetForegroundWindow', 'No error message is available')
Das ist der Thread:
Code: Alles auswählen
def Schlafzeit(self):
'''Dieser Thread sorgt dafür, dass der Vokabeltrainer
eine bestimmte Zeit ruht'''
hwnd = self.GetHandle()
sleep(self.cfg.ReadFloat('Schlafzeit')*60)
self.Restore()
win32gui.SetForegroundWindow(hwnd)
self.ZugVokabel()
self.Eingabe.Enable(1)
Danke
Verfasst: Sonntag 7. Januar 2007, 01:22
von gerold
basti33 hat geschrieben:es funktioniert solange das Fenster von keinem anderen überdeckt ist problemlos. Wenn ich aber z.B. den Internet Explorer darüber habe, kommt wieder besagte Fehlermeldung.
Hi basti33!
Ich konnte deinen Fehler nachvollziehen.

Aber nur, wenn ich den Internet Explorer über das Fenster gelegt habe.
Deshalb habe ich es mal mit drei Versuchen probiert:
http://paste.pocoo.org/show/583/
mfg
Gerold

Verfasst: Sonntag 7. Januar 2007, 01:33
von gerold
...hinter dem Explorer oder hinter Winamp bleibt das Fenster im Hintergrund.
Ich würde mich damit abfinden, dass es Programme gibt, die verhindern, dass ein Fenster unerwünscht nach vorne geholt wird.
Zumindest blinkt dann das Programm in der Taskleiste.
Ich glaube, das hat damit etwas zu tun, dass sich viele Leute darüber aufgeregt haben, wenn sich ein Fenster in den Vordergrund schiebt, während man gerade mit einem Programm arbeitet (z.B. etwas im Editor schreibt).
Schreibst du gerade etwas und ein Fenster kommt unerwartet in den Vordergrund, dann ist alles, was du eingibst, bis du das neue Fenster bemerkst, umsonst eingegeben worden. Das ist mir schon ziemlich oft passiert. -- Ich habe da ein tägliches Backup, das sich einfach so in den Vordergrund schiebt.

Das ist ziemlich ärgerlich.
mfg
Gerold
