Anwendung einfach nur in Sys-Tray



  • Hallo,

    Ich habe folgendes Problem:

    - Ich möchte meine Anwendung minimiert starten und dabei ein Tray-Icon mit Menü anzeigen.
    - Bei einem Doppelklick soll die Anwendung angezeigt werden.
    - Durch die Minimieren-Schaltfläche soll die Anwendung wieder im Tray verschwinden.
    - Wenn Windows die Message WM_DEVICECHANGE sendet, soll eine Sprechblase erscheinen und eine Funktion aufgerufen werden.

    Ich habe diese Anleitungen durch:
    http://www.codeproject.com/shell/systemtray.asp
    --> Keine Ahnung, verstehe ich nicht. In der Erklärung wird MFC und Nicht-MFC ständig vermischt.

    http://www.c-plusplus.net/forum/viewtopic.php?t=39038
    und
    http://www.c-plusplus.net/forum/viewtopic.php?t=39045
    --> Verstehe ich, konnte ich auch einbauen.

    Mein Problem ist jedoch:
    1. Verschwindet das Menü vom Tray-Icon nicht, wenn es den Focus verliert.
    2. Wie baue ich einen Balloon-Tipp (Sprechblase) ein?

    Kann mir bitte jemand das ganze mal so erklären, dass es auch ein Nicht-C++-Freak versteht?

    mfg
    trequ



  • Zu 1.: Das Problem hatte ich auch und konnte es nur dadurch lösen, dass ich ein Menü komplett mit der WinAPI aufgebaut habe.



  • the_alien schrieb:

    Zu 1.: Das Problem hatte ich auch und konnte es nur dadurch lösen, dass ich ein Menü komplett mit der WinAPI aufgebaut habe.

    Was soll mir als Anfänger diese Aussage sagen?





  • trequ schrieb:

    Was soll mir als Anfänger diese Aussage sagen?

    Das du nachguckst wie man ein Menü mit der WinAPI erstellt?

    by designs Lösung ist natürlich sehr viel eleganter 🙂
    Danke dafür an der Stelle.



  • the_alien schrieb:

    trequ schrieb:

    Was soll mir als Anfänger diese Aussage sagen?

    Das du nachguckst wie man ein Menü mit der WinAPI erstellt?

    by designs Lösung ist natürlich sehr viel eleganter 🙂
    Danke dafür an der Stelle.

    Ja ok - Aber das Menü kann ich erst schreiben und testen, wenn ich es geschaft habe, die Anwendung zum Tray-Icon zu minimieren.

    mfg
    trequ



  • Ich hatte das so verstanden, dass du damit kein Problem mehr hast. Immerhin tauchte es in deinen 2 Fragen nicht auf 😉

    Wo ist das Problem mit dem Tray Icon?



  • Hm....

    ok, habe ich wirklich nicht dazugesagt - sorry.

    Ich habe keine Probleme damit ein Tray-Icon zu erstellen.

    Ich muss die Anleitung (siehe oben) aber so ändern, dass:

    - Die Anwendung beim Start nur als Tray-Icon läuft und das Dialogfenster unsichtbar ist. (Funktioniert ShowWindow(SW_HIDE) nicht in OnInitDialog()?)

    - Die Anwendung beim Doppelklick auf das Tray-Icon sichtbar wird.
    Ich hab jetzt das gemacht, nur muss da jetzt noch das Menü für die rechte Maustaste rein:

    LRESULT CSCMPCCardLogoInstallerDlg::OnTrayNotification(WPARAM wp, LPARAM lp) 
    { 
        switch (lp) 
        { 
        case WM_LBUTTONDBLCLK: 
            ShowWindow(SW_SHOW); 
            return 0;
        } 
    return 0; 
    }
    

    - Die Anwendung weiterläuft, wenn der Benutzer auf das X oben rechts klickt
    (ok, man kann ja CDialog::OnOK() überschreiben)

    - Dass Tray-Icon muss verschwinden, wenn die Anwendung wirklich beendet wird
    (über "Rechtsklick auf Tray-Icon" -> "Exit") Ist das OnDestroy()?

    mfg
    trequ



  • trequ schrieb:

    - Die Anwendung beim Start nur als Tray-Icon läuft und das Dialogfenster unsichtbar ist. (Funktioniert ShowWindow(SW_HIDE) nicht in OnInitDialog()?)

    Nein, in OnInitDialog() existiert das Fenster noch nicht, ergo kannst du es auch nicht verstecken. Du musst das in OnPaint() aufrufen.

    trequ schrieb:

    - Die Anwendung beim Doppelklick auf das Tray-Icon sichtbar wird.
    Ich hab jetzt das gemacht, nur muss da jetzt noch das Menü für die rechte Maustaste rein:

    LRESULT CSCMPCCardLogoInstallerDlg::OnTrayNotification(WPARAM wp, LPARAM lp) 
    { 
        switch (lp) 
        { 
        case WM_LBUTTONDBLCLK: 
            ShowWindow(SW_SHOW); 
            return 0;
        } 
    return 0; 
    }
    

    Das funktioniert aber soweit?

    trequ schrieb:

    - Die Anwendung weiterläuft, wenn der Benutzer auf das X oben rechts klickt
    (ok, man kann ja CDialog::OnOK() überschreiben)

    Entweder OnOK() überschreiben oder WM_CLOSE (glaube ich) abfangen

    trequ schrieb:

    - Dass Tray-Icon muss verschwinden, wenn die Anwendung wirklich beendet wird
    (über "Rechtsklick auf Tray-Icon" -> "Exit") Ist das OnDestroy()?

    Ich muss nichts extra machen, damit das Tray Icon verschwindet. Sobald ich meine Anwendung beende ist das Icon auch weg. (Win XP & 2000)



  • Hallo,

    ok, danke.
    2 Probleme habe ich jedoch damit:

    1. Wenn ich ShowWindow(SW_HIDE) in OnPaint reinschreibe, sehe ich mein Fenster gar nicht mehr.
    Ich habe das Tray-Icon in OnInitDialog erstellt.
    In OnPaint habe ich dann ShowWindow(SW_HIDE) geschrieben.
    Jetzt ist das Fenster nicht sichtbar - wie es sein sollte - allerdings wird es bei einem Klick auf das Tray für nur 1ms angezeigt und sofort wieder augebelendet.

    2. Wenn ich meine Anwendung beende, wird das Tray-Icon ungültig.
    Es wird aber nicht sofort ausgeblendet. Es verschwindet erst, wenn ich mit der Maus darauf zeige.

    Mein Icon verschwindet dagegen sofort, wenn ich es per C++ Code entferne.
    Wenn ich es in OnDestroy entferne, funktioniert es so wie es soll.

    Ich muss jetzt meine Anwendung nur noch zu 4 Dingen bewegen, dann habe ich alles:
    1. Balloon Tips (Sprechblasen) einbauen
    --> Gar keine Idee. Ich kann zwar eine MessageBox erzeugen, wenn mein Ereigniss eintritt, aber wie mache ich diese Sprechblasen?
    2. Beim Start ShowWindow(SW_HIDE) einbauen
    --> Siehe oben
    3. Beim klick auf das X ShowWindow(SW_HIDE) einbauen
    --> Wie fange ich das X ab?
    4. Ein Menü in das Tray-Icon einbauen.
    --> Ich kann auf einen Rechtsklick reagieren, nur wie zeige ich dann das Menü an?
    Geht das mit dem Code von http://support.microsoft.com/kb/q135788/ ?

    mfg
    trequ



  • trequ schrieb:

    Hallo,

    ok, danke.
    2 Probleme habe ich jedoch damit:

    1. Wenn ich ShowWindow(SW_HIDE) in OnPaint reinschreibe, sehe ich mein Fenster gar nicht mehr.
    Ich habe das Tray-Icon in OnInitDialog erstellt.
    In OnPaint habe ich dann ShowWindow(SW_HIDE) geschrieben.
    Jetzt ist das Fenster nicht sichtbar - wie es sein sollte - allerdings wird es bei einem Klick auf das Tray für nur 1ms angezeigt und sofort wieder augebelendet.

    Stimmt, hatte ein leeres Dialogfeld erstellt und das dann direkt ausgeblendet. Alles was ich an Fenstern brauchte hab ich dann extra aufgerufen.

    trequ schrieb:

    2. Wenn ich meine Anwendung beende, wird das Tray-Icon ungültig.
    Es wird aber nicht sofort ausgeblendet. Es verschwindet erst, wenn ich mit der Maus darauf zeige.

    Mein Icon verschwindet dagegen sofort, wenn ich es per C++ Code entferne.
    Wenn ich es in OnDestroy entferne, funktioniert es so wie es soll.

    Gut ein Problem weniger

    trequ schrieb:

    1. Balloon Tips (Sprechblasen) einbauen
    --> Gar keine Idee. Ich kann zwar eine MessageBox erzeugen, wenn mein Ereigniss eintritt, aber wie mache ich diese Sprechblasen?

    Keine Ahnung, sorry.

    trequ schrieb:

    2. Beim Start ShowWindow(SW_HIDE) einbauen
    --> Siehe oben

    Weiss ich ehrlich gesagt gerade auch nicht. Aber vielleicht kannst du es so umbauen, dass du es so wie ich (s.o.) machst.

    trequ schrieb:

    3. Beim klick auf das X ShowWindow(SW_HIDE) einbauen
    --> Wie fange ich das X ab?

    WindowProc überschreiben und WM_CLOSE abfangen.

    trequ schrieb:

    4. Ein Menü in das Tray-Icon einbauen.
    --> Ich kann auf einen Rechtsklick reagieren, nur wie zeige ich dann das Menü an?
    Geht das mit dem Code von http://support.microsoft.com/kb/q135788/ ?

    mfg
    trequ

    Ja.



  • Zu 1) Das liegt daran, dass die Message OnPaint() dein Dialog neu zeichnet und dadurch oft hintereinander aufgerufen wird (Vielleicht sekündlich). Und wenn jetzt nun ShowWindow(SW_HIDE); drinsteht, wird auch dieser Code jederzeit aufgerufen. Schreib ShowWindow() besser in die InitDialog()...

    Zu 2) Ruf in dem Destruktor einfach NIM_DELETE auf

    NOTIFYICONDATA nid; 
    .
    .
    .
    Shell_NotifyIcon(NIM_DELETE, &nid);
    

    Zu Sprechblasen) Den Code müsstest du dann bei dir einbauen:
    http://www.codeproject.com/miscctrl/pptooltip.asp

    X abfangen) Dazu musst du die OnCancel() abfangen.

    Menue) Du holst dir die Koordinaten der Maus und erzeugst dort das Menue...

    Gruß
    :: NoName ::

    [edit] Bin wohl eine Minute zu spät 😃 [/edit]



  • Doppelpost



  • Hallo,

    zu 1. (Dialog am Start verbergen):
    Geht jetzt:
    Ich rufe in OnInitDialog einen Timer mit der Zeit 1 auf, der dann ShowWindow auf SW_HIDE setzt.

    zu 2. (Balloon-Tip):
    Bei den ganzen CodeGuru Klassen blicke ich absolut nicht durch.
    In der MSDN steht etwas von CToolTipCtrl. Damit muss es doch machbar sein.
    Die Downloads von CodeGuru lassen sich nicht mal kompilieren, da gibt es erst mal 7 Fehler. --> ???

    zu 3. (x abfangen):
    Geht jetzt mit OnClose

    zu 4. (Menü)
    Mit welchen Code erstellt man ein Menü?
    Ich kann es in den Resourcen ja erstellen. Dann hat es den Namen IDR_TRAYMENUE.
    Was schreibe ich jetzt in meine Funktion, damit das Menü dann so eingeblendet wird, dass es beim Verlust des Focus wieder verschwindet?
    Ich verstehe das Beispiel aus der MSDN (siehe oben) einfach nicht.

    mfg
    trequ



  • SetForegroundWindow(hDlg);
    // Display the menu
    TrackPopupMenu(   hSubMenu,        //Handle zum Menü
                      TPM_RIGHTBUTTON, 
                      pt.x,            //aktuelle Mausposition holen
                      pt.y,            //und übergeben
                      0,
                      hDlg,
                      NULL);
    
    PostMessage(hDlg, WM_NULL, 0, 0);
    

    Für weitere Informationen müsstest du in die MSDN gucken, geht schneller als zu posten 😉
    Wenn Fragen bestehen immer gerne.

    PS: Hab mal kurz CToolTipCtrl angeguckt. War mir jetzt aber auf die schnelle zu verworren. Müssteste nur mal in der MSDN die Member Funktionen angucken, dann kriegste auch das hin.



  • Hallo,

    SetForegroundWindow(hDlg); 
    		TrackPopupMenu(	hSubMenu,        //Handle zum Menü 
    						TPM_RIGHTBUTTON, 
    						pt.x,            //aktuelle Mausposition holen 
    						pt.y,            //und übergeben 
    						0, 
    						hDlg, 
    						NULL); 
    
    		PostMessage(hDlg, WM_NULL, 0, 0);
    

    Was ich nicht verstehe:

    - Was ist hDlg? Es wird gar kein Dialog angezeigt...? Was soll ich da übergeben?
    - Wie komme ich an die position der Maus ran? für pt.y und pt.x?
    - Wie erzeuge ich das Handle zum Menü? Wenn ich
    HMENU hSubMenu = CreatePopupMenu();
    schreibe, ist zwar der Fehler weg, aber ich muss ja irgendwie auf IDR_TRAYMENUE verweisen...

    mfg
    trequ



  • Das müsste so gehen

    CPoint pt;
    
    GetCursorPos(&pt); 
    ClientToScreen(&pt);
    
    CMenu menu;
    menu.LoadMenu(IDR_DEIN_MENUE);
    menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, NULL);
    

    Hoffe konnte dir helfen...

    Gruß
    :: NoName ::



  • trequ schrieb:

    - Was ist hDlg? Es wird gar kein Dialog angezeigt...? Was soll ich da übergeben?

    Nicht angezeigt, aber erst ist ja vorhanden!


Anmelden zum Antworten