最小化窗口到系统托盘

问题描述 投票:0回答:2

我创建了一个 SDL2 应用程序,希望它最小化到系统托盘,而不是出现在任务栏中。

SDL_MinimizeWindow
没有做我想要的事情,它留下了任务栏图标。有没有办法通过 SDL 实现这一目标?

windows sdl-2
2个回答
5
投票

没有纯粹的SDL2方法可以做到这一点,正如Cody所说,

Shell_NotifyIcon
是创建通知区域(系统托盘)图标所需的功能。

我用来获取图标的代码是

SDL_Window *window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 200, 200, SDL_WINDOW_HIDDEN);

SDL_SysWMinfo info;
SDL_VERSION(&info.version); 

NOTIFYICONDATA icon;
if (SDL_GetWindowWMInfo(window, &info))
{
    icon.uCallbackMessage = WM_USER + 1;
    icon.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
    icon.hIcon = LoadIcon(NULL, IDI_INFORMATION);
    icon.cbSize = sizeof(icon);
    icon.hWnd = info.info.win.window;
    strcpy_s(icon.szTip, "Test tip");

    bool success = Shell_NotifyIcon(NIM_ADD, &icon);
}

这将创建一个隐藏窗口和一个图标(使用默认信息图标)。

要从 SDL 与之交互,您需要启用平台特定的窗口管理事件,具体操作如下

SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);

此后,在主事件循环中,您必须测试

SDL_SYSWMEVENT
,其中包含有关用户如何与通知区域图标交互的信息。这还会查找最小化事件并隐藏窗口,从而将其从任务栏中删除。这是在以下代码片段中实现的

SDL_Event e;
while (SDL_PollEvent(&e) != 0)
{
    switch (e.type)
    {
    case SDL_SYSWMEVENT:
        if (e.syswm.msg->msg.win.msg == WM_USER + 1)
        {
            if (LOWORD(e.syswm.msg->msg.win.lParam) == WM_LBUTTONDBLCLK)
            {
                SDL_ShowWindow(window);
                SDL_RestoreWindow(window);
            }
        }
        break;
    case SDL_QUIT:
        running = false;
        break;
    case SDL_WINDOWEVENT:
        if (e.window.event == SDL_WINDOWEVENT_MINIMIZED)
            SDL_HideWindow(window);
        break;
    }
}

0
投票

我发现最简单的方法是在隐藏时间与显示时间进行恢复。我认为在 SDL3 中,您可以使用 SyncWindow 来绕过窗口标志竞争状态。至少对于 SDL2,Colin 的解决方案并不总是有效,因为隐藏窗口在更改窗口属性/标志的竞争中失去了最小化状态。

NOTIFYICONDATA icon;
if (SDL_GetWindowWMInfo(window, &info))
{
    icon.uCallbackMessage = WM_USER + 1;
    icon.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
    icon.hIcon = LoadIcon(NULL, IDI_INFORMATION);
    icon.cbSize = sizeof(icon);
    icon.hWnd = info.info.win.window;
    strcpy_s(icon.szTip, "Test tip");

    bool success = Shell_NotifyIcon(NIM_ADD, &icon);
}

bool running = true;

while (!running ) {

SDL_Event e;
while (SDL_PollEvent(&e) != 0)
{
    switch (e.type)
    {
    case SDL_SYSWMEVENT:
        if (e.syswm.msg->msg.win.msg == WM_USER + 1)
        {
            if (LOWORD(e.syswm.msg->msg.win.lParam) == WM_LBUTTONDBLCLK)
            {
                SDL_ShowWindow(window);
                // Alternative available in SDL3 that makes the original 
                // possible.
                // SDL_SyncWindow(window);
                // SDL_RestoreWindow(window);
            }
        }
        break;
    case SDL_QUIT:
        running = false;
        break;
    case SDL_WINDOWEVENT:
        if (e.window.event == SDL_WINDOWEVENT_MINIMIZED) {
            // Now the window is restored as soon as we show it.
            SDL_RestoreWindow(window);
            // Hide the window.
            SDL_HideWindow(window);
        }
        break;
    }
}
   // Rest of render logic here.
}
© www.soinside.com 2019 - 2024. All rights reserved.