From c511354c8f77f05e31709952c0712fc9ac7c0f2c Mon Sep 17 00:00:00 2001 From: l619534951 <619534951@qq.com> Date: Sat, 28 Oct 2023 00:01:05 +0800 Subject: [PATCH 1/4] [windows] feat: Add onWindowsTaskbarCreated Method. --- example/lib/pages/home.dart | 6 ++++++ example/windows/runner/Runner.rc | 10 +++++----- lib/src/tray_listener.dart | 3 +++ lib/src/tray_manager.dart | 4 ++++ windows/tray_manager_plugin.cpp | 12 ++++++++++++ 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/example/lib/pages/home.dart b/example/lib/pages/home.dart index c0a9f65..4cf27b7 100644 --- a/example/lib/pages/home.dart +++ b/example/lib/pages/home.dart @@ -295,4 +295,10 @@ class _HomePageState extends State with TrayListener { text: '${menuItem.toJson()}', ); } + + @override + void onWindowsTaskbarCreated() { + debugPrint('onWindowsTaskbarCreated'); + _handleSetIcon(_iconType); + } } diff --git a/example/windows/runner/Runner.rc b/example/windows/runner/Runner.rc index 4368a4b..890af28 100644 --- a/example/windows/runner/Runner.rc +++ b/example/windows/runner/Runner.rc @@ -60,14 +60,14 @@ IDI_APP_ICON ICON "resources\\app_icon.ico" // Version // -#ifdef FLUTTER_BUILD_NUMBER -#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD #else -#define VERSION_AS_NUMBER 1,0,0 +#define VERSION_AS_NUMBER 1,0,0,0 #endif -#ifdef FLUTTER_BUILD_NAME -#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION #else #define VERSION_AS_STRING "1.0.0" #endif diff --git a/lib/src/tray_listener.dart b/lib/src/tray_listener.dart index f5d26f2..bf92f29 100644 --- a/lib/src/tray_listener.dart +++ b/lib/src/tray_listener.dart @@ -12,4 +12,7 @@ abstract class TrayListener { void onTrayIconRightMouseUp() {} void onTrayMenuItemClick(MenuItem menuItem) {} + + /// Emitted when windows taskbar created, such as explorer.exe restarted + void onWindowsTaskbarCreated() {} } diff --git a/lib/src/tray_manager.dart b/lib/src/tray_manager.dart index 248ed80..344fe2b 100644 --- a/lib/src/tray_manager.dart +++ b/lib/src/tray_manager.dart @@ -16,6 +16,7 @@ const kEventOnTrayIconMouseUp = 'onTrayIconMouseUp'; const kEventOnTrayIconRightMouseDown = 'onTrayIconRightMouseDown'; const kEventOnTrayIconRightMouseUp = 'onTrayIconRightMouseUp'; const kEventOnTrayMenuItemClick = 'onTrayMenuItemClick'; +const kWindowsTaskbarCreated = 'onWindowsTaskbarCreated'; enum TrayIconPositon { left, right } @@ -64,6 +65,9 @@ class TrayManager { } } break; + case kWindowsTaskbarCreated: + listener.onWindowsTaskbarCreated(); + break; } } } diff --git a/windows/tray_manager_plugin.cpp b/windows/tray_manager_plugin.cpp index b1978b9..bd070ec 100644 --- a/windows/tray_manager_plugin.cpp +++ b/windows/tray_manager_plugin.cpp @@ -50,6 +50,7 @@ class TrayManagerPlugin : public flutter::Plugin { NOTIFYICONIDENTIFIER niif; HMENU hMenu; bool tray_icon_setted = false; + UINT windows_taskbar_created_message = 0; // The ID of the WindowProc delegate registration. int window_proc_id = -1; @@ -105,6 +106,7 @@ void TrayManagerPlugin::RegisterWithRegistrar( TrayManagerPlugin::TrayManagerPlugin(flutter::PluginRegistrarWindows* registrar) : registrar(registrar) { + windows_taskbar_created_message = RegisterWindowMessage(L"TaskbarCreated"); window_proc_id = registrar->RegisterTopLevelWindowProcDelegate( [this](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { return HandleWindowProc(hwnd, message, wparam, lparam); @@ -197,6 +199,16 @@ std::optional TrayManagerPlugin::HandleWindowProc(HWND hWnd, default: return DefWindowProc(hWnd, message, wParam, lParam); }; + } else { + bool isTaskBarCreateMsg = windows_taskbar_created_message != 0 + && message == windows_taskbar_created_message; + if (isTaskBarCreateMsg) { + channel->InvokeMethod( + "onWindowsTaskbarCreated", + std::make_unique(nullptr)); + tray_icon_setted = false; + return LRESULT(0); + } } return result; } From 29803d1e732e06844201a93c54c29c57382f6724 Mon Sep 17 00:00:00 2001 From: Mozi <29089388+pzhlkj6612@users.noreply.github.com> Date: Tue, 15 Apr 2025 16:05:36 +0000 Subject: [PATCH 2/4] refactor: make taskbar-related code comply to current code style --- .../tray_manager/example/lib/pages/home.dart | 4 +++- .../tray_manager/lib/src/tray_listener.dart | 2 +- .../tray_manager/lib/src/tray_manager.dart | 4 ++-- .../windows/tray_manager_plugin.cpp | 19 ++++++++----------- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/tray_manager/example/lib/pages/home.dart b/packages/tray_manager/example/lib/pages/home.dart index c88accc..7475bbb 100644 --- a/packages/tray_manager/example/lib/pages/home.dart +++ b/packages/tray_manager/example/lib/pages/home.dart @@ -351,7 +351,9 @@ class _HomePageState extends State with TrayListener { @override void onWindowsTaskbarCreated() { - debugPrint('onWindowsTaskbarCreated'); + if (kDebugMode) { + print('onWindowsTaskbarCreated'); + } _handleSetIcon(_iconType); } } diff --git a/packages/tray_manager/lib/src/tray_listener.dart b/packages/tray_manager/lib/src/tray_listener.dart index f045fd8..1ae2600 100644 --- a/packages/tray_manager/lib/src/tray_listener.dart +++ b/packages/tray_manager/lib/src/tray_listener.dart @@ -13,6 +13,6 @@ abstract mixin class TrayListener { void onTrayMenuItemClick(MenuItem menuItem) {} - /// Emitted when windows taskbar created, such as explorer.exe restarted + /// Emitted upon taskbar creation, e.g., when Explorer restarts. void onWindowsTaskbarCreated() {} } diff --git a/packages/tray_manager/lib/src/tray_manager.dart b/packages/tray_manager/lib/src/tray_manager.dart index c8b8f5d..737de79 100644 --- a/packages/tray_manager/lib/src/tray_manager.dart +++ b/packages/tray_manager/lib/src/tray_manager.dart @@ -16,7 +16,7 @@ const kEventOnTrayIconMouseUp = 'onTrayIconMouseUp'; const kEventOnTrayIconRightMouseDown = 'onTrayIconRightMouseDown'; const kEventOnTrayIconRightMouseUp = 'onTrayIconRightMouseUp'; const kEventOnTrayMenuItemClick = 'onTrayMenuItemClick'; -const kWindowsTaskbarCreated = 'onWindowsTaskbarCreated'; +const kEventOnWindowsTaskbarCreated = 'onWindowsTaskbarCreated'; enum TrayIconPosition { left, right } @@ -70,7 +70,7 @@ class TrayManager { } } break; - case kWindowsTaskbarCreated: + case kEventOnWindowsTaskbarCreated: listener.onWindowsTaskbarCreated(); break; } diff --git a/packages/tray_manager/windows/tray_manager_plugin.cpp b/packages/tray_manager/windows/tray_manager_plugin.cpp index f6243da..3ce0f4e 100644 --- a/packages/tray_manager/windows/tray_manager_plugin.cpp +++ b/packages/tray_manager/windows/tray_manager_plugin.cpp @@ -50,7 +50,7 @@ class TrayManagerPlugin : public flutter::Plugin { NOTIFYICONIDENTIFIER niif; HMENU hMenu; bool tray_icon_setted = false; - UINT windows_taskbar_created_message = 0; + UINT windows_taskbar_created_message_id = 0; // The ID of the WindowProc delegate registration. int window_proc_id = -1; @@ -106,11 +106,11 @@ void TrayManagerPlugin::RegisterWithRegistrar( TrayManagerPlugin::TrayManagerPlugin(flutter::PluginRegistrarWindows* registrar) : registrar(registrar) { - windows_taskbar_created_message = RegisterWindowMessage(L"TaskbarCreated"); window_proc_id = registrar->RegisterTopLevelWindowProcDelegate( [this](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { return HandleWindowProc(hwnd, message, wparam, lparam); }); + windows_taskbar_created_message_id = RegisterWindowMessage(L"TaskbarCreated"); } TrayManagerPlugin::~TrayManagerPlugin() { @@ -197,15 +197,12 @@ std::optional TrayManagerPlugin::HandleWindowProc(HWND hWnd, default: return DefWindowProc(hWnd, message, wParam, lParam); }; - } else { - bool isTaskBarCreateMsg = windows_taskbar_created_message != 0 - && message == windows_taskbar_created_message; - if (isTaskBarCreateMsg) { - channel->InvokeMethod( - "onWindowsTaskbarCreated", - std::make_unique(nullptr)); - tray_icon_setted = false; - return LRESULT(0); + } else if (message == windows_taskbar_created_message_id) { + if (windows_taskbar_created_message_id != 0) { + channel->InvokeMethod("onWindowsTaskbarCreated", + std::make_unique(nullptr)); + // race condition? + tray_icon_setted = false; } } return result; From f4c1735742e138b65c4fe8ab3564771668d34584 Mon Sep 17 00:00:00 2001 From: Mozi <29089388+pzhlkj6612@users.noreply.github.com> Date: Tue, 15 Apr 2025 15:31:39 +0000 Subject: [PATCH 3/4] feat: restore icon and context menu when Explorer restarts if possible - restore the icon with the existing resource. - do create pop-up menu only once. --- .../tray_manager/example/lib/pages/home.dart | 8 ------ .../tray_manager/lib/src/tray_listener.dart | 3 --- .../tray_manager/lib/src/tray_manager.dart | 4 --- .../windows/tray_manager_plugin.cpp | 25 ++++++++++--------- 4 files changed, 13 insertions(+), 27 deletions(-) diff --git a/packages/tray_manager/example/lib/pages/home.dart b/packages/tray_manager/example/lib/pages/home.dart index 7475bbb..2d21789 100644 --- a/packages/tray_manager/example/lib/pages/home.dart +++ b/packages/tray_manager/example/lib/pages/home.dart @@ -348,12 +348,4 @@ class _HomePageState extends State with TrayListener { text: '${menuItem.toJson()}', ); } - - @override - void onWindowsTaskbarCreated() { - if (kDebugMode) { - print('onWindowsTaskbarCreated'); - } - _handleSetIcon(_iconType); - } } diff --git a/packages/tray_manager/lib/src/tray_listener.dart b/packages/tray_manager/lib/src/tray_listener.dart index 1ae2600..add190f 100644 --- a/packages/tray_manager/lib/src/tray_listener.dart +++ b/packages/tray_manager/lib/src/tray_listener.dart @@ -12,7 +12,4 @@ abstract mixin class TrayListener { void onTrayIconRightMouseUp() {} void onTrayMenuItemClick(MenuItem menuItem) {} - - /// Emitted upon taskbar creation, e.g., when Explorer restarts. - void onWindowsTaskbarCreated() {} } diff --git a/packages/tray_manager/lib/src/tray_manager.dart b/packages/tray_manager/lib/src/tray_manager.dart index 737de79..f23b61c 100644 --- a/packages/tray_manager/lib/src/tray_manager.dart +++ b/packages/tray_manager/lib/src/tray_manager.dart @@ -16,7 +16,6 @@ const kEventOnTrayIconMouseUp = 'onTrayIconMouseUp'; const kEventOnTrayIconRightMouseDown = 'onTrayIconRightMouseDown'; const kEventOnTrayIconRightMouseUp = 'onTrayIconRightMouseUp'; const kEventOnTrayMenuItemClick = 'onTrayMenuItemClick'; -const kEventOnWindowsTaskbarCreated = 'onWindowsTaskbarCreated'; enum TrayIconPosition { left, right } @@ -70,9 +69,6 @@ class TrayManager { } } break; - case kEventOnWindowsTaskbarCreated: - listener.onWindowsTaskbarCreated(); - break; } } } diff --git a/packages/tray_manager/windows/tray_manager_plugin.cpp b/packages/tray_manager/windows/tray_manager_plugin.cpp index 3ce0f4e..418dcfa 100644 --- a/packages/tray_manager/windows/tray_manager_plugin.cpp +++ b/packages/tray_manager/windows/tray_manager_plugin.cpp @@ -48,7 +48,8 @@ class TrayManagerPlugin : public flutter::Plugin { flutter::PluginRegistrarWindows* registrar; NOTIFYICONDATA nid; NOTIFYICONIDENTIFIER niif; - HMENU hMenu; + // do create pop-up menu only once. + HMENU hMenu = CreatePopupMenu(); bool tray_icon_setted = false; UINT windows_taskbar_created_message_id = 0; @@ -56,6 +57,7 @@ class TrayManagerPlugin : public flutter::Plugin { int window_proc_id = -1; void TrayManagerPlugin::_CreateMenu(HMENU menu, flutter::EncodableMap args); + void TrayManagerPlugin::_ApplyIcon(); // Called for top-level WindowProc delegation. std::optional TrayManagerPlugin::HandleWindowProc(HWND hwnd, @@ -198,11 +200,10 @@ std::optional TrayManagerPlugin::HandleWindowProc(HWND hWnd, return DefWindowProc(hWnd, message, wParam, lParam); }; } else if (message == windows_taskbar_created_message_id) { - if (windows_taskbar_created_message_id != 0) { - channel->InvokeMethod("onWindowsTaskbarCreated", - std::make_unique(nullptr)); - // race condition? + if (windows_taskbar_created_message_id != 0 && tray_icon_setted) { + // restore the icon with the existing resource. tray_icon_setted = false; + _ApplyIcon(); } } return result; @@ -233,22 +234,25 @@ void TrayManagerPlugin::SetIcon( std::wstring_convert> converter; - HICON hIcon = static_cast( + nid.hIcon = static_cast( LoadImage(nullptr, (LPCWSTR)(converter.from_bytes(iconPath).c_str()), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_LOADFROMFILE)); + _ApplyIcon(); + + result->Success(flutter::EncodableValue(true)); +} + +void TrayManagerPlugin::_ApplyIcon() { if (tray_icon_setted) { - nid.hIcon = hIcon; Shell_NotifyIcon(NIM_MODIFY, &nid); } else { nid.cbSize = sizeof(NOTIFYICONDATA); nid.hWnd = GetMainWindow(); nid.uCallbackMessage = WM_MYMESSAGE; - nid.hIcon = hIcon; nid.uFlags = NIF_MESSAGE | NIF_ICON; Shell_NotifyIcon(NIM_ADD, &nid); - hMenu = CreatePopupMenu(); } niif.cbSize = sizeof(NOTIFYICONIDENTIFIER); @@ -257,8 +261,6 @@ void TrayManagerPlugin::SetIcon( niif.guidItem = GUID_NULL; tray_icon_setted = true; - - result->Success(flutter::EncodableValue(true)); } void TrayManagerPlugin::SetToolTip( @@ -285,7 +287,6 @@ void TrayManagerPlugin::SetContextMenu( const flutter::EncodableMap& args = std::get(*method_call.arguments()); - hMenu = CreatePopupMenu(); _CreateMenu(hMenu, std::get( args.at(flutter::EncodableValue("menu")))); From d65b28d694b6a12a9544423c808b35e66f48f678 Mon Sep 17 00:00:00 2001 From: Mozi <29089388+pzhlkj6612@users.noreply.github.com> Date: Thu, 24 Apr 2025 08:03:26 +0000 Subject: [PATCH 4/4] feat: restore icon and context menu when Explorer restarts if necessary Correct the message of the previous commit.