@@ -1808,6 +1808,51 @@ void IslandWindow::AddToSystemMenu(const winrt::hstring& itemLabel, winrt::deleg
18081808 _systemMenuNextItemId++;
18091809}
18101810
1811+ void IslandWindow::AddSystemSubMenu (const winrt::hstring& menuLabel, const std::vector<std::pair<winrt::hstring, winrt::delegate<void ()>>>& items)
1812+ {
1813+ const auto systemMenu = GetSystemMenu (_window.get (), FALSE );
1814+
1815+ HMENU subMenu = CreatePopupMenu ();
1816+ if (!subMenu)
1817+ {
1818+ LOG_LAST_ERROR ();
1819+ return ;
1820+ }
1821+
1822+ for (const auto & [label, callback] : items)
1823+ {
1824+ auto wID = _systemMenuNextItemId;
1825+
1826+ MENUITEMINFOW item;
1827+ item.cbSize = sizeof (MENUITEMINFOW);
1828+ item.fMask = MIIM_STATE | MIIM_ID | MIIM_STRING;
1829+ item.fState = MF_ENABLED;
1830+ item.wID = wID;
1831+ item.dwTypeData = const_cast <LPWSTR>(label.c_str ());
1832+ item.cch = static_cast <UINT>(label.size ());
1833+
1834+ if (LOG_LAST_ERROR_IF (!InsertMenuItemW (subMenu, wID, FALSE , &item)))
1835+ {
1836+ continue ;
1837+ }
1838+ _systemMenuItems.insert ({ wID, { label, callback } });
1839+ _systemMenuNextItemId++;
1840+ }
1841+
1842+ MENUITEMINFOW subMenuItem;
1843+ subMenuItem.cbSize = sizeof (MENUITEMINFOW);
1844+ subMenuItem.fMask = MIIM_STRING | MIIM_SUBMENU;
1845+ subMenuItem.hSubMenu = subMenu;
1846+ subMenuItem.dwTypeData = const_cast <LPWSTR>(menuLabel.c_str ());
1847+ subMenuItem.cch = static_cast <UINT>(menuLabel.size ());
1848+
1849+ if (LOG_LAST_ERROR_IF (!InsertMenuItemW (systemMenu, _systemMenuNextItemId, FALSE , &subMenuItem)))
1850+ {
1851+ DestroyMenu (subMenu);
1852+ return ;
1853+ }
1854+ }
1855+
18111856void IslandWindow::RemoveFromSystemMenu (const winrt::hstring& itemLabel)
18121857{
18131858 const auto systemMenu = GetSystemMenu (_window.get (), FALSE );
@@ -1832,6 +1877,53 @@ void IslandWindow::RemoveFromSystemMenu(const winrt::hstring& itemLabel)
18321877 _systemMenuItems.erase (it->first );
18331878}
18341879
1880+ // Method Description:
1881+ // - Removes a submenu from the system menu by its label. Also removes all
1882+ // child items from the _systemMenuItems tracking map. The submenu HMENU
1883+ // is destroyed automatically by DeleteMenu.
1884+ // Arguments:
1885+ // - menuLabel: The label of the submenu to remove.
1886+ void IslandWindow::RemoveSystemSubMenu (const winrt::hstring& menuLabel)
1887+ {
1888+ const auto systemMenu = GetSystemMenu (_window.get (), FALSE );
1889+ const auto itemCount = GetMenuItemCount (systemMenu);
1890+ if (LOG_LAST_ERROR_IF (itemCount == -1 ))
1891+ {
1892+ return ;
1893+ }
1894+
1895+ for (int i = 0 ; i < itemCount; i++)
1896+ {
1897+ wchar_t buffer[256 ]{};
1898+ MENUITEMINFOW mii{};
1899+ mii.cbSize = sizeof (MENUITEMINFOW);
1900+ mii.fMask = MIIM_STRING | MIIM_SUBMENU;
1901+ mii.dwTypeData = buffer;
1902+ mii.cch = ARRAYSIZE (buffer);
1903+
1904+ if (!GetMenuItemInfoW (systemMenu, static_cast <UINT>(i), TRUE , &mii))
1905+ {
1906+ continue ;
1907+ }
1908+
1909+ if (mii.hSubMenu && menuLabel == std::wstring_view{ buffer })
1910+ {
1911+ const auto subItemCount = GetMenuItemCount (mii.hSubMenu );
1912+ for (int j = 0 ; j < subItemCount; j++)
1913+ {
1914+ const auto subItemId = GetMenuItemID (mii.hSubMenu , j);
1915+ if (subItemId != static_cast <UINT>(-1 ))
1916+ {
1917+ _systemMenuItems.erase (subItemId);
1918+ }
1919+ }
1920+
1921+ DeleteMenu (systemMenu, static_cast <UINT>(i), MF_BYPOSITION);
1922+ return ;
1923+ }
1924+ }
1925+ }
1926+
18351927void IslandWindow::_resetSystemMenu ()
18361928{
18371929 // GetSystemMenu(..., true) will revert the menu to the default state.
0 commit comments