繁体   English   中英

C++ 按下关闭时:最小化到系统托盘并继续运行

[英]C++ when pressing close: minimize to system tray and keep running

我在 c++ 中有一个 windows 的应用程序,当用户按下关闭按钮时,它应该最小化命令行的 window。 它不应该再出现在任务栏中,并且在系统托盘中有一个图标。 我的意思是:当用户按下关闭按钮时,程序应该只像我描述的那样“隐藏”。

我只能设法让程序在运行时在托盘中有一个图标,但不能让它在按下 x 时保持运行

感谢帮助!

到目前为止,这是我的代码:

#include <iostream>
#include <Windows.h> // needed for console window and system tray functionality

// global variables
NOTIFYICONDATA trayIcon; // structure for the tray icon
HWND hwnd = GetConsoleWindow(); // handle to the console window

// function prototypes
void minimizeToTray(); // function to minimize the console window to the system tray

int main()
{
    // set up the tray icon
    trayIcon.cbSize = sizeof(NOTIFYICONDATA);
    trayIcon.hWnd = hwnd;
    trayIcon.uID = 1;
    trayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    trayIcon.hIcon = (HICON)LoadImage(NULL, "icon.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); // specify the icon file
    trayIcon.uCallbackMessage = WM_USER + 1; // message identifier for tray icon clicks
    trayIcon.uVersion = NOTIFYICON_VERSION_4;
    strcpy_s(trayIcon.szTip, "Program Running");

    // add the tray icon to the system tray
    Shell_NotifyIcon(NIM_ADD, &trayIcon);

    std::cout << "Program running..." << std::endl;

    // set up a message loop to handle tray icon clicks and window messages
    MSG msg;
    while (true) // infinite loop
    {
        // check for messages
        while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE))
        {
            // if the user clicks the close button, minimize the window to the tray
            if (msg.message == WM_CLOSE)
            {
                minimizeToTray();
                continue; // skip the rest of the message loop
            }

            // if the user clicks the tray icon, restore the window
            if (msg.message == WM_USER + 1)
            {
                ShowWindow(hwnd, SW_RESTORE);
            }

            // pass the message to the default window procedure
            DispatchMessage(&msg);
        }

        // do other tasks here
    }

    // remove the tray icon before exiting the program
    Shell_NotifyIcon(NIM_DELETE, &trayIcon);

    return 0;
}

// function to minimize the console window to the system tray
void minimizeToTray()
{
    // hide the console window
    ShowWindow(hwnd, SW_HIDE);

    // update the tray icon
    trayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    Shell_NotifyIcon(NIM_MODIFY, &trayIcon);
}

当用户“关闭”window 时,它应该只是隐藏而不是完全关闭,就像 ms teams 或 discord 那样

测试你的代码后,它肯定失败了。 它无法获得消息 WM_CLOSE。 正如 Hans Passant 所说,您可以使用SetConsoleCtrlHandler()连接到控制台接收信号。

这是我的代码。 它运行良好。 它使用ShellExecuteW() API 重启程序实现最小化。 设置SW_MINIMIZE ,它将在任务栏中最小化。 设置SW_HIDE ,它将在系统托盘中最小化。 但无法再次打开。

#include <Windows.h> 
#include <string.h>     
#include <stdlib.h>     
#include <stdio.h>      
#include <errno.h>      
#include <iostream>


NOTIFYICONDATA trayIcon; 
HWND hwnd = GetConsoleWindow(); 

BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
    char mesg[128];
    switch (CEvent)
    {

    case CTRL_C_EVENT:
        MessageBox(NULL,
            L"CTRL+C received!", L"CEvent", MB_OK);
        break;
    case CTRL_BREAK_EVENT:
        MessageBox(NULL,
            L"CTRL+BREAK received!", L"CEvent", MB_OK);
        break;
    case CTRL_CLOSE_EVENT:
      
        ShellExecuteW(NULL, L"open", L"yourexe.exe", NULL, NULL, SW_MINIMIZE);

        break;
    case CTRL_LOGOFF_EVENT:
        MessageBox(NULL,
            L"User is logging off!", L"CEvent", MB_OK);
        break;
    case CTRL_SHUTDOWN_EVENT:
        MessageBox(NULL,
            L"User is logging off!", L"CEvent", MB_OK);
        break;
    }
    return TRUE;
}

int main()
{

    trayIcon.cbSize = sizeof(NOTIFYICONDATA);
    trayIcon.hWnd = hwnd;
    trayIcon.uID = 1;
    trayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    trayIcon.hIcon = (HICON)LoadImage(NULL, L"icon1.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); 
    trayIcon.uCallbackMessage = WM_USER + 1; 
    trayIcon.uVersion = NOTIFYICON_VERSION_4;
   
    Shell_NotifyIcon(NIM_ADD, &trayIcon);
    std::cout << "Program running..." << std::endl;
    
    MSG msg;
    if (SetConsoleCtrlHandler(
        (PHANDLER_ROUTINE)ConsoleHandler, TRUE) == FALSE)
    {
     
        printf("Unable to install handler!\n");
        return -1;
    }
    while (true) 
    {
        
        while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE))
        {
           
            if (msg.message == WM_CLOSE)
            {          
                continue; 
            }
            
            if (msg.message == WM_USER + 1)
            {
                ShowWindow(hwnd, SW_RESTORE);
            }
            
            DispatchMessage(&msg);
        }       
       
    }
   
    Shell_NotifyIcon(NIM_DELETE, &trayIcon);
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM