ShowWindow() 显示空白应用程序,直到在 C++ 中从系统托盘恢复后通过 mouse/keyboard 进行交互 - Flutter App
ShowWindow() showing blank app until is interacted with via mouse/keyboard after restoring from systray in C++ - Flutter App
我一直想将系统托盘功能合并到我的 Flutter 应用程序中,所以我去修改启动 window 等的本机 C++ 代码,看看我是否可以挂钩它。
尽管之前没有太多 C++ 经验,但我已经能够在系统托盘中为我的应用程序创建一个图标,该菜单允许 window 在隐藏时再次显示(使用 ShowWindow(hwnd, SW_HIDE);
)并退出完全。
然而,当我的系统托盘菜单中的一个选项被选中以在隐藏后使用 ShowWindow(hwnd, SW_NORMAL);
再次显示 window 时,应用程序保持空白,如下所示:
然后,当最终与window进行交互时,window的内容再次显示:
这是我到目前为止添加到 win32_window.cpp 的代码(来自默认的 Flutter 应用程序)。我没有包含完整的功能,因为我认为这会使事情变得不那么清晰,但我也会在这个 post 的末尾附上完整的 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;
}
Link to full win32_window.cpp here.
这是怎么回事?我认为使用 UpdateWindow() 会有所帮助,但后来我意识到该应用程序无论如何都是在 ShowWindow() 上绘制的。我的猜测是,这与 Flutter 的 运行 循环被阻塞有关,但我不知道下一步该去哪里,特别是考虑到我通常不涉足 C++,只是想添加一个额外的功能运行在 Windows 时我的应用程序。
非常感谢任何帮助,谢谢。
好的,我已经弄清楚为什么它不起作用了。关闭 window 时,我不能只使用 SW_HIDE,还可以使用 SW_MINIMIZE。否则尝试重绘 window 将无法正常工作:
ShowWindow(hwnd, SW_MINIMIZE);
ShowWindow(hwnd, SW_HIDE);
在那之后,当显示 window 时它被绘制但不是活动的 window,但是添加 SetForegroundWindow() 修复了:
ShowWindow(window, SW_NORMAL);
SetForegroundWindow(window);
感谢大家的帮助:)
我一直想将系统托盘功能合并到我的 Flutter 应用程序中,所以我去修改启动 window 等的本机 C++ 代码,看看我是否可以挂钩它。
尽管之前没有太多 C++ 经验,但我已经能够在系统托盘中为我的应用程序创建一个图标,该菜单允许 window 在隐藏时再次显示(使用 ShowWindow(hwnd, SW_HIDE);
)并退出完全。
然而,当我的系统托盘菜单中的一个选项被选中以在隐藏后使用 ShowWindow(hwnd, SW_NORMAL);
再次显示 window 时,应用程序保持空白,如下所示:
然后,当最终与window进行交互时,window的内容再次显示:
这是我到目前为止添加到 win32_window.cpp 的代码(来自默认的 Flutter 应用程序)。我没有包含完整的功能,因为我认为这会使事情变得不那么清晰,但我也会在这个 post 的末尾附上完整的 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;
}
Link to full win32_window.cpp here.
这是怎么回事?我认为使用 UpdateWindow() 会有所帮助,但后来我意识到该应用程序无论如何都是在 ShowWindow() 上绘制的。我的猜测是,这与 Flutter 的 运行 循环被阻塞有关,但我不知道下一步该去哪里,特别是考虑到我通常不涉足 C++,只是想添加一个额外的功能运行在 Windows 时我的应用程序。
非常感谢任何帮助,谢谢。
好的,我已经弄清楚为什么它不起作用了。关闭 window 时,我不能只使用 SW_HIDE,还可以使用 SW_MINIMIZE。否则尝试重绘 window 将无法正常工作:
ShowWindow(hwnd, SW_MINIMIZE);
ShowWindow(hwnd, SW_HIDE);
在那之后,当显示 window 时它被绘制但不是活动的 window,但是添加 SetForegroundWindow() 修复了:
ShowWindow(window, SW_NORMAL);
SetForegroundWindow(window);
感谢大家的帮助:)