0

我一直想将系统托盘功能合并到我的 Flutter 应用程序中,所以我去修改启动窗口等的本机 C++ 代码,看看我是否可以挂接到它。尽管在 C++ 方面没有太多经验,但我已经能够在系统托盘中为我的应用程序创建一个图标,其菜单允许窗口在隐藏时再次显示(使用ShowWindow(hwnd, SW_HIDE);)并完全退出。

However when an option in my systray menu is selected to show the window again using ShowWindow(hwnd, SW_NORMAL);after being hidden, the app stays blank like this:

在此处输入图像描述

然后,当最终与窗口交互时,窗口的内容再次显示:

在此处输入图像描述

这是到目前为止我添加到我的 win32_window.cpp 的代码(来自默认的 Flutter 应用程序)。我没有包含整个函数,因为我认为这会使事情变得不太清楚,但我也会在本文末尾附上完整的 win32_window.cpp。Win32Window::CreateAndShow():

//Systray:
HICON hMainIcon;
hMainIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_APP_ICON));
nidApp.cbSize = sizeof(NOTIFYICONDATA); // sizeof the struct in bytes
nidApp.hWnd = (HWND) window;              //handle of the window which will process this app. messages
nidApp.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; //ORing of all the flags
nidApp.hIcon = hMainIcon; // handle of the Icon to be displayed, obtained from LoadIcon
nidApp.uCallbackMessage = WM_USER_SHELLICON;
StringCchCopy(nidApp.szTip, ARRAYSIZE(nidApp.szTip), L"All Platforms Test");
Shell_NotifyIcon(NIM_ADD, &nidApp);

return OnCreate();

Win32Window::WndProc():

if (message == WM_NCCREATE) { ... }
else if (message == WM_USER_SHELLICON) { //interacting with systray icon
    if (LOWORD(lparam) == WM_RBUTTONDOWN) { //right clicked
        POINT lpClickPoint;
        GetCursorPos(&lpClickPoint);
        hPopMenu = CreatePopupMenu();
        InsertMenu(hPopMenu,0xFFFFFFFF,MF_BYPOSITION|MF_STRING,IDM_SHOW,_T("Show"));
        InsertMenu(hPopMenu,0xFFFFFFFF,MF_BYPOSITION|MF_STRING,IDM_EXIT,_T("Quit"));
        SetForegroundWindow(window);
        TrackPopupMenu(hPopMenu,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_BOTTOMALIGN,lpClickPoint.x, lpClickPoint.y,0,window,NULL);
    }
    else if (LOWORD(lparam) == WM_LBUTTONDOWN) { //left clicked
        ShowWindow(window, SW_NORMAL);
        //LOOK: works but shows blank screen until is interacted with (mouse enters or key is pressed etc)
    }
}
else if (message == WM_COMMAND) { //if message is a command event such as a click on the exit menu option
    int wmId;
    wmId = LOWORD(wparam);

    if (wmId == IDM_EXIT) { //if quit has been pressed
        Shell_NotifyIcon(NIM_DELETE,&nidApp);
        DestroyWindow(window);
    }
    else if (wmId == IDM_SHOW) {
        ShowWindow(window, SW_NORMAL);
        //LOOK: works but shows blank screen until is interacted with (mouse enters or key is pressed etc)
    }

Win32Window::MessageHandler():

switch (message) {
  ...
  case WM_CLOSE: //stop window from closing normally, can only be closed when DestroyWindow() is run from systray
    //Hide window and continue running in background.
    ShowWindow(hwnd, SW_HIDE);
    return 0;
}

在此处链接到完整的 win32_window.cpp。

这里发生了什么?我认为使用 UpdateWindow() 会有所帮助,但后来我意识到该应用程序是在 ShowWindow() 上绘制的。我的猜测是这与 Flutter 的运行循环被阻塞有关,但我不知道下一步该去哪里,特别是考虑到我通常不涉足 C++,只是想在运行时为我的应用程序添加一个额外的功能在 Windows 上。

任何帮助将不胜感激,谢谢。

4

1 回答 1

0

好的,所以我已经弄清楚了为什么它不起作用。关闭窗口时,我不能只使用 SW_HIDE,还可以使用 SW_MINIMIZE。否则尝试重绘窗口将无法正常工作:

ShowWindow(hwnd, SW_MINIMIZE);
ShowWindow(hwnd, SW_HIDE);

之后,当显示它被绘制的窗口但不是活动窗口时,但添加 SetForegroundWindow() 修复了:

ShowWindow(window, SW_NORMAL);
SetForegroundWindow(window);

感谢大家的帮助:)

于 2021-05-20T18:58:28.310 回答