[gelöst] Konsolenanwendung im Tray verschwinden lassen und bei Klick wiederherstellen
-
Hallo zusammen,
ein Konsolenprogramm zu verstecken und ein Tray-Icon anzulegen, ist ja nicht sonderlich schwer. Dazu habe ich auch hier mit der Suchfunktion im Forum und auch mit google einiges gefunden. Jetzt würde ich das Fenster allerdings gerne nicht nur automatisch sondern auch durch einen Klick aufs Tray-Icon wiederherstellen können. Mein bisheriger Versuch sieht wie folgt aus, funktioniert jedoch nicht.
#if !defined _WIN32_WINNT # define _WIN32_WINNT 0x0500 #endif #include <windows.h> #include <shellapi.h> #include <iostream> NOTIFYICONDATA Tray; HWND consoleWindow; HANDLE threadHandle; volatile bool quitMessageThread( false ); volatile bool inTray( false ); bool ToTray( bool hide = true ) { if ( !Shell_NotifyIcon( NIM_ADD, &Tray ) ) { std::cerr << "Shell_NotifyIcon( NIM_ADD, &Tray ) gescheitert.\n"; return false; } inTray = true; if ( hide ) ShowWindow( consoleWindow, SW_HIDE ); std::cout << "Fenster in den Tray minimiert\n"; return true; } bool FromTray() { if ( !inTray ) return false; if ( !Shell_NotifyIcon( NIM_DELETE, &Tray ) ) { std::cerr << "Shell_NotifyIcon( NIM_DELETE, &Tray ) gescheitert.\n"; return false; } ShowWindow( consoleWindow, SW_SHOW ); std::cout << "Fenster aus dem Tray wiederhergestellt.\n"; return true; } DWORD WINAPI MessageThreadFunc(LPVOID lpArg) { MSG msg; while( !quitMessageThread ) { if ( PeekMessage( &msg, consoleWindow, 0, 0, PM_REMOVE ) ) { std::cout << "Eine Message ist reingerauscht.\n" ; if ( msg.message == WM_USER ) { std::cout << "Jemand hat das Tray-Icon angeklickt.\n" ; FromTray(); } TranslateMessage(&msg); DispatchMessage(&msg); } else { std::cout << ".\n" ; Sleep( 200 ); } } return 0; } bool Init() { static int arg( 0 ); DWORD ThreadId; threadHandle = CreateThread( NULL, 0, MessageThreadFunc, &arg, 0, &ThreadId ); if ( threadHandle == NULL ) { std::cerr << "Konnte den Thread nicht erzeugen.\n"; return false; } else std::cout << "Thread erzeugt.\n"; consoleWindow = GetConsoleWindow(); if ( !consoleWindow ) { std::cerr << "GetConsoleWindow() gescheitert.\n"; return false; } Tray.cbSize = sizeof( Tray ); Tray.hIcon = LoadIcon( NULL, IDI_APPLICATION ); Tray.hWnd = consoleWindow; strcpy_s( Tray.szTip, "Traytest" ); Tray.uCallbackMessage = WM_USER; Tray.uFlags=NIF_ICON | NIF_TIP | NIF_MESSAGE; Tray.uID = 1; return true; } bool Quit() { quitMessageThread = true; return WaitForSingleObject( threadHandle, INFINITE ) == 0; } int main() { if ( !Init() ) return 1; std::cout << "Warte 2 Sekunden.\n"; Sleep( 2000 ); if ( !ToTray( false ) ) return 2; std::cout << "Warte 4 Sekunden im Tray.\n"; Sleep( 4000 ); if ( !FromTray() ) return 3; std::cout << "Bin wieder da.\n"; Sleep( 1000 ); std::cout << "Beende Message-Thread.\n"; if ( !Quit() ) return 4; Sleep( 1000 ); std::cout << "Beende Programm.\n"; Sleep( 1000 ); }
Können Konsolenanwendungen grundsätzlich keine Messages empfangen (ausser den paar, für die man mit SetConsoleCtrlHandler einen Handler einsetzen kann)?
Wenn doch, wie mache ich es richtig? Geht es vielleicht über ein Callback? Meinen pollenden Thread finde ich erstens nicht gerade hübsch, und zweitens empfängt er überhaupt keine Messages.Gruß
Dobi
-
Hab's nun. Wenn ich in einem Thread ein normales Fenster mit CreateWindow erzeuge und unsichtbar mache, kann ich in dessen WndProc die Messages empfangen und ganz normal drauf reagieren.
-
-
Ah, danke, funktioniert.