From dd1ea96f37cd138bc9defb3a0fc896195f6ea1f8 Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sat, 19 Nov 2022 20:54:21 +0100 Subject: [PATCH 01/12] Build: Fix source indexing x64 version of pdbstr doesn't work (because of missing __CxxFrameHandler4 on Windows Server 2019). Fortunately it seems that x86 version works well, so we can use that one. --- Src/Setup/BuildBinaries.bat | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Src/Setup/BuildBinaries.bat b/Src/Setup/BuildBinaries.bat index f1f814962..ec0648d74 100644 --- a/Src/Setup/BuildBinaries.bat +++ b/Src/Setup/BuildBinaries.bat @@ -114,7 +114,7 @@ copy /B Output\x64\StartMenuHelper64.dll Output\PDB64 > nul REM ********* Source Index PDBs -set PDBSTR_PATH="C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\srcsrv\pdbstr.exe" +set PDBSTR_PATH="C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\srcsrv\pdbstr.exe" if exist %PDBSTR_PATH% ( echo --- Adding source index to PDBs @@ -122,10 +122,18 @@ if exist %PDBSTR_PATH% ( for %%f in (Output\PDB32\*.pdb) do ( %PDBSTR_PATH% -w -p:%%f -s:srcsrv -i:Output\pdbstr.txt + if not ERRORLEVEL 0 ( + echo Error adding source index to PDB + exit /b 1 + ) ) for %%f in (Output\PDB64\*.pdb) do ( %PDBSTR_PATH% -w -p:%%f -s:srcsrv -i:Output\pdbstr.txt + if not ERRORLEVEL 0 ( + echo Error adding source index to PDB + exit /b 1 + ) ) ) From 696f49461421a2308ec85f2828e8acdb4637297d Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sat, 29 Oct 2022 22:18:48 +0200 Subject: [PATCH 02/12] Get proper branding string on Windows 11 Based on info from https://dennisbabkin.com/blog/?t=how-to-tell-the-real-version-of-windows-your-app-is-running-on#ver_string . Fixes #878, #960, #1063. --- Src/StartMenu/StartMenuDLL/SettingsUI.cpp | 54 +++++++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp index ef1957b99..5a406859e 100644 --- a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp +++ b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp @@ -4648,6 +4648,48 @@ void UpgradeSettings( bool bShared ) } } +static CString GetWindowsBrandingString() +{ + CString retval; + + if (GetWinVersion() >= WIN_VER_WIN10) + { + auto winbrand = LoadLibraryEx(L"winbrand.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (winbrand) + { + PWSTR (WINAPI * BrandingFormatString)(PCWSTR pstrFormat); + BrandingFormatString = (decltype(BrandingFormatString))GetProcAddress(winbrand, "BrandingFormatString"); + if (BrandingFormatString) + { + auto osName = BrandingFormatString(L"%WINDOWS_LONG%"); + if (osName) + { + retval = osName; + GlobalFree(osName); + } + } + + FreeLibrary(winbrand); + } + } + + if (retval.IsEmpty()) + { + // fallback for older Windows + wchar_t title[256] = L"Windows"; + + if (CRegKey reg; reg.Open(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion", KEY_READ) == ERROR_SUCCESS) + { + ULONG size = _countof(title); + reg.QueryStringValue(L"ProductName", title, &size); + } + + retval = title; + } + + return retval; +} + void UpdateSettings( void ) { { @@ -4770,16 +4812,10 @@ void UpdateSettings( void ) UpdateSetting(L"NumericSort",CComVariant(SHRestricted(REST_NOSTRCMPLOGICAL)?0:1),false); - wchar_t title[256]=L"Windows"; - ULONG size=_countof(title); - { - CRegKey regTitle; - if (regTitle.Open(HKEY_LOCAL_MACHINE,L"Software\\Microsoft\\Windows NT\\CurrentVersion",KEY_READ)==ERROR_SUCCESS) - regTitle.QueryStringValue(L"ProductName",title,&size); - } - UpdateSetting(L"MenuCaption",CComVariant(title),false); + UpdateSetting(L"MenuCaption",CComVariant(GetWindowsBrandingString()),false); - size=_countof(title); + wchar_t title[256]{}; + ULONG size=_countof(title); if (!GetUserNameEx(NameDisplay,title,&size)) { // GetUserNameEx may fail (for example on Home editions). use the login name From 809bcda99eb3f046114c4e9ead467a14cf7d5703 Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Tue, 1 Nov 2022 11:43:05 +0100 Subject: [PATCH 03/12] Show Open-Shell version in start context menu Fixes #888. --- Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp | 8 ++++++-- Src/StartMenu/StartMenuDLL/StartMenuDLL.rc | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp b/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp index e1aa81ab8..cdeca188b 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp @@ -3861,9 +3861,13 @@ if (!g_bTrimHooks) // right-click on the start button - open the context menu (Settings, Help, Exit) HMENU menu=CreatePopupMenu(); - CString title=LoadStringEx(IDS_MENU_TITLE); - if (!title.IsEmpty()) + CString titleFmt=LoadStringEx(IDS_MENU_TITLE); + if (!titleFmt.IsEmpty()) { + CString title; + DWORD ver=GetVersionEx(g_Instance); + title.Format(titleFmt,ver>>24,(ver>>16)&0xFF,ver&0xFFFF); + AppendMenu(menu,MF_STRING,0,title); EnableMenuItem(menu,0,MF_BYPOSITION|MF_DISABLED); SetMenuDefaultItem(menu,0,TRUE); diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc index c851afac4..416554e93 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc @@ -427,7 +427,7 @@ BEGIN IDS_SKIN_ERR_LOAD_FILE "Failed to load the variation skin file %s.\r\n" IDS_SKIN_ERR_LOAD "Error loading %s\n%s" IDS_SKIN_ERR_VERSION "The selected skin is not compatible with this version of the start menu.\r\n" - IDS_MENU_TITLE "== Open-Shell Menu ==" + IDS_MENU_TITLE "Open-Shell Menu %d.%d.%d" IDS_DEFAULT_SKIN "" IDS_CONTROLS_SETTINGS "Controls" IDS_OPEN_NOTHING "Nothing" From 5c31b6d495b4333bdef2551252cb32882d1fe06c Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sat, 19 Nov 2022 21:44:13 +0100 Subject: [PATCH 04/12] Fix image rendering on Win7 Fixes #1023 #90. --- Src/Lib/ResourceHelper.cpp | 12 +++++++++--- Src/StartMenu/StartMenuDLL/ItemManager.cpp | 3 ++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Src/Lib/ResourceHelper.cpp b/Src/Lib/ResourceHelper.cpp index 3ab46510e..d7f7db6ea 100644 --- a/Src/Lib/ResourceHelper.cpp +++ b/Src/Lib/ResourceHelper.cpp @@ -396,8 +396,11 @@ HBITMAP LoadImageFile( const wchar_t *path, const SIZE *pSize, bool bUseAlpha, b CComPtr pFactory; if (FAILED(pFactory.CoCreateInstance(CLSID_WICImagingFactory))) { - if (srcBmp) DeleteObject(srcBmp); - return NULL; + if (FAILED(pFactory.CoCreateInstance(CLSID_WICImagingFactory1))) + { + if (srcBmp) DeleteObject(srcBmp); + return NULL; + } } CComPtr pBitmap; @@ -534,7 +537,10 @@ HBITMAP LoadImageResource( HMODULE hModule, const wchar_t *name, bool bTopDown, { CComPtr pFactory; if (FAILED(pFactory.CoCreateInstance(CLSID_WICImagingFactory))) - return NULL; + { + if (FAILED(pFactory.CoCreateInstance(CLSID_WICImagingFactory1))) + return NULL; + } CComPtr pBitmap; if (hModule) diff --git a/Src/StartMenu/StartMenuDLL/ItemManager.cpp b/Src/StartMenu/StartMenuDLL/ItemManager.cpp index 9bbf787f8..c26733bdd 100644 --- a/Src/StartMenu/StartMenuDLL/ItemManager.cpp +++ b/Src/StartMenu/StartMenuDLL/ItemManager.cpp @@ -489,7 +489,8 @@ void CItemManager::LoadIconData::Init( void ) HIMAGELIST_QueryInterface(m_TempLists[i],IID_IImageList2,(void**)&m_pTempLists[i]); } } - m_pFactory.CoCreateInstance(CLSID_WICImagingFactory); + if (FAILED(m_pFactory.CoCreateInstance(CLSID_WICImagingFactory))) + m_pFactory.CoCreateInstance(CLSID_WICImagingFactory1); } void CItemManager::LoadIconData::Close( void ) From 55c76ce79af511ad0bc7128a3259e995ce8f16ec Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sun, 27 Nov 2022 15:45:01 +0100 Subject: [PATCH 05/12] Use more convenient format for color settings We are storing color settings in BBGGRR format (for historical reasons). This may be confusing for people that are used to (more widely used) RRGGBB format. Thus we will present color settings in RRGGBB format when editing. We will still use BBGGRR format for those settings internally. To maintain backward compatibility with existing settings stored in registry/xml. Also setting descriptions now contain hint about expected color format. This way it should be more clear what values `Open-Shell` expects. Fixes #82, #1141. --- Src/ClassicIE/ClassicIEDLL/ClassicIEDLL.rc | 12 +++---- Src/Lib/SettingsUIHelper.cpp | 28 ++++++++++++---- Src/Lib/SettingsUIHelper.h | 8 +++++ Src/StartMenu/StartMenuDLL/SettingsUI.cpp | 39 ++++++++++++++++------ Src/StartMenu/StartMenuDLL/StartMenuDLL.rc | 14 ++++---- 5 files changed, 70 insertions(+), 31 deletions(-) diff --git a/Src/ClassicIE/ClassicIEDLL/ClassicIEDLL.rc b/Src/ClassicIE/ClassicIEDLL/ClassicIEDLL.rc index 9d163d852..cd2e5dfd0 100644 --- a/Src/ClassicIE/ClassicIEDLL/ClassicIEDLL.rc +++ b/Src/ClassicIE/ClassicIEDLL/ClassicIEDLL.rc @@ -135,17 +135,17 @@ BEGIN IDS_LANGUAGE_SETTINGS "Language" IDS_CAPTION_FONT "Caption font" IDS_CAPTION_FONT_TIP "Select the font and text size to use for the caption" - IDS_TEXT_COLOR "Text color" + IDS_TEXT_COLOR "Text color (RRGGBB)" IDS_TEXT_COLOR_TIP "Select the color for the caption text" - IDS_MAXTEXT_COLOR "Text color (maximized)" + IDS_MAXTEXT_COLOR "Text color (maximized) (RRGGBB)" IDS_MAXTEXT_COLOR_TIP "Select the color for the caption text when the window is maximized" - IDS_INTEXT_COLOR "Text color (inactive)" + IDS_INTEXT_COLOR "Text color (inactive) (RRGGBB)" IDS_INTEXT_COLOR_TIP "Select the color for the caption text when the window is inactive" - IDS_MAXINTEXT_COLOR "Text color (maximized, inactive)" + IDS_MAXINTEXT_COLOR "Text color (maximized, inactive) (RRGGBB)" IDS_MAXINTEXT_COLOR_TIP "Select the color for the caption text when the window is maximized and inactive" IDS_GLOW "Text glow" IDS_GLOW_TIP "When this is checked, the text will have a glow around it" - IDS_GLOW_COLOR "Glow color" + IDS_GLOW_COLOR "Glow color (RRGGBB)" IDS_GLOW_COLOR_TIP "Select the color for the caption glow" END @@ -153,7 +153,7 @@ STRINGTABLE BEGIN IDS_MAXGLOW "Text glow (maximized)" IDS_MAXGLOW_TIP "When this is checked, the text in the maximized window will have a glow around it" - IDS_MAXGLOW_COLOR "Glow color (maximized)" + IDS_MAXGLOW_COLOR "Glow color (maximized) (RRGGBB)" IDS_MAXGLOW_COLOR_TIP "Select the color for the caption glow when the window is maximized" IDS_STATUS_SETTINGS "Status Bar" IDS_SHOW_PROGRESS "Show progress" diff --git a/Src/Lib/SettingsUIHelper.cpp b/Src/Lib/SettingsUIHelper.cpp index a23d2b7cb..effb3f16a 100644 --- a/Src/Lib/SettingsUIHelper.cpp +++ b/Src/Lib/SettingsUIHelper.cpp @@ -2651,15 +2651,14 @@ LRESULT CTreeSettingsDlg::OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BO CString str; m_EditBox.GetWindowText(str); str.TrimLeft(); str.TrimRight(); - wchar_t *end; - COLORREF val=wcstol(str,&end,16)&0xFFFFFF; + COLORREF val=RgbToBgr(ParseColor(str)); static COLORREF customColors[16]; CHOOSECOLOR choose={sizeof(choose),m_hWnd,NULL,val,customColors}; choose.Flags=CC_ANYCOLOR|CC_FULLOPEN|CC_RGBINIT; if (ChooseColor(&choose)) { wchar_t text[100]; - Sprintf(text,_countof(text),L"%06X",choose.rgbResult); + Sprintf(text,_countof(text),L"%06X",BgrToRgb(choose.rgbResult)); m_EditBox.SetWindowText(text); ApplyEditBox(); UpdateGroup(m_pEditSetting); @@ -3048,8 +3047,7 @@ void CTreeSettingsDlg::ApplyEditBox( void ) } else if (pSetting->type==CSetting::TYPE_COLOR) { - wchar_t *end; - int val=wcstol(str,&end,16)&0xFFFFFF; + int val=RgbToBgr(ParseColor(str)); if (pSetting->value.vt!=VT_I4 || pSetting->value.intVal!=val) { pSetting->value=CComVariant(val); @@ -3156,7 +3154,7 @@ void CTreeSettingsDlg::ItemSelected( HTREEITEM hItem, CSetting *pSetting, bool b mode=EDIT_COLOR; int val=0; if (valVar.vt==VT_I4) - val=valVar.intVal; + val=BgrToRgb(valVar.intVal); Sprintf(text,_countof(text),L"%06X",val); } } @@ -3462,7 +3460,7 @@ void CTreeSettingsDlg::UpdateGroup( const CSetting *pModified ) CString str=LoadStringEx(pSetting->nameID); int val=0; if (valVar.vt==VT_I4) - val=valVar.intVal; + val=BgrToRgb(valVar.intVal); Sprintf(text,_countof(text),L"%s: %06X",str,val); item.mask|=TVIF_TEXT; } @@ -3616,3 +3614,19 @@ bool CDefaultSettingsPanel::Validate( HWND parent ) s_Dialog.Validate(); return true; } + +DWORD RgbToBgr(DWORD val) +{ + return ((val & 0xFF) << 16) | (val & 0xFF00) | ((val >> 16) & 0xFF); +} + +DWORD BgrToRgb(DWORD val) +{ + return RgbToBgr(val); +} + +DWORD ParseColor(const wchar_t* str) +{ + wchar_t* end; + return wcstoul(str, &end, 16) & 0xFFFFFF; +} diff --git a/Src/Lib/SettingsUIHelper.h b/Src/Lib/SettingsUIHelper.h index 473dd953c..acdea3f63 100644 --- a/Src/Lib/SettingsUIHelper.h +++ b/Src/Lib/SettingsUIHelper.h @@ -387,3 +387,11 @@ extern const GUID FOLDERID_DesktopRoot; bool BrowseCommandHelper( HWND parent, wchar_t *text ); bool BrowseLinkHelper( HWND parent, wchar_t *text, bool bFoldersOnly ); bool BrowseIconHelper( HWND parent, wchar_t *text ); + +// convert color in RRGGBB format to BBGGRR +DWORD RgbToBgr(DWORD val); +// convert color in BBGGRR format to RRGGBB +DWORD BgrToRgb(DWORD val); + +// parse color from hexadecimal string +DWORD ParseColor(const wchar_t* str); diff --git a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp index 5a406859e..d1107751f 100644 --- a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp +++ b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp @@ -30,6 +30,19 @@ const int DEFAULT_TASK_OPACITY10=85; // 85% /////////////////////////////////////////////////////////////////////////////// +CString RgbToBgr(const wchar_t* str) +{ + CString retval; + retval.Format(L"%06X", RgbToBgr(ParseColor(str))); + + return retval; +} + +CString BgrToRgb(const wchar_t* str) +{ + return RgbToBgr(str); +} + class CSkinSettingsDlg: public CResizeableDlg { public: @@ -422,7 +435,7 @@ void CSkinSettingsDlg::UpdateSkinSettings( void ) if (!option.bEnabled || bLocked) image|=SETTING_STATE_DISABLED; if (option.bValue && option.type>SKIN_OPTION_BOOL) - Sprintf(text,_countof(text),L"%s: %s",option.label,option.sValue); + Sprintf(text,_countof(text),L"%s: %s",option.label,(option.type==SKIN_OPTION_COLOR)?BgrToRgb(option.sValue):option.sValue); else Sprintf(text,_countof(text),L"%s",option.label); @@ -482,9 +495,7 @@ LRESULT CSkinSettingsDlg::OnCustomDraw( int idCtrl, LPNMHDR pnmh, BOOL& bHandled if (TreeView_GetItemRect(m_Tree,(HTREEITEM)pDraw->nmcd.dwItemSpec,&rc,TRUE)) { const wchar_t *str=m_CurrentSkin.Options[pDraw->nmcd.lItemlParam].sValue; - wchar_t *end; - COLORREF color=wcstoul(str,&end,16); - SetDCBrushColor(pDraw->nmcd.hdc,color&0xFFFFFF); + SetDCBrushColor(pDraw->nmcd.hdc,ParseColor(str)); SelectObject(pDraw->nmcd.hdc,GetStockObject(DC_BRUSH)); SelectObject(pDraw->nmcd.hdc,GetStockObject(BLACK_PEN)); Rectangle(pDraw->nmcd.hdc,rc.right,rc.top,rc.right+rc.bottom-rc.top,rc.bottom-1); @@ -690,15 +701,14 @@ LRESULT CSkinSettingsDlg::OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BO CString str; m_EditBox.GetWindowText(str); str.TrimLeft(); str.TrimRight(); - wchar_t *end; - COLORREF val=wcstol(str,&end,16)&0xFFFFFF; + COLORREF val=RgbToBgr(ParseColor(str)); static COLORREF customColors[16]; CHOOSECOLOR choose={sizeof(choose),m_hWnd,NULL,val,customColors}; choose.Flags=CC_ANYCOLOR|CC_FULLOPEN|CC_RGBINIT; if (ChooseColor(&choose)) { wchar_t text[100]; - Sprintf(text,_countof(text),L"%06X",choose.rgbResult); + Sprintf(text,_countof(text),L"%06X",BgrToRgb(choose.rgbResult)); m_EditBox.SetWindowText(text); ApplyEditBox(); m_Tree.Invalidate(); @@ -717,7 +727,11 @@ void CSkinSettingsDlg::ApplyEditBox( void ) CString str; m_EditBox.GetWindowText(str); str.TrimLeft(); str.TrimRight(); - m_CurrentSkin.Options[m_EditItemIndex].sValue=str; + auto& option=m_CurrentSkin.Options[m_EditItemIndex]; + if (option.type==SKIN_OPTION_COLOR) + option.sValue=RgbToBgr(str); + else + option.sValue=str; StoreSkinOptions(); } } @@ -730,7 +744,7 @@ void CSkinSettingsDlg::ItemSelected( HTREEITEM hItem, int index, bool bEnabled ) const MenuSkin::Option &option=m_CurrentSkin.Options[m_EditItemIndex]; wchar_t text[256]; if (option.bValue && option.type>SKIN_OPTION_BOOL) - Sprintf(text,_countof(text),L"%s: %s",option.label,option.sValue); + Sprintf(text,_countof(text),L"%s: %s",option.label,(option.type==SKIN_OPTION_COLOR)?BgrToRgb(option.sValue):option.sValue); else Sprintf(text,_countof(text),L"%s",option.label); TVITEM item={TVIF_TEXT,m_EditItem,0,0,text}; @@ -745,7 +759,10 @@ void CSkinSettingsDlg::ItemSelected( HTREEITEM hItem, int index, bool bEnabled ) const MenuSkin::Option &option=m_CurrentSkin.Options[index]; if (option.type>SKIN_OPTION_BOOL) mode=option.type; - text=option.sValue; + if (option.type==SKIN_OPTION_COLOR) + text=BgrToRgb(option.sValue); + else + text=option.sValue; } RECT rc; @@ -4946,7 +4963,7 @@ void UpdateSettings( void ) if (GetWinVersion()>WIN_VER_WIN7) { int color=GetSystemGlassColor8(); - UpdateSetting(L"TaskbarColor",CComVariant(((color&0xFF)<<16)|(color&0xFF00)|((color>>16)&0xFF)),false); + UpdateSetting(L"TaskbarColor",CComVariant(RgbToBgr(color)),false); } if (GetWinVersion()<=WIN_VER_WIN7) diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc index 416554e93..46634e16b 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc @@ -1082,7 +1082,7 @@ BEGIN IDS_MIN_HEIGHT_TIP "The main menu will be at least as tall as this many search results" IDS_GLASS_OVERRIDE "Override glass color" IDS_GLASS_OVERRIDE_TIP "Check this to override the system glass color to use in the menu" - IDS_GLASS_COLOR "Menu glass color" + IDS_GLASS_COLOR "Menu glass color (RRGGBB)" IDS_GLASS_COLOR_TIP "Select the glass color to use in the menu. How much this color affects the menu will depend on the selected skin" IDS_GLASS_INTENSITY "Menu glass intensity" IDS_GLASS_INTENSITY_TIP "Select the intensity (brightness) for the glass color in the menu (0 - dark, 100 - bright)" @@ -1144,17 +1144,17 @@ BEGIN IDS_STRING7024 "Shadows on glass#The text and the arrows in the second column of the main menu will have a drop shadow" IDS_STRING7025 "Opaque" IDS_STRING7026 "Main menu color" - IDS_STRING7027 "Custom color#Select custom color for the main menu" + IDS_STRING7027 "Custom color (RRGGBB)#Select custom color for the main menu" IDS_STRING7028 "Sub-menu color" - IDS_STRING7029 "Custom color#Select custom color for the sub-menus" + IDS_STRING7029 "Custom color (RRGGBB)#Select custom color for the sub-menus" IDS_STRING7030 "Silver" IDS_STRING7031 "Gold" IDS_STRING7032 "Steel" IDS_STRING7033 "Titanium" IDS_STRING7034 "Image for first column#Select custom image for the first column of the main menu" IDS_STRING7035 "Image for second column#Select custom image for the second column of the main menu" - IDS_STRING7036 "Text color for first column#Select custom color for the first column of the main menu text" - IDS_STRING7037 "Text color for second column#Select custom color for the second column of the main menu text" + IDS_STRING7036 "Text color for first column (RRGGBB)#Select custom color for the first column of the main menu text" + IDS_STRING7037 "Text color for second column (RRGGBB)#Select custom color for the second column of the main menu text" IDS_STRING7038 "Text size#Select custom size for the main menu text" END @@ -1249,7 +1249,7 @@ BEGIN IDS_TASK_AEROGLASS_TIP "The taskbar will have glass transparency that is compatible with the Aero Glass mod" IDS_TASK_OPACITY "Taskbar opacity" IDS_TASK_OPACITY_TIP "Set the opacity for the taskbar (0 - transparent, 100 - opaque)" - IDS_TASK_COLOR "Taskbar color" + IDS_TASK_COLOR "Taskbar color (RRGGBB)" IDS_TASK_COLOR_TIP "Set the color for the taskbar" IDS_PCSETTINGS "Settings" IDS_PCSETTINGS_TIP "Shows the modern Settings window" @@ -1288,7 +1288,7 @@ BEGIN IDS_TASK_BORDERS "Border sizes" IDS_TASK_BORDERS_TIP "Select how many pixel on each side of the texture to exclude from stretching" IDS_TASKBAR_SETTINGS "Taskbar" - IDS_TASK_TEXTCOLOR "Taskbar text color" + IDS_TASK_TEXTCOLOR "Taskbar text color (RRGGBB)" IDS_TASK_TEXTCOLOR_TIP "Select the color for the text on the taskbar" IDS_SELECT_LAST "Select the last item in shutdown menu" IDS_SELECT_LAST_TIP "When this is checked, the last item will be selected by default when the shutdown menu is opened with the keyboard" From b59ea48b80fb6ae9ea0ae1e1c0db63f3723a2a07 Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Fri, 25 Nov 2022 21:50:36 +0100 Subject: [PATCH 06/12] Don't track usage of Open-Shell modern settings folder This way `Open-Shell Modern Settings` folder won't appear in File Explorer's frequent list. Fixes #744. --- Src/StartMenu/StartMenuDLL/MenuCommands.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Src/StartMenu/StartMenuDLL/MenuCommands.cpp b/Src/StartMenu/StartMenuDLL/MenuCommands.cpp index 3f949f27b..0ff9b7454 100644 --- a/Src/StartMenu/StartMenuDLL/MenuCommands.cpp +++ b/Src/StartMenu/StartMenuDLL/MenuCommands.cpp @@ -2811,6 +2811,10 @@ void CMenuContainer::ActivateItem( int index, TActivateType type, const POINT *p if (bRefresh || bRefreshMain) info.fMask|=CMIC_MASK_NOASYNC; // wait for delete/link commands to finish so we can refresh the menu + // we don't want our virtual folder to appear in Explorer's frequent list + if (wcsncmp(item.pItemInfo->PATH, L"::{82E749ED-B971-4550-BAF7-06AA2BF7E836}", 40) == 0) + info.fMask &= ~CMIC_MASK_FLAG_LOG_USAGE; + s_bPreventClosing=true; for (auto& it : s_Menus) { From 0cbe11685de370d4d11e2a2d8dfa35376855ef90 Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Wed, 30 Nov 2022 18:48:33 +0100 Subject: [PATCH 07/12] Fix skin options default values Multi-string settings have to be terminated by new line. Otherwise there may be some garbage (following the string) stored in registry. --- Src/StartMenu/StartMenuDLL/SettingsUI.cpp | 30 +++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp index d1107751f..3b2c429cc 100644 --- a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp +++ b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp @@ -5063,15 +5063,15 @@ void UpdateSettings( void ) HIGHCONTRAST contrast={sizeof(contrast)}; if (SystemParametersInfo(SPI_GETHIGHCONTRAST,sizeof(contrast),&contrast,0) && (contrast.dwFlags&HCF_HIGHCONTRASTON)) { - options1=L"CAPTION=1\nUSER_IMAGE=0\nUSER_NAME=0\nCENTER_NAME=0\nSMALL_ICONS=0\nTHICK_BORDER=0\nSOLID_SELECTION=1"; - options2=L"NO_ICONS=1\nUSER_IMAGE=1\nUSER_NAME=0\nCENTER_NAME=0\nSMALL_ICONS=0\nTHICK_BORDER=0\nSOLID_SELECTION=1"; - options3=L"USER_IMAGE=1\nSMALL_ICONS=0\nTHICK_BORDER=0\nSOLID_SELECTION=1"; + options1=L"CAPTION=1\nUSER_IMAGE=0\nUSER_NAME=0\nCENTER_NAME=0\nSMALL_ICONS=0\nTHICK_BORDER=0\nSOLID_SELECTION=1\n"; + options2=L"NO_ICONS=1\nUSER_IMAGE=1\nUSER_NAME=0\nCENTER_NAME=0\nSMALL_ICONS=0\nTHICK_BORDER=0\nSOLID_SELECTION=1\n"; + options3=L"USER_IMAGE=1\nSMALL_ICONS=0\nTHICK_BORDER=0\nSOLID_SELECTION=1\n"; } else { - options1=L"CAPTION=1\nUSER_IMAGE=0\nUSER_NAME=0\nCENTER_NAME=0\nSMALL_ICONS=0\nTHICK_BORDER=0\nSOLID_SELECTION=0"; - options2=L"NO_ICONS=1\nUSER_IMAGE=1\nUSER_NAME=0\nCENTER_NAME=0\nSMALL_ICONS=0\nTHICK_BORDER=0\nSOLID_SELECTION=0"; - options3=L"USER_IMAGE=1\nSMALL_ICONS=0\nTHICK_BORDER=0\nSOLID_SELECTION=0"; + options1=L"CAPTION=1\nUSER_IMAGE=0\nUSER_NAME=0\nCENTER_NAME=0\nSMALL_ICONS=0\nTHICK_BORDER=0\nSOLID_SELECTION=0\n"; + options2=L"NO_ICONS=1\nUSER_IMAGE=1\nUSER_NAME=0\nCENTER_NAME=0\nSMALL_ICONS=0\nTHICK_BORDER=0\nSOLID_SELECTION=0\n"; + options3=L"USER_IMAGE=1\nSMALL_ICONS=0\nTHICK_BORDER=0\nSOLID_SELECTION=0\n"; } } else if (GetWinVersion() Date: Wed, 30 Nov 2022 19:02:42 +0100 Subject: [PATCH 08/12] Make debugging more skin friendly Debug StartMenuDLL used to not find skins when put to Open-Shell installation folder. Now it will try to look for skins in default location (Skins folder in the same folder as DLL) and use alternative (Skins folder one level up) if not present. --- Src/StartMenu/StartMenuDLL/SkinManager.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Src/StartMenu/StartMenuDLL/SkinManager.cpp b/Src/StartMenu/StartMenuDLL/SkinManager.cpp index 213a09d8e..41b6e9ba6 100644 --- a/Src/StartMenu/StartMenuDLL/SkinManager.cpp +++ b/Src/StartMenu/StartMenuDLL/SkinManager.cpp @@ -3235,10 +3235,14 @@ void GetSkinsPath( wchar_t *path ) { GetModuleFileName(g_Instance,path,_MAX_PATH); *PathFindFileName(path)=0; -#ifdef BUILD_SETUP Strcat(path,_MAX_PATH,L"Skins\\"); -#else - Strcat(path,_MAX_PATH,L"..\\Skins\\"); + +#ifndef BUILD_SETUP + if (!PathIsDirectory(path)) + { + *PathFindFileName(path) = 0; + Strcat(path,_MAX_PATH,L"..\\Skins\\"); + } #endif } From 7189497b28831e6c4a4b20480ab08751a059cb4e Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sat, 12 Nov 2022 19:54:29 +0100 Subject: [PATCH 09/12] Windows 11 start menu button support - handling of `Taskbar alignment` setting (left/center) - start menu position is based on position of start button - mouse clicks to original button now work properly (without triggering original menu) - custom button is properly positioned - Win+X works properly --- Src/Lib/ResourceHelper.cpp | 41 ++ Src/Lib/ResourceHelper.h | 9 + Src/StartMenu/StartMenuDLL/MenuContainer.cpp | 24 +- Src/StartMenu/StartMenuDLL/StartButton.cpp | 50 +-- Src/StartMenu/StartMenuDLL/StartButton.h | 2 +- Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp | 373 +++++++++++-------- Src/StartMenu/StartMenuDLL/StartMenuDLL.h | 6 +- 7 files changed, 295 insertions(+), 210 deletions(-) diff --git a/Src/Lib/ResourceHelper.cpp b/Src/Lib/ResourceHelper.cpp index d7f7db6ea..525facfbd 100644 --- a/Src/Lib/ResourceHelper.cpp +++ b/Src/Lib/ResourceHelper.cpp @@ -733,6 +733,19 @@ bool IsWin10RS4( void ) return bIsRS4; } +static bool IsWin11Helper() +{ + auto version = GetOSVersion(); + return version.dwMajorVersion >= 10 && version.dwBuildNumber >= 22000; +} + +// Returns true if the version is Windows11 or later +bool IsWin11(void) +{ + static bool bIsWin11 = IsWin11Helper(); + return bIsWin11; +} + // Wrapper for IShellFolder::ParseDisplayName HRESULT ShParseDisplayName( const wchar_t *pszName, PIDLIST_ABSOLUTE *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut ) { @@ -909,3 +922,31 @@ HFONT CreateFontSetting( const wchar_t *fontStr, int dpi ) int size=-_wtol(token); return CreateFont(size*dpi/72,0,0,0,weight,bItalic?1:0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,name); } + +static UINT WINAPI GetDpiForWindow(HWND hwnd) +{ + static auto p = static_cast((void*)GetProcAddress(GetModuleHandle(L"user32.dll"), "GetDpiForWindow")); + if (p) + return p(hwnd); + + return 0; +} + +UINT GetDpi(HWND hwnd) +{ + UINT dpi = GetDpiForWindow(hwnd); + if (!dpi) + { + // fall-back for older systems + HDC hdc = GetDC(nullptr); + dpi = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(nullptr, hdc); + } + + return dpi; +} + +int ScaleForDpi(HWND hwnd, int value) +{ + return MulDiv(value, GetDpi(hwnd), USER_DEFAULT_SCREEN_DPI); +} diff --git a/Src/Lib/ResourceHelper.h b/Src/Lib/ResourceHelper.h index ac7399acd..d44eb6b59 100644 --- a/Src/Lib/ResourceHelper.h +++ b/Src/Lib/ResourceHelper.h @@ -67,6 +67,9 @@ bool IsWin10RS1( void ); // Returns true if the version is Windows10 RS4 (Spring Creator Update) or later bool IsWin10RS4( void ); +// Returns true if the version is Windows11 or later +bool IsWin11(); + // Wrapper for IShellFolder::ParseDisplayName HRESULT ShParseDisplayName( const wchar_t *pszName, PIDLIST_ABSOLUTE *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut ); @@ -82,6 +85,12 @@ void StringUpper( CString &str ); // Create a font from the user settings HFONT CreateFontSetting( const wchar_t *fontStr, int dpi ); +// Return DPI of given window (or system DPI on older systems) +UINT GetDpi(HWND hwnd = nullptr); + +// Scale given value according to DPI of window +int ScaleForDpi(HWND hwnd, int value); + extern HINSTANCE g_Instance; const int ANIM_BUTTON_TAG1='ANM'; diff --git a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp index 1f7788b44..0de4d05a0 100644 --- a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp +++ b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp @@ -345,7 +345,8 @@ bool CMenuContainer::s_bMRULoaded=false; const CItemManager::ItemInfo *CMenuContainer::s_JumpAppInfo; CJumpList CMenuContainer::s_JumpList; int CMenuContainer::s_TaskBarId; -HWND CMenuContainer::s_TaskBar, CMenuContainer::s_StartButton; +HWND CMenuContainer::s_TaskBar; +HWND CMenuContainer::s_StartButton; // custom start button (if any) UINT CMenuContainer::s_TaskBarEdge; RECT CMenuContainer::s_StartRect; HWND CMenuContainer::s_LastFGWindow; @@ -7507,6 +7508,7 @@ RECT CMenuContainer::CalculateWorkArea( const RECT &taskbarRect ) return rc; } +// Calculates start menu position POINT CMenuContainer::CalculateCorner( void ) { RECT margin={0,0,0,0}; @@ -7514,10 +7516,24 @@ POINT CMenuContainer::CalculateCorner( void ) AdjustWindowRect(&margin,GetWindowLong(GWL_STYLE),FALSE); POINT corner; - if (m_Options&CONTAINER_LEFT) - corner.x=s_MainMenuLimits.left+margin.left; + if (IsWin11()) + { + // start button can be in the center on Win11 + // we want to show menu at the position of start button + if (m_Options&CONTAINER_LEFT) + corner.x=s_StartRect.left+margin.left; + else + corner.x=s_StartRect.right+margin.right; + } else - corner.x=s_MainMenuLimits.right+margin.right; + { + // start button can be only in corner on older systems + // we can use screen limits to determine menu position + if (m_Options&CONTAINER_LEFT) + corner.x=s_MainMenuLimits.left+margin.left; + else + corner.x=s_MainMenuLimits.right+margin.right; + } if (m_Options&CONTAINER_TOP) { diff --git a/Src/StartMenu/StartMenuDLL/StartButton.cpp b/Src/StartMenu/StartMenuDLL/StartButton.cpp index 074827410..0ea3dc601 100644 --- a/Src/StartMenu/StartMenuDLL/StartButton.cpp +++ b/Src/StartMenu/StartMenuDLL/StartButton.cpp @@ -154,6 +154,7 @@ LRESULT CStartButton::OnCreate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& b OnThemeChanged(WM_THEMECHANGED,0,0,bHandled); m_bPressed=true; SetPressed(false); + ResizeClient(m_Size.cx,m_Size.cy); bHandled=FALSE; return 0; } @@ -534,12 +535,12 @@ void CStartButton::LoadBitmap( void ) if (!m_Bitmap) { int id; - int dpi=CItemManager::GetDPI(false); + int dpi=GetDpi(GetParent()); if (dpi<120) id=IDB_BUTTON96; else if (dpi<144) id=IDB_BUTTON120; - else if (dpi<180) + else if (dpi<168) id=IDB_BUTTON144; else id=IDB_BUTTON180; @@ -604,55 +605,12 @@ void CStartButton::LoadBitmap( void ) static std::map g_StartButtons; -HWND CreateStartButton( int taskbarId, HWND taskBar, HWND rebar, const RECT &rcTask ) +HWND CreateStartButton( int taskbarId, HWND taskBar, HWND rebar ) { bool bRTL=(GetWindowLongPtr(rebar,GWL_EXSTYLE)&WS_EX_LAYOUTRTL)!=0; DWORD styleTopmost=GetWindowLongPtr(taskBar,GWL_EXSTYLE)&WS_EX_TOPMOST; CStartButton &button=g_StartButtons[taskbarId]; button.Create(taskBar,NULL,NULL,WS_POPUP,styleTopmost|WS_EX_TOOLWINDOW|WS_EX_LAYERED,0U,(void*)(intptr_t)(taskbarId*2+(bRTL?1:0))); - SIZE size=button.GetSize(); - RECT rcButton; - MONITORINFO info; - UINT uEdge=GetTaskbarPosition(taskBar,&info,NULL,NULL); - if (uEdge==ABE_LEFT || uEdge==ABE_RIGHT) - { - if (GetSettingInt(L"StartButtonType")!=START_BUTTON_CUSTOM || !GetSettingBool(L"StartButtonAlign")) - rcButton.left=(rcTask.left+rcTask.right-size.cx)/2; - else if (uEdge==ABE_LEFT) - rcButton.left=rcTask.left; - else - rcButton.left=rcTask.right-size.cx; - rcButton.top=rcTask.top; - } - else - { - if (bRTL) - rcButton.left=rcTask.right-size.cx; - else - rcButton.left=rcTask.left; - if (GetSettingInt(L"StartButtonType")!=START_BUTTON_CUSTOM || !GetSettingBool(L"StartButtonAlign")) - rcButton.top=(rcTask.top+rcTask.bottom-size.cy)/2; - else if (uEdge==ABE_TOP) - rcButton.top=rcTask.top; - else - rcButton.top=rcTask.bottom-size.cy; - } - rcButton.right=rcButton.left+size.cx; - rcButton.bottom=rcButton.top+size.cy; - g_bAllowMoveButton=true; - button.SetWindowPos(HWND_TOP,&rcButton,SWP_SHOWWINDOW|SWP_NOOWNERZORDER|SWP_NOACTIVATE); - g_bAllowMoveButton=false; - - RECT rc; - IntersectRect(&rc,&rcButton,&info.rcMonitor); - HRGN rgn=CreateRectRgn(rc.left-rcButton.left,rc.top-rcButton.top,rc.right-rcButton.left,rc.bottom-rcButton.top); - if (!SetWindowRgn(button,rgn,FALSE)) - { - AddTrackedObject(rgn); - DeleteObject(rgn); - } - - button.UpdateButton(); return button.m_hWnd; } diff --git a/Src/StartMenu/StartMenuDLL/StartButton.h b/Src/StartMenu/StartMenuDLL/StartButton.h index 13b8686d4..7ff7ffb43 100644 --- a/Src/StartMenu/StartMenuDLL/StartButton.h +++ b/Src/StartMenu/StartMenuDLL/StartButton.h @@ -12,7 +12,7 @@ enum TStartButtonType // START_BUTTON_METRO, }; -HWND CreateStartButton( int taskbarId, HWND taskBar, HWND rebar, const RECT &rcTask ); +HWND CreateStartButton( int taskbarId, HWND taskBar, HWND rebar ); void DestroyStartButton( int taskbarId ); void UpdateStartButton( int taskbarId ); void PressStartButton( int taskbarId, bool bPressed ); diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp b/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp index cdeca188b..6a0ec530a 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp @@ -47,7 +47,7 @@ static HWND g_Tooltip; static TOOLINFO g_StartButtonTool; static bool g_bHotkeyShift; static int g_HotkeyCSM, g_HotkeyWSM, g_HotkeyShiftID, g_HotkeyCSMID, g_HotkeyWSMID; -static HHOOK g_ProgHook, g_StartHook, g_AppManagerHook, g_NewWindowHook, g_StartMenuHook; +static HHOOK g_ProgHook, g_StartHook, g_StartMouseHook, g_AppManagerHook, g_NewWindowHook, g_StartMenuHook; static bool g_bAllProgramsTimer; static bool g_bInMenu; static DWORD g_LastClickTime; @@ -402,6 +402,7 @@ static TaskbarInfo *FindTaskBarInfoBar( HWND bar ) static LRESULT CALLBACK HookProgManThread( int code, WPARAM wParam, LPARAM lParam ); static LRESULT CALLBACK HookDesktopThread( int code, WPARAM wParam, LPARAM lParam ); +static LRESULT CALLBACK HookDesktopThreadMouse(int code, WPARAM wParam, LPARAM lParam); static BOOL CALLBACK FindTooltipEnum( HWND hwnd, LPARAM lParam ) { @@ -671,21 +672,45 @@ UINT GetTaskbarPosition( HWND taskBar, MONITORINFO *pInfo, HMONITOR *pMonitor, R bool PointAroundStartButton( size_t taskbarId, const CPoint &pt ) { const TaskbarInfo *taskBar=GetTaskbarInfo(taskbarId); - if (!taskBar || !taskBar->startButton) return false; - RECT rc; + if (!taskBar || !(taskBar->startButton || taskBar->oldButton)) return false; + CRect rc; GetWindowRect(taskBar->taskBar,&rc); if (!PtInRect(&rc,pt)) return false; - UINT uEdge=GetTaskbarPosition(taskBar->taskBar,NULL,NULL,NULL); + bool rtl=GetWindowLongPtr(taskBar->taskBar,GWL_EXSTYLE)&WS_EX_LAYOUTRTL; + + CRect rcStart; + if (taskBar->startButton) + GetWindowRect(taskBar->startButton,&rcStart); + + CRect rcOld; + if (taskBar->oldButton) + { + GetWindowRect(taskBar->oldButton,&rcOld); + + if (IsWin11()) + { + // on Win11 the Start button rectangle is a bit smaller that actual XAML active area + // lets make it a bit wider to avoid accidental original Start menu triggers + const int adjust=ScaleForDpi(taskBar->taskBar,1); + if (rtl) + rcOld.left-=adjust; + else + rcOld.right+=adjust; + } + } + + rc.UnionRect(&rcStart,&rcOld); + // check if the point is inside the start button rect - GetWindowRect(taskBar->startButton,&rc); + UINT uEdge=GetTaskbarPosition(taskBar->taskBar,NULL,NULL,NULL); if (uEdge==ABE_LEFT || uEdge==ABE_RIGHT) - return pt.ytaskBar,GWL_EXSTYLE)&WS_EX_LAYOUTRTL) - return pt.x>rc.left; + return pt.y>=rc.top && pt.yrc.left && pt.x<=rc.right; else - return pt.x=rc.left && pt.xtaskbarId) != IsTaskbarSmallIcons()) + RecreateStartButton(taskBar->taskbarId); + + RECT rcTask; + GetWindowRect(taskBar->taskBar, &rcTask); + MONITORINFO info; + UINT uEdge = GetTaskbarPosition(taskBar->taskBar, &info, NULL, NULL); + DWORD buttonFlags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE; + if (IsWindowVisible(taskBar->taskBar)) + buttonFlags |= SWP_SHOWWINDOW; + else + buttonFlags |= SWP_HIDEWINDOW; + + APPBARDATA appbar = { sizeof(appbar) }; + if (SHAppBarMessage(ABM_GETSTATE, &appbar) & ABS_AUTOHIDE) + { + bool bHide = false; + if (uEdge == ABE_LEFT) + bHide = (rcTask.right < info.rcMonitor.left + 5); + else if (uEdge == ABE_RIGHT) + bHide = (rcTask.left > info.rcMonitor.right - 5); + else if (uEdge == ABE_TOP) + bHide = (rcTask.bottom < info.rcMonitor.top + 5); + else + bHide = (rcTask.top > info.rcMonitor.bottom - 5); + if (bHide) + buttonFlags = (buttonFlags & ~SWP_SHOWWINDOW) | SWP_HIDEWINDOW; + } + if (uEdge == ABE_TOP || uEdge == ABE_BOTTOM) + { + if (rcTask.left < info.rcMonitor.left) rcTask.left = info.rcMonitor.left; + if (rcTask.right > info.rcMonitor.right) rcTask.right = info.rcMonitor.right; + } + else + { + if (rcTask.top < info.rcMonitor.top) rcTask.top = info.rcMonitor.top; + } + + HWND zPos = NULL; + if (pPos->flags & SWP_NOZORDER) + buttonFlags |= SWP_NOZORDER; + else + { + zPos = pPos->hwndInsertAfter; + if (zPos == HWND_TOP && !(GetWindowLongPtr(taskBar->startButton, GWL_EXSTYLE) & WS_EX_TOPMOST)) + zPos = HWND_TOPMOST; + if (zPos == HWND_TOPMOST && !(GetWindowLongPtr(taskBar->taskBar, GWL_EXSTYLE) & WS_EX_TOPMOST)) + zPos = HWND_TOP; + if (zPos == HWND_BOTTOM) + buttonFlags |= SWP_NOZORDER; + if (zPos == taskBar->startButton) + buttonFlags |= SWP_NOZORDER; + } + + if (!IsStartButtonSmallIcons(taskBar->taskbarId)) + { + bool bClassic; + if (GetWinVersion() < WIN_VER_WIN8) + bClassic = !IsAppThemed(); + else + { + HIGHCONTRAST contrast = { sizeof(contrast) }; + bClassic = (SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(contrast), &contrast, 0) && (contrast.dwFlags & HCF_HIGHCONTRASTON)); + } + if (!bClassic) + { + if (uEdge == ABE_TOP) + OffsetRect(&rcTask, 0, -1); + else if (uEdge == ABE_BOTTOM) + OffsetRect(&rcTask, 0, 1); + } + } + + RECT rcOldButton; + if (taskBar->oldButton) + GetWindowRect(taskBar->oldButton, &rcOldButton); + + int x, y; + if (uEdge == ABE_LEFT || uEdge == ABE_RIGHT) + { + if (GetSettingInt(L"StartButtonType") != START_BUTTON_CUSTOM || !GetSettingBool(L"StartButtonAlign")) + x = (rcTask.left + rcTask.right - taskBar->startButtonSize.cx) / 2; + else if (uEdge == ABE_LEFT) + x = rcTask.left; + else + x = rcTask.right - taskBar->startButtonSize.cx; + y = taskBar->oldButton ? rcOldButton.top : rcTask.top; + } + else + { + if (GetWindowLongPtr(taskBar->rebar, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) + x = (taskBar->oldButton ? rcOldButton.right : rcTask.right) - taskBar->startButtonSize.cx; + else + x = taskBar->oldButton ? rcOldButton.left : rcTask.left; + if (GetSettingInt(L"StartButtonType") != START_BUTTON_CUSTOM || !GetSettingBool(L"StartButtonAlign")) + y = (rcTask.top + rcTask.bottom - taskBar->startButtonSize.cy) / 2; + else if (uEdge == ABE_TOP) + y = rcTask.top; + else + y = rcTask.bottom - taskBar->startButtonSize.cy; + } + + // Start button on Win11 is a bit shifted to the right + // We will shift our Aero button to cover original button + if (IsWin11() && (x == 0) && (GetStartButtonType() == START_BUTTON_AERO)) + x += ScaleForDpi(taskBar->taskBar, 6); + + RECT rcButton = { x, y, x + taskBar->startButtonSize.cx, y + taskBar->startButtonSize.cy }; + RECT rc; + IntersectRect(&rc, &rcButton, &info.rcMonitor); + HRGN rgn = CreateRectRgn(rc.left - x, rc.top - y, rc.right - x, rc.bottom - y); + if (!SetWindowRgn(taskBar->startButton, rgn, FALSE)) + { + AddTrackedObject(rgn); + DeleteObject(rgn); + } + + SetWindowPos(taskBar->startButton, zPos, x, y, 0, 0, buttonFlags); + + if (buttonFlags & SWP_SHOWWINDOW) + UpdateStartButton(taskBar->taskbarId); +} + static LRESULT CALLBACK SubclassWin81StartButton( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) { + TaskbarInfo* taskBar = GetTaskbarInfo((int)dwRefData); + if (uMsg==WM_WINDOWPOSCHANGING) { // keep the original start button hidden at all times - const TaskbarInfo *taskBar=GetTaskbarInfo((int)dwRefData); if (taskBar && taskBar->bHideButton) { ((WINDOWPOS*)lParam)->flags&=~SWP_SHOWWINDOW; } } + if (uMsg==WM_WINDOWPOSCHANGED) + { + if (taskBar && taskBar->bReplaceButton) + { + UpdateStartButtonPosition(taskBar,(WINDOWPOS*)lParam); + } + } if (uMsg==WM_SIZE) { RECT rc; GetWindowRect(hWnd,&rc); rc.right-=rc.left; rc.bottom-=rc.top; - TaskbarInfo *taskBar=GetTaskbarInfo((int)dwRefData); if (taskBar && (taskBar->oldButtonSize.cx!=rc.right || taskBar->oldButtonSize.cy!=rc.bottom)) { taskBar->oldButtonSize.cx=rc.right; @@ -1467,6 +1624,15 @@ static void ComputeTaskbarColors( int *data ) static void ShowWinX( void ) { + if (IsWin11()) + { + HWND hwnd=FindWindowEx(NULL,NULL,L"Shell_TrayWnd",NULL); + if (hwnd) + PostMessage(hwnd,WM_HOTKEY,590,MAKELPARAM(MOD_WIN,'X')); + + return; + } + if (GetWinVersion()>=WIN_VER_WIN10) { CComPtr pImmersiveShell; @@ -1651,116 +1817,7 @@ static LRESULT CALLBACK SubclassTaskBarProc( HWND hWnd, UINT uMsg, WPARAM wParam { if (taskBar->bReplaceButton) { - if (IsStartButtonSmallIcons(taskBar->taskbarId)!=IsTaskbarSmallIcons()) - RecreateStartButton((int)dwRefData); - - WINDOWPOS *pPos=(WINDOWPOS*)lParam; - RECT rcTask; - GetWindowRect(hWnd,&rcTask); - MONITORINFO info; - UINT uEdge=GetTaskbarPosition(hWnd,&info,NULL,NULL); - DWORD buttonFlags=SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE; - if (IsWindowVisible(taskBar->taskBar)) - buttonFlags|=SWP_SHOWWINDOW; - else - buttonFlags|=SWP_HIDEWINDOW; - - APPBARDATA appbar={sizeof(appbar)}; - if (SHAppBarMessage(ABM_GETSTATE,&appbar)&ABS_AUTOHIDE) - { - bool bHide=false; - if (uEdge==ABE_LEFT) - bHide=(rcTask.rightinfo.rcMonitor.right-5); - else if (uEdge==ABE_TOP) - bHide=(rcTask.bottominfo.rcMonitor.bottom-5); - if (bHide) - buttonFlags=(buttonFlags&~SWP_SHOWWINDOW)|SWP_HIDEWINDOW; - } - if (uEdge==ABE_TOP || uEdge==ABE_BOTTOM) - { - if (rcTask.leftinfo.rcMonitor.right) rcTask.right=info.rcMonitor.right; - } - else - { - if (rcTask.toptaskbarId)) - { - bool bClassic; - if (GetWinVersion()flags&SWP_NOZORDER) - buttonFlags|=SWP_NOZORDER; - else - { - zPos=pPos->hwndInsertAfter; - if (zPos==HWND_TOP && !(GetWindowLongPtr(taskBar->startButton,GWL_EXSTYLE)&WS_EX_TOPMOST)) - zPos=HWND_TOPMOST; - if (zPos==HWND_TOPMOST && !(GetWindowLongPtr(hWnd,GWL_EXSTYLE)&WS_EX_TOPMOST)) - zPos=HWND_TOP; - if (zPos==HWND_BOTTOM) - buttonFlags|=SWP_NOZORDER; - if (zPos==taskBar->startButton) - buttonFlags|=SWP_NOZORDER; - } - - int x, y; - if (uEdge==ABE_LEFT || uEdge==ABE_RIGHT) - { - if (GetSettingInt(L"StartButtonType")!=START_BUTTON_CUSTOM || !GetSettingBool(L"StartButtonAlign")) - x=(rcTask.left+rcTask.right-taskBar->startButtonSize.cx)/2; - else if (uEdge==ABE_LEFT) - x=rcTask.left; - else - x=rcTask.right-taskBar->startButtonSize.cx; - y=rcTask.top; - } - else - { - if (GetWindowLongPtr(taskBar->rebar,GWL_EXSTYLE)&WS_EX_LAYOUTRTL) - x=rcTask.right-taskBar->startButtonSize.cx; - else - x=rcTask.left; - if (GetSettingInt(L"StartButtonType")!=START_BUTTON_CUSTOM || !GetSettingBool(L"StartButtonAlign")) - y=(rcTask.top+rcTask.bottom-taskBar->startButtonSize.cy)/2; - else if (uEdge==ABE_TOP) - y=rcTask.top; - else - y=rcTask.bottom-taskBar->startButtonSize.cy; - } - RECT rcButton={x,y,x+taskBar->startButtonSize.cx,y+taskBar->startButtonSize.cy}; - RECT rc; - IntersectRect(&rc,&rcButton,&info.rcMonitor); - HRGN rgn=CreateRectRgn(rc.left-x,rc.top-y,rc.right-x,rc.bottom-y); - if (!SetWindowRgn(taskBar->startButton,rgn,FALSE)) - { - AddTrackedObject(rgn); - DeleteObject(rgn); - } - g_bAllowMoveButton=true; - SetWindowPos(taskBar->startButton,zPos,x,y,0,0,buttonFlags); - g_bAllowMoveButton=false; - if (buttonFlags&SWP_SHOWWINDOW) - UpdateStartButton(taskBar->taskbarId); + UpdateStartButtonPosition(taskBar,(WINDOWPOS*)lParam); } if (taskBar->oldButton && GetWinVersion()info.rcMonitor.right) rcTask2.right=info.rcMonitor.right; - } - else - { - if (rcTask2.topRelease(); @@ -3050,6 +3077,8 @@ static void RecreateStartButton( size_t taskbarId ) taskBar.oldButtonSize.cy=rc.bottom-rc.top; } + RECT rcTask; + GetWindowRect(taskBar.taskBar,&rcTask); PostMessage(taskBar.taskBar,WM_SIZE,SIZE_RESTORED,MAKELONG(rcTask.right-rcTask.left,rcTask.bottom-rcTask.top)); } } @@ -3099,6 +3128,8 @@ static void CleanStartMenuDLL( void ) HWND hwnd=FindWindow(L"OpenShellMenu.CStartHookWindow",L"StartHookWindow"); UnhookWindowsHookEx(g_ProgHook); UnhookWindowsHookEx(g_StartHook); + if (g_StartMouseHook) UnhookWindowsHookEx(g_StartMouseHook); + g_StartMouseHook=NULL; if (g_AppManagerHook) UnhookWindowsHookEx(g_AppManagerHook); g_AppManagerHook=NULL; if (g_NewWindowHook) UnhookWindowsHookEx(g_NewWindowHook); @@ -3120,7 +3151,8 @@ static void CleanStartMenuDLL( void ) if (it->second.oldButton) { RemoveWindowSubclass(it->second.oldButton,SubclassWin81StartButton,'CLSH'); - SetWindowPos(it->second.oldButton,NULL,0,0,0,0,SWP_NOSIZE|SWP_NOZORDER); + if (GetWinVersion()second.taskBar,NULL,NULL,NULL)==ABE_BOTTOM) + SetWindowPos(it->second.oldButton,NULL,0,0,0,0,SWP_NOSIZE|SWP_NOZORDER); RevokeDragDrop(it->second.oldButton); if (it->second.pOriginalTarget) RegisterDragDrop(it->second.oldButton,it->second.pOriginalTarget); @@ -3383,6 +3415,35 @@ static LRESULT CALLBACK HookProgManThread( int code, WPARAM wParam, LPARAM lPara return CallNextHookEx(NULL,code,wParam,lParam); } +// WH_MOUSE hook for taskbar thread (Win11+) +static LRESULT CALLBACK HookDesktopThreadMouse(int code, WPARAM wParam, LPARAM lParam) +{ + if (code == HC_ACTION) + { + // we need to steal mouse messages that are issues in start button area + // so that they won't get to XAML framework that is handling original start button + auto info = (const MOUSEHOOKSTRUCT*)lParam; + { + auto taskBar = FindTaskBarInfoButton(info->hwnd); // click on start button + if (!taskBar) + { + taskBar = FindTaskBarInfoBar(GetAncestor(info->hwnd, GA_ROOT)); // click on taskbar + if (taskBar && !PointAroundStartButton(taskBar->taskbarId)) + taskBar = NULL; + } + + if (taskBar && (info->hwnd != taskBar->startButton) && taskBar->oldButton) + { + // steal messages from other than our custom button window + PostMessage(taskBar->oldButton, (UINT)wParam, 0, MAKELPARAM(info->pt.x, info->pt.y)); + return 1; + } + } + } + + return CallNextHookEx(NULL, code, wParam, lParam); +} + // WH_GETMESSAGE hook for the taskbar thread static LRESULT CALLBACK HookDesktopThread( int code, WPARAM wParam, LPARAM lParam ) { diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.h b/Src/StartMenu/StartMenuDLL/StartMenuDLL.h index 2601727e9..fb27b980a 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.h +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.h @@ -51,7 +51,7 @@ struct TaskbarInfo int taskbarId; HWND taskBar; HWND startButton; // either own start button or the win7 start button (depending on bReplaceButton) - HWND oldButton; // win81 start button (child of taskBar) + HWND oldButton; // win8.1+ start button (child of taskBar) HWND rebar; HWND taskList; HWND chevron; @@ -61,8 +61,8 @@ struct TaskbarInfo int pointerId; bool bTimer; bool bCustomLook; - bool bReplaceButton; - bool bHideButton; + bool bReplaceButton; // replace start button with own one + bool bHideButton; // hide old start button (if we have own button) bool bRecreatingButton; bool bThemeChanging; std::vector trayButtons; // ordered by Z order (for win10) From a0c238f231e04798e3514751f7f7f64c541e2d7b Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Thu, 1 Dec 2022 20:57:24 +0100 Subject: [PATCH 10/12] Properly handle automatically hiding taskbar on multi-monitor setup When taskbar is hidden its window is moved off the screen (except for few pixels at border). It may happen that the taskbar window actually spans to another monitor (though still not visible). MonitorFromWindow API may thus return different monitor handle than the one visible taskbar is on. We will use GetTaskbarPosition function that correctly identifies taskbar's monitor by checking rectangle of visible taskbar. Fixes #908 --- Src/StartMenu/StartMenuDLL/MenuContainer.cpp | 3 +++ Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp index 0de4d05a0..ac9b872a0 100644 --- a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp +++ b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp @@ -7652,6 +7652,9 @@ HWND CMenuContainer::ToggleStartMenu( int taskbarId, bool bKeyboard, bool bAllPr // initialize all settings bool bErr=false; HMONITOR initialMonitor=MonitorFromWindow(s_TaskBar,MONITOR_DEFAULTTONEAREST); + // note: GetTaskbarPosition properly identifies monitor in case of multi-monitor setup and automatic taskbar hiding + GetTaskbarPosition(s_TaskBar,NULL,&initialMonitor,NULL); + int dpi=CItemManager::GetDPI(true); if (!CItemManager::GetDPIOverride() && GetWinVersion()>=WIN_VER_WIN81) { diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp b/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp index 6a0ec530a..8857fa3dc 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp @@ -617,12 +617,12 @@ UINT GetTaskbarPosition( HWND taskBar, MONITORINFO *pInfo, HMONITOR *pMonitor, R if (pRc->right>rc.right) pRc->right=rc.right; } } + HMONITOR monitor=MonitorFromRect(&appbar.rc,MONITOR_DEFAULTTONEAREST); + if (pMonitor) *pMonitor=monitor; if (pInfo) { pInfo->cbSize=sizeof(MONITORINFO); - HMONITOR monitor=MonitorFromRect(&appbar.rc,MONITOR_DEFAULTTONEAREST); GetMonitorInfo(monitor,pInfo); - if (pMonitor) *pMonitor=monitor; } return appbar.uEdge; } From 857627147bf388819b6dcfd3801c43abbdca0ed7 Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sat, 3 Dec 2022 11:27:12 +0100 Subject: [PATCH 11/12] Don't show `Windows Shell Experience Host` in list of frequent programs It is not a program that user will use explicitly. No need to show it in the list even if Windows tracks it as frequent program for some reason. Fixes #1164 --- Src/StartMenu/StartMenuDLL/MenuContainer.cpp | 21 ++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp index ac9b872a0..8d8afc7da 100644 --- a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp +++ b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp @@ -1589,6 +1589,23 @@ static const wchar_t *g_MfuIgnoreExes[]={ L"WUAPP.EXE", }; +static bool IgnoreUserAssistItem(const UserAssistItem& uaItem) +{ + static constexpr const wchar_t* ignoredNames[] = + { + DESKTOP_APP_ID, + L"Microsoft.Windows.ShellExperienceHost_cw5n1h2txyewy!App", + }; + + for (const auto& name : ignoredNames) + { + if (_wcsicmp(uaItem.name, name) == 0) + return true; + } + + return false; +} + void CMenuContainer::GetRecentPrograms( std::vector &items, int maxCount ) { bool bShowMetro=GetSettingBool(L"RecentMetroApps"); @@ -1941,9 +1958,9 @@ void CMenuContainer::GetRecentPrograms( std::vector &items, int maxCou continue; } - if (_wcsicmp(uaItem.name,DESKTOP_APP_ID)==0) + if (IgnoreUserAssistItem(uaItem)) { - LOG_MENU(LOG_MFU,L"UserAssist: Dropping: Ignore desktop"); + LOG_MENU(LOG_MFU,L"UserAssist: Dropping: Ignore '%s'",uaItem.name); continue; } From 7b5787016164109050fcc89def86e545f95138a2 Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sat, 3 Dec 2022 11:46:28 +0100 Subject: [PATCH 12/12] Use `Segoe Fluent Icons` font for modern settings icons on Win11 It seems that Windows 11 prefers `Segoe Fluent Icons` over `Segoe MDL2 Assets` font. https://learn.microsoft.com/en-us/windows/apps/design/style/segoe-fluent-icons-font Most of settings defined in `AllSystemSettings_{253E530E-387D-4BC2-959D-E6F86122E5F2}.xml` now refer to the new font. --- Src/StartMenu/StartMenuHelper/ModernSettingsShellFolder.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Src/StartMenu/StartMenuHelper/ModernSettingsShellFolder.cpp b/Src/StartMenu/StartMenuHelper/ModernSettingsShellFolder.cpp index a9e973ee3..fb2a13e10 100644 --- a/Src/StartMenu/StartMenuHelper/ModernSettingsShellFolder.cpp +++ b/Src/StartMenu/StartMenuHelper/ModernSettingsShellFolder.cpp @@ -9,6 +9,7 @@ #include "stdafx.h" #include "ModernSettings.h" #include "ModernSettingsShellFolder.h" +#include "ResourceHelper.h" #include #include #include @@ -181,7 +182,7 @@ HICON IconFromGlyph(UINT glyph, UINT size) HDC dc = CreateCompatibleDC(nullptr); SelectObject(dc, info.hbmColor); - HFONT font = CreateFontW(size, 0, 0, 0, 400, 0, 0, 0, 1, 0, 0, 0, 0, L"Segoe MDL2 Assets"); + HFONT font = CreateFontW(size, 0, 0, 0, 400, 0, 0, 0, 1, 0, 0, 0, 0, IsWin11() ? L"Segoe Fluent Icons" : L"Segoe MDL2 Assets"); SelectObject(dc, font); RECT rc{};