Win32-Programmierung mit VC++ und der Win-Api

3.3 - Programm im Tray als Icon

Diesmal ein HowTo um Programme im Tray (oder nur im Tray) erscheinen zu lassen. Und jetzt kommt das wie immer: Dazu müssen wir unseren Quellcode, basierend auf dem Win-Konstrukt erweitern.

Als erstes ein wenig rumdefinieren:

// ------------ ICON_STUFF - NEW!!! ----------------
#define WM_ICONCLICK (WM_APP+0)
static UINT s_uTaskbarRestart;
HICON hIcon;
void Icon_in_Taskleiste (HWND hwnd, BOOL bAnzeigen);
// ------------- until here --------------------------

Des weiteren benötigen wir eine neue Funktion:

//------------- eine neues funktion zum anzeigen des icons in der task... dingens ------------------
void Icon_in_Taskleiste (HWND hwnd, BOOL bAnzeigen)
{
    NOTIFYICONDATA tsym; // in diese Struktur kommen die Daten des Icons
    ZeroMemory (&tsym, sizeof (NOTIFYICONDATA)); //tsym -> traysymbol

    if (bAnzeigen)
    {
        tsym.cbSize = sizeof (NOTIFYICONDATA);
        tsym.hWnd = hwnd;
        tsym.uID = IDI_ICON;
        tsym.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
        tsym.uCallbackMessage = WM_ICONCLICK;
        tsym.hIcon = hIcon;
        strcpy (tsym.szTip, "einfaches popup-help...");
        Shell_NotifyIcon (NIM_ADD, &tsym);
    }
    else
    {
        tsym.cbSize = sizeof (NOTIFYICONDATA);
        tsym.hWnd = hwnd;
        tsym.uID = IDI_ICON;
        tsym.uFlags = 0;
        Shell_NotifyIcon (NIM_DELETE, &tsym);
    }
    return;
}

Logisch! oder?

Nun muss unsere “LRESULT CALLBACK WindProc (… ” - Funktion ein wenig erweitert werden. Anstatt jede Zeile einzeln aufzuführen, stell ich gleich die ganze Funktion bereit.

//Abfragen zum im Hauptfenster befindlichen Knöpfe + Buttons etc. ...
LRESULT CALLBACK WindProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_CREATE:
        {
            // Die Message, die das System bei Neustart der Taskleiste schickt registrieren
            // Damit wir den Neustart bei evtl. Absturz des Explorers mitbekommen.
            s_uTaskbarRestart = RegisterWindowMessage (TEXT("TaskbarCreated"));

            // Aus dem Verzeichnis heraus ne icon-file laden
            // Im Verzeichnis der EXE muss sich die Icondatei "icon.ico" befinden
            hIcon = (HICON)LoadImage (hInstance, "icon1.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE);

            Icon_in_Taskleiste (hwnd, TRUE); //icon in taskleiste anzeigen
        }
        break;

        case WM_DESTROY: //wenn das programm beendet wird - wie auch immer
            Icon_in_Taskleiste (hwnd, FALSE); // Icon aus der Taskleiste entfernen
            DestroyIcon (hIcon); // Speicher freigeben
            PostQuitMessage(0); // beenden
        break;

        //Clickereignisse auf das Trayicon
        case WM_ICONCLICK:
            switch(lParam)
            {
                case WM_LBUTTONUP: // linke Maustaste
                    MessageBox (hwnd, "Maustaste links", "Taskbar Icon", MB_OK);
                    ShowWindow(hwnd,SW_SHOWNORMAL); //zeige unser programm wieder...
                break;

                case WM_RBUTTONUP: // rechte Maustaste
                    MessageBox (hwnd, "Maustaste rechts", "Taskbar Icon", MB_OK);
                break;
            }
        return 0;

        case WM_COMMAND:
        {
            switch( LOWORD( wParam ) )
            {
                case IDC_INIT:
                {
                    Init(hwnd);
                }
                break;
            }
        }
        return 0 ;

        case WM_SYSCOMMAND: //wenn unsere anwendung minimiert wurde
                            //(durch den systemknopf oben rechts ( _ O X ) )
            if(SC_MINIMIZE == wParam)
            {
                ShowWindow(hwnd,SW_HIDE); //verstecke unser programm in der taskleiste -> hide
                return TRUE;
            }
            break;

        default:
            // Wurde die Taskleiste zwischendurch neu gestartet?
            if (message == s_uTaskbarRestart)
                Icon_in_Taskleiste (hwnd, TRUE); // Icon in die Taskleiste setzen
            break;
    }
    return DefWindowProc (hwnd, message, wParam, lParam) ;
}

Hinweise zum Programm:

Beim minimieren verschwindet das Programm. Mit einem “Linksklick” auf das Symbol erscheint das Programm nach bestätigen der MessageBox wieder. die Datei icon1.ico sollte wenn möglich in dem Verzeichnis liegen, wo auch die exe ist.

Bugfix von Daniel am 16.12.2004:

Beim compilieren mit lcc-win32 gibts gar kein Icon zu sehen. Deswegen ist darauf zu achten, die entsprechende Zeile für den VC++ auszukommentieren und die Zeile für den lcc-win32 zu aktivieren. Ist im source nicht zu übersehen :-) Eine aktualisierte Version des Codes steht zum download bereit. Dank an Daniel.

Wie immer gibts den Source als kompletten Visual C++ Workspace zum download: