Taste abfragen ohne Fokus

Alles rund um die Programmierung mit Qt
Antworten
MTW
Beiträge: 20
Registriert: 24. Juni 2008 18:26
Wohnort: Vaihingen/Enz
Kontaktdaten:

Taste abfragen ohne Fokus

Beitrag von MTW »

Hallo,

ich habe ein Programm mit einem Tray Icon. Jetzt soll das Programm angezeigt werden wenn ich eine Taste drücke. Wie bekomme ich es aber hin dass die Taste auch ohne Fokus abgefragt wird??

Danke für die Hilfe :D
Robin
Beiträge: 3
Registriert: 14. August 2009 08:44

Beitrag von Robin »

Du kannst in deiner Betriebsumgebung (Windows, Gnome, KDE, ...) einen Shortcut (Hotkey) definieren, der Dein Programm startet.
Beim Programmstart kannst Du dann einfach abfragen, ob bereits eine Instanz Deines Programms läuft und ggf. das entsprechende Fenster aktivieren.
MTW
Beiträge: 20
Registriert: 24. Juni 2008 18:26
Wohnort: Vaihingen/Enz
Kontaktdaten:

Beitrag von MTW »

Danke schon mal, aber gibt es keine andere Möglichkeit?

Diese Lösung scheint mir nicht so befriedigend zu sein, Qt kann doch das sicher besser... :D
hasu
Beiträge: 5
Registriert: 28. Januar 2010 23:40

Beitrag von hasu »

Hi, also ich habe derzeit ein aehnliches Problem, deshalb klink ich mir hier mal ein.

Ziel ist ebenso wie bei dir das abfangen eines globalen Hotkeys, auch wenn andere Fenster im Vordergrund sind.
Folgendes habe ich mir bisher überlegt und in einem Konsolenprogramm auch schon zum laufen bekommen (Windows!):

Anlegen eines globalen Hotkeys über RegisterHotKey, dann Abfrage über eine Mainloop in der GetMessage aufgerufen wird (jeweils Win-Api).

Das wollte ich nun eigentlich auch in Qt so umsetzen, da allerdings die Mainloop fehlt müsste man anders auf das Event reagieren können.

Hatte an eine Reimplementierung von QWidget::winEvent gedacht.

Folgender Code (ich benutze Python/PyQt) führt jedoch leider nicht zum Erfolg:

Code: Alles auswählen

def winEvent( self, message ):
      if message.message == WC.WM_HOTKEY:
         print "Hotkey!"
         return True, 0
     
      else:
         print message
      return False, 0
Es werden alle möglichen Events erzeugt, jedoch keine WM_HOTKEY, obwohl selbiger korrekt registriert wurde.
Insbesondere kommen keine Events mehr an wenn ein anderes Fenster den Fokus hat.

Soviel zur Idee, vielleicht hilfts dir ja. Dann könnten wir versuchen gemeinsam rauszufinden (oder nachzufragen) wie man das in Qt korrekt realisiert.

Derselbe Code nochmal in C++ falls man damit mehr anfangen kann:

Code: Alles auswählen

bool winEvent( MSG *message, long *result )
{
   *result = 0;
   if (message.message == WM_HOTKEY)
   { cout << "Hotkey!" << endl; return true; }
   return false;
}
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Ich glaube QCoreApplication::winEventFilter() ist da eher das was Du suchst...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
hasu
Beiträge: 5
Registriert: 28. Januar 2010 23:40

Beitrag von hasu »

Funktioniert leider ebenfalls nicht, da kommen auch alle möglichen Events rein aber keine WM_HOTKEY.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Aufgrund von
The message procedure calls this function for every message received
würde ich sagen das RegisterHotkey wurde nicht korrekt aufgerufen. Denn winEventFilter wird in der Qt-Eventloop (also genau da was Du willst) aufgerufen.
Also bitte Beispielcode (c++, pyqt habe ich nicht)
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
hasu
Beiträge: 5
Registriert: 28. Januar 2010 23:40

Beitrag von hasu »

Ich bin mir ziemlich sicher dass RegisterHotKey funktioniert, aus zwei Gründen: Erstens ohne Aenderung aus der bisherigen Konsolenversion des Programmes übernommen in der das ganze tadellos funktioniert hat.
Zweitens hab ich bspw. Backspace als Hotkey festgelegt, und wenn ich während das Programm läuft woanders diese Taste benutze tut sich nichts.

Kann/will jetzt leider nicht das ganze Projekt in C++ abtippen, aber mal die relevanten Passagen (bitte nicht allzu kleinlich bei Syntaxfehlern, ich tipp das jetzt on-the-fly ein):

Code: Alles auswählen

void RegisterHotkeys( bool unregister=false )
{
   if (!unregister)
   {
      RegisterHotKey( NULL, 1, 0, VK_F9 );
      ....
      RegisterHotKey( NULL, 5, 0, VK_BACK );
   }
   else
   {
      for(int i=0; i<6; i++)
         UnregisterHotKey( NULL, i );
   }
}
wird jeweils beim Start bzw. Beenden des Programms aufgerufen.

Application sieht in Python so aus:

Code: Alles auswählen

class Application(QtGui.QApplication):
   def __init__( self, argv ):
      QtGui.QApplication.__init__(self, argv)
      
   def winEventFilter( self, msg ):
      if msg.message == WC.WM_HOTKEY:
         print "Hotkey!"
         return True, 0
      
      return False, 0
entspricht also in C++ etwa

Code: Alles auswählen

class Application : public QApplication
{
   public:
      Application( int & argc, char ** argv ) : QApplication(argc, argv) {;};
      bool winEventFilter( MSG *msg, long * result )
      {
         *result = 0;
         if (MSG.message == WM_HOTKEY)
            { cout << "Hotkey!" << endl; return true; }
         return false;
      }
};

Edit: Habe noch bisschen weiter recherchiert und bin auf QCoreApplication::setEventFilter gestoßen was eigentlich vielversprechend klingt, leider ist genau das in PyQt nicht implementiert.
(Vgl. http://www.mail-archive.com/pyqt@riverb ... 08041.html)
Nur um das schonmal vorwegzunehmen, auch wenn ich befürchte dass sich die meisten C++-treuen damit jetzt hier verabschieden werden :/
MTW
Beiträge: 20
Registriert: 24. Juni 2008 18:26
Wohnort: Vaihingen/Enz
Kontaktdaten:

Beitrag von MTW »

Hi,

bei mir funktioniert es dank der guten Tipps von hasu und Christian81, vielen Dank an dieser Stelle!
Aber jetzt zu meiner Lösung des Problems:

Ich habe wie hasu einen Hotkey registriert mit RegisterHotKey, aber habe als hWnd nicht NULL verwendet sondern das Fensterhandle, also in meinem Falle this->winId(). Dann eine App-Klasse gemacht, von QApplication abgeleitet und darin die winEventFilter funktion überschrieben.

also mit

Code: Alles auswählen

RegisterHotKey(this->winId(),1,MOD_CONTROL | MOD_ALT,'M');
hotkey registrieren, dann funktioniert das QApplication::winEventFilter:

Code: Alles auswählen

bool MPHapp::winEventFilter(MSG *message, long *result){
    *result = 0;
    if(message->message == WM_HOTKEY){
        this->aboutQt();
        return true;
    }
    else return false;

}

Ich hoffe bei dir klappt es jetzt auch. :D
hasu
Beiträge: 5
Registriert: 28. Januar 2010 23:40

Beitrag von hasu »

Oh man, danke für den Hinweis, damit funktioniert es tatsächlich.
Wär ich wohl nie drauf gekommen...
Antworten