TrayIcon-Probleme



  • Ich habe eine MFC-Dialoganwendung geschrieben, die einen Dialog rechts unten auf dem Windows-Bildschirm darstellt und über Autostart geladen wird.
    Außerdem soll der Dialog zu Beginn nicht sichtbar sein und nach dem Minimieren darf der Dialog auch nicht in der Taskbar sichtbar sein. Der letzte Punkt hat mich sehr viel googlen und Nervern gekostet. Am Ende habe ich es dann so hinbekommen, weiß jetzt leider nicht mehr so genau, warum das jetzt funktioniert. Ich programmiere eigentlich schon länger mit C# und .NET 2.0 und habe damit dieselbe Anwendung in kurzer Zeit hinbekommen. Da wir aber im Betrieb noch Windows 2000 haben und gerade bei einigen wenigen .NET 1.1 Runtime installiert ist, wollte ich nicht jetzt noch auf 500 PCs die 2.0 Runtime installieren müssen, was ja ziemlich lange dauert. Daher mein Versuch mit MFC.

    Nun zu meinem eigentlichen Problem: Mein TrayIcon funktioniert sehr gut. Der Dialog startet minimiert und ist nicht in der Taskleiste sichtbar. Per Doppelklick erscheint das Dialogfenster, dem ich auch noch einen Schließ-Button (SW_HIDE) zum Minimieren gespendet habe. Außerdem gibt es ein Kontext-Menü, dass je nach Zustand des Dialogfensters, 'Anzeigen' oder 'Minimieren' anbietet. Wenn ich jetzt aber Strg-Alt-Entf drücke, den Computer sperre, oder der PC sich nach 20 Minuten selbst sperrt, und ich die Sperrung wieder aufhebe, dann ändert sich der Status des Dialoges zwar (erkennbar am Kontextmenü), das Dialogfenster selbst aber bleibt unsichtbar. Wenn ich Strg-Alt-Entf drücke und dann nur auf ESC, dann funktioniert das Programm normal.
    Kann das Sperren des PCs so etwas bewirken?

    Danke


  • Mod

    hmbreit schrieb:

    Nun zu meinem eigentlichen Problem: Mein TrayIcon funktioniert sehr gut. Der Dialog startet minimiert und ist nicht in der Taskleiste sichtbar. Per Doppelklick erscheint das Dialogfenster, dem ich auch noch einen Schließ-Button (SW_HIDE) zum Minimieren gespendet habe. Außerdem gibt es ein Kontext-Menü, dass je nach Zustand des Dialogfensters, 'Anzeigen' oder 'Minimieren' anbietet. Wenn ich jetzt aber Strg-Alt-Entf drücke, den Computer sperre, oder der PC sich nach 20 Minuten selbst sperrt, und ich die Sperrung wieder aufhebe, dann ändert sich der Status des Dialoges zwar (erkennbar am Kontextmenü), das Dialogfenster selbst aber bleibt unsichtbar. Wenn ich Strg-Alt-Entf drücke und dann nur auf ESC, dann funktioniert das Programm normal.
    Kann das Sperren des PCs so etwas bewirken?

    Ich verstehe Dein Problem nicht ganz. Was passiert oder geht nicht mehr nach dem Sperren des PCs? Wird der Zustand Deiner Applikation nicht mehr erkannt? Denkt er er ist versteckt, ist aber sichtbar?

    Die Frage ist wie Du diesen Status feststellst. Auf welche Nachrichten reagierst Du wie?



  • Also, nach dem Sperren und wieder entsperren, passiert beim Doppelklick auf das Trayicon folgendes: Der Dialog wird nicht angezeigt.
    In der WindowProc habe ich folgende Abfrage:

    LRESULT CComputerInfo_MFCDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
    {
     if(message == MYWM_NOTIFYICON){
      switch (lParam){
         case WM_LBUTTONDBLCLK:
    	switch (wParam)	{
    	    case IDR_MAINFRAME:
                 {	
    	     m_visible = TRUE;
                  ShowWindow(SW_SHOW);
                  SetForegroundWindow();
                  SetFocus();
                  return TRUE;
    	     break;
                  }
    			}
    	    break;
          case WM_RBUTTONUP:
          {
           CMenu Menu;
           Menu.CreatePopupMenu();
           if( !IsWindowVisible() )
              Menu.AppendMenu(MF_ENABLED,ID_OEFFNEN, _T("Dialog &anzeigen"));
           else
              Menu.AppendMenu(MF_ENABLED,ID_MIN, _T("Dialog &minimieren"));
           Menu.AppendMenu(MF_ENABLED,ID_INFO, _T("Über &Dialog"));
           Menu.AppendMenu(MF_SEPARATOR);
           Menu.AppendMenu(MF_ENABLED,ID_SCHLIESSEN, _T("Dialog &beenden"));
           CPoint pt;
           GetCursorPos(&pt);
           SetForegroundWindow();
           Menu.TrackPopupMenu(TPM_RIGHTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,pt.x,pt.y,this);
           return TRUE;
           break;
           }
         }	
    
       return CDialog::WindowProc(message, wParam, lParam);
    }
    

    und nach besagtem Doppelklick auf das Trayicon zeigt das Menü 'Info minimieren', IsWindowVisible() muss also TRUE sein, der Dialog ist aber nicht sichtbar.

    Die relevanten Zeilen im OnInitDialog():

    ShowWindow(SW_HIDE);
     m_TrayMenu.LoadMenu(IDR_MENU1);
     InsertMenu(m_TrayMenu, -1, MF_BYPOSITION, SWM_HIDE, _T("Hide"));
     ModifyStyleEx( WS_EX_APPWINDOW, 0 );
     return TRUE;
    

    Das TrayMenu habe ich in der WindowProc noch einmal überschrieben, da ich es dynamisch machen wollte und ich nicht wusste, wie das nur dynamisch geht.

    und dann noch:

    void CComputerInfo_MFCDlg::OnWindowPosChanging(WINDOWPOS* lpwndpos)
    {    
      //Dialogfeldgröße ermitteln
        RECT rc;
        GetClientRect(&rc);
    
        if (lpwndpos->cx = -1) if (lpwndpos->cy = -1) // is init time 
        { 
    
            lpwndpos->x = ScreenWidth - rc.right; // Screenbreite - Dialogbreite 
            lpwndpos->y = ScreenHeight - rc.bottom; // Screenhöhe - Dialoghöhe 
        }
        if(!m_visible)
        {
            lpwndpos->flags &= ~SWP_SHOWWINDOW;
        }
    
        CDialog::OnWindowPosChanging(lpwndpos);
    }
    

    Danke für die Hilfe.


  • Mod

    Was sagt Spy++ in diesem Fall?

    Warum benutt Du OnWindowPosChaning und nicht die einfacheren Nachrichten wie WM_SIZE und WM_SHOW?

    BTW: Warum baust Du diesen Code in WindowProc ein und nutzt nicht den normalen Weg über Handler?
    Das macht den Code nur unübersichtlich!



  • Was sagt Spy++ in diesem Fall?

    Ich habe Spy++ noch nie verwendet und weiß auch nicht, für was dieses Tool gut ist. Was kann ich in diesem Fall damit herausbekommen?
    Außerdem arbeite ich mit VS 2005 Prof und da finde ich kein Spy++.

    Warum benutt Du OnWindowPosChaning und nicht die einfacheren Nachrichten wie WM_SIZE und WM_SHOW?

    OnWindowPosChanging benutze ich, weil ich das Dailogfeld rechts unten auf dem Desktop haben will und ~SWP_SHOWWINDOW habe ich irgendwo im Netz gefunden. Aber, wie gesagt, ich bin nicht so gut in MFC und ich habe sehr viel Code kopiert und gelöscht bis es endlich funktionierte (bis auf: s. Beitragstitel ) ohne aber dabei alles voll zu verstehen. Natürlich kann ich jetzt die WinApi und MFC studieren und dann irgendwann vielleicht auch alles verstehen. Nur, ich habe leider nicht mehr genug Zeit.

    BTW: Warum baust Du diesen Code in WindowProc ein und nutzt nicht den normalen Weg über Handler?

    @Martin, danke für deine Hilfe, aber kannst du mir kurz erklären, wie dieser normale Weg ausschauen soll?

    Danke


Anmelden zum Antworten