2011-01-03 8 views
3

Ich implementiere eine Windows 7/Vista-ähnliche Benachrichtigungsleiste ('System Tray') Popup-Anwendung in WPF. Ich habe bisher über meine Arbeit geschrieben here (Bestimmen der Position des Benachrichtigungssymbols, Deaktivieren der Größenänderung usw.).Alternatives Ein-/Ausblenden-Fenster, wenn auf das Benachrichtigungssymbol geklickt wird

Es gibt ein Problem, das ich jedoch nicht zu meiner Zufriedenheit gelöst habe: das Fenster ausblenden, wenn das Benachrichtigungssymbol ein zweites Mal angeklickt wird. Wenn Sie beispielsweise in Vista/7 auf das Lautstärkesymbol klicken, um das Lautstärkeregler anzuzeigen, beachten Sie, dass es erneut ausgeblendet wird, wenn das Symbol ein zweites Mal angeklickt wird.

Ich handle mit dem Deaktivierungsereignis des Fensters, um das Fenster auszublenden, und das Fenster ist tatsächlich deaktiviert, wenn auf das Benachrichtigungssymbol geklickt wird. Wenn Sie jedoch auf das Benachrichtigungssymbol klicken, wird das Fenster angezeigt und aktiviert. Dies führt dazu, dass das Fenster verschwindet, während die Maus nicht gedrückt ist und wieder angezeigt wird, wenn die Maustaste losgelassen wird (das Mausklick-Ereignis wird abgeschlossen).

Mein erster Gedanke war, dass ich das MouseDown-Ereignis des Benachrichtigungssymbols verwenden könnte (ich verwende ein System.Windows.Forms.NotifyIcon) und überprüfe, ob das Fenster zu diesem Zeitpunkt sichtbar ist - wenn ja, könnte ich es interpretieren wenn der Benutzer ein zweites Mal auf das Benachrichtigungssymbol klickt, um das Fenster auszublenden. Unglücklicherweise scheint das MouseDown-Ereignis erst ausgelöst zu werden, wenn die Maus tatsächlich angeklickt wurde (mit anderen Worten, es funktioniert genauso wie das MouseClick-Ereignis). Zu diesem Zeitpunkt wurde das Fenster bereits deaktiviert und somit ausgeblendet. Dies scheint diese Lösung auszuschließen.

Meine nächste Idee (und der Ansatz, den ich verwendet habe) war, die Cursorposition zu erhalten, wenn das Fenster deaktiviert ist (GetCursorPos) und zu überprüfen, ob dieser Punkt innerhalb der Grenzen des Benachrichtigungssymbols liegt. Gleichzeitig benutze ich GetForegroundWindow auch, um das aktuell aktive Fenster zu finden - wenn das Benachrichtigungssymbol tatsächlich geklickt werden soll, sollte es entweder die Taskleiste (das Fenster der obersten Ebene mit dem Klassennamen Shell_TrayWnd) oder das Flyout des Infobereichs sein (Fenster der obersten Ebene mit dem Klassennamen NotifyIconOverflowWindow; nur Windows 7+). Kurz gesagt, wenn sich der Cursor über dem Benachrichtigungssymbol befindet und der Benachrichtigungsbereich aktiv ist, gehe ich davon aus, dass der Benutzer das Benachrichtigungssymbol mit der Maus gedrückt hat, um das Fenster auszublenden. Wenn diese Bedingungen erfüllt sind, wird das folgende MouseClick-Ereignis nicht dazu führen, dass das Fenster angezeigt/aktiviert wird.

Diese Lösung hat jedoch mindestens ein Problem: Wenn sich der Cursor über dem Benachrichtigungssymbol befindet und der Benutzer die Windows-Taste drückt, um das Startmenü zu öffnen (oder eine Windows-Tastenkombination zum Öffnen einer Anwendung verwendet), Mein Programm wird dies fälschlicherweise als ein Mausklick auf das Benachrichtigungssymbol interpretieren (weil die Taskleiste durch diese Tastaturkürzel aktiviert wird). Dies bedeutet, dass das Fenster beim nächsten Klicken auf das Benachrichtigungssymbol nicht mehr angezeigt wird. (Durch nochmaliges Klicken auf das Benachrichtigungssymbol wird es angezeigt.)

Ich hoffe, dass das, was ich geschrieben habe, einen Sinn ergibt; Wenn nicht, bin ich froh, die Situation weiter zu klären.

Ich bin interessiert zu hören, wenn jemand andere Ideen hat, wie man das löst.

Ich vermute, dass es möglicherweise nicht möglich ist: es scheint mir, dass die nativen Windows 7-Infobereich Pop-up-Anwendungen selbst eine einfache Timer-Implementierung verwenden. Wenn Sie beispielsweise bei geöffnetem Lautstärkeregler auf das Lautstärkesymbol klicken, wird der Lautstärkeregler nur geschlossen, wenn die Zeit zwischen Deaktivierung des Fensters und Mausklick weniger als etwa 2 Sekunden beträgt. Halten Sie die Maus länger auf das Symbol gedrückt und lassen Sie den Lautstärkeregler dann wieder los, auch wenn er vor dem Mouse-Down geöffnet war.

Antwort

1

So funktioniert das Lautstärkereglerfenster nicht. Es verschwindet, wenn Sie auf überall klicken, einschließlich des Benachrichtigungssymbols. Das Symbol ist nicht relevant.Dies ist ein Win32-Standardtrick, er erfasst die Maus, sodass er Klicks außerhalb seines Fensters sehen kann.

Mouse.Capture in WPF. Nicht so einfach, da es ein IInputElement anstelle eines Fensterhandle erfordert.

+0

Sie haben Recht, das Benachrichtigungssymbol ist nicht relevant zum Ausblenden des Fensters - das Fenster wird ausgeblendet, wenn das Fenster inaktiv wird (wenn es eine WM_ACTIVATE-Nachricht mit WA_INACTIVE als wParam empfängt, nehme ich an). Das Problem besteht darin, dass beim Klicken auf das Symbol das Lautstärkereglerfenster angezeigt wird/sofern/es noch nicht geöffnet ist. – Quppa

+0

Nein, die Mauserfassung ist kritisch. Es verhindert, dass der Klick einen anderen Nebeneffekt hat, als das Fenster zu schließen. Um was kämpfst du? –

+0

Welche Art von Nebenwirkungen? (Ich bin nicht sehr gut über Win32, sorry). Bedeutet dies, dass es auch Tastenbetätigungen der Tastatur erfassen muss? Mit der Alt-Tab-Taste wird beispielsweise das Fenster ebenfalls ausgeblendet. – Quppa