Skip to content

Commit 04770c4

Browse files
committed
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
1 parent f42980e commit 04770c4

File tree

7 files changed

+295
-210
lines changed

7 files changed

+295
-210
lines changed

Src/Lib/ResourceHelper.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,19 @@ bool IsWin10RS4( void )
733733
return bIsRS4;
734734
}
735735

736+
static bool IsWin11Helper()
737+
{
738+
auto version = GetOSVersion();
739+
return version.dwMajorVersion >= 10 && version.dwBuildNumber >= 22000;
740+
}
741+
742+
// Returns true if the version is Windows11 or later
743+
bool IsWin11(void)
744+
{
745+
static bool bIsWin11 = IsWin11Helper();
746+
return bIsWin11;
747+
}
748+
736749
// Wrapper for IShellFolder::ParseDisplayName
737750
HRESULT ShParseDisplayName( const wchar_t *pszName, PIDLIST_ABSOLUTE *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut )
738751
{
@@ -909,3 +922,31 @@ HFONT CreateFontSetting( const wchar_t *fontStr, int dpi )
909922
int size=-_wtol(token);
910923
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);
911924
}
925+
926+
static UINT WINAPI GetDpiForWindow(HWND hwnd)
927+
{
928+
static auto p = static_cast<decltype(&GetDpiForWindow)>((void*)GetProcAddress(GetModuleHandle(L"user32.dll"), "GetDpiForWindow"));
929+
if (p)
930+
return p(hwnd);
931+
932+
return 0;
933+
}
934+
935+
UINT GetDpi(HWND hwnd)
936+
{
937+
UINT dpi = GetDpiForWindow(hwnd);
938+
if (!dpi)
939+
{
940+
// fall-back for older systems
941+
HDC hdc = GetDC(nullptr);
942+
dpi = GetDeviceCaps(hdc, LOGPIXELSY);
943+
ReleaseDC(nullptr, hdc);
944+
}
945+
946+
return dpi;
947+
}
948+
949+
int ScaleForDpi(HWND hwnd, int value)
950+
{
951+
return MulDiv(value, GetDpi(hwnd), USER_DEFAULT_SCREEN_DPI);
952+
}

Src/Lib/ResourceHelper.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ bool IsWin10RS1( void );
6767
// Returns true if the version is Windows10 RS4 (Spring Creator Update) or later
6868
bool IsWin10RS4( void );
6969

70+
// Returns true if the version is Windows11 or later
71+
bool IsWin11();
72+
7073
// Wrapper for IShellFolder::ParseDisplayName
7174
HRESULT ShParseDisplayName( const wchar_t *pszName, PIDLIST_ABSOLUTE *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut );
7275

@@ -82,6 +85,12 @@ void StringUpper( CString &str );
8285
// Create a font from the user settings
8386
HFONT CreateFontSetting( const wchar_t *fontStr, int dpi );
8487

88+
// Return DPI of given window (or system DPI on older systems)
89+
UINT GetDpi(HWND hwnd = nullptr);
90+
91+
// Scale given value according to DPI of window
92+
int ScaleForDpi(HWND hwnd, int value);
93+
8594
extern HINSTANCE g_Instance;
8695

8796
const int ANIM_BUTTON_TAG1='ANM';

Src/StartMenu/StartMenuDLL/MenuContainer.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,8 @@ bool CMenuContainer::s_bMRULoaded=false;
345345
const CItemManager::ItemInfo *CMenuContainer::s_JumpAppInfo;
346346
CJumpList CMenuContainer::s_JumpList;
347347
int CMenuContainer::s_TaskBarId;
348-
HWND CMenuContainer::s_TaskBar, CMenuContainer::s_StartButton;
348+
HWND CMenuContainer::s_TaskBar;
349+
HWND CMenuContainer::s_StartButton; // custom start button (if any)
349350
UINT CMenuContainer::s_TaskBarEdge;
350351
RECT CMenuContainer::s_StartRect;
351352
HWND CMenuContainer::s_LastFGWindow;
@@ -7507,17 +7508,32 @@ RECT CMenuContainer::CalculateWorkArea( const RECT &taskbarRect )
75077508
return rc;
75087509
}
75097510

7511+
// Calculates start menu position
75107512
POINT CMenuContainer::CalculateCorner( void )
75117513
{
75127514
RECT margin={0,0,0,0};
75137515
if (IsAppThemed())
75147516
AdjustWindowRect(&margin,GetWindowLong(GWL_STYLE),FALSE);
75157517

75167518
POINT corner;
7517-
if (m_Options&CONTAINER_LEFT)
7518-
corner.x=s_MainMenuLimits.left+margin.left;
7519+
if (IsWin11())
7520+
{
7521+
// start button can be in the center on Win11
7522+
// we want to show menu at the position of start button
7523+
if (m_Options&CONTAINER_LEFT)
7524+
corner.x=s_StartRect.left+margin.left;
7525+
else
7526+
corner.x=s_StartRect.right+margin.right;
7527+
}
75197528
else
7520-
corner.x=s_MainMenuLimits.right+margin.right;
7529+
{
7530+
// start button can be only in corner on older systems
7531+
// we can use screen limits to determine menu position
7532+
if (m_Options&CONTAINER_LEFT)
7533+
corner.x=s_MainMenuLimits.left+margin.left;
7534+
else
7535+
corner.x=s_MainMenuLimits.right+margin.right;
7536+
}
75217537

75227538
if (m_Options&CONTAINER_TOP)
75237539
{

Src/StartMenu/StartMenuDLL/StartButton.cpp

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ LRESULT CStartButton::OnCreate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& b
154154
OnThemeChanged(WM_THEMECHANGED,0,0,bHandled);
155155
m_bPressed=true;
156156
SetPressed(false);
157+
ResizeClient(m_Size.cx,m_Size.cy);
157158
bHandled=FALSE;
158159
return 0;
159160
}
@@ -534,12 +535,12 @@ void CStartButton::LoadBitmap( void )
534535
if (!m_Bitmap)
535536
{
536537
int id;
537-
int dpi=CItemManager::GetDPI(false);
538+
int dpi=GetDpi(GetParent());
538539
if (dpi<120)
539540
id=IDB_BUTTON96;
540541
else if (dpi<144)
541542
id=IDB_BUTTON120;
542-
else if (dpi<180)
543+
else if (dpi<168)
543544
id=IDB_BUTTON144;
544545
else
545546
id=IDB_BUTTON180;
@@ -604,55 +605,12 @@ void CStartButton::LoadBitmap( void )
604605

605606
static std::map<int,CStartButton> g_StartButtons;
606607

607-
HWND CreateStartButton( int taskbarId, HWND taskBar, HWND rebar, const RECT &rcTask )
608+
HWND CreateStartButton( int taskbarId, HWND taskBar, HWND rebar )
608609
{
609610
bool bRTL=(GetWindowLongPtr(rebar,GWL_EXSTYLE)&WS_EX_LAYOUTRTL)!=0;
610611
DWORD styleTopmost=GetWindowLongPtr(taskBar,GWL_EXSTYLE)&WS_EX_TOPMOST;
611612
CStartButton &button=g_StartButtons[taskbarId];
612613
button.Create(taskBar,NULL,NULL,WS_POPUP,styleTopmost|WS_EX_TOOLWINDOW|WS_EX_LAYERED,0U,(void*)(intptr_t)(taskbarId*2+(bRTL?1:0)));
613-
SIZE size=button.GetSize();
614-
RECT rcButton;
615-
MONITORINFO info;
616-
UINT uEdge=GetTaskbarPosition(taskBar,&info,NULL,NULL);
617-
if (uEdge==ABE_LEFT || uEdge==ABE_RIGHT)
618-
{
619-
if (GetSettingInt(L"StartButtonType")!=START_BUTTON_CUSTOM || !GetSettingBool(L"StartButtonAlign"))
620-
rcButton.left=(rcTask.left+rcTask.right-size.cx)/2;
621-
else if (uEdge==ABE_LEFT)
622-
rcButton.left=rcTask.left;
623-
else
624-
rcButton.left=rcTask.right-size.cx;
625-
rcButton.top=rcTask.top;
626-
}
627-
else
628-
{
629-
if (bRTL)
630-
rcButton.left=rcTask.right-size.cx;
631-
else
632-
rcButton.left=rcTask.left;
633-
if (GetSettingInt(L"StartButtonType")!=START_BUTTON_CUSTOM || !GetSettingBool(L"StartButtonAlign"))
634-
rcButton.top=(rcTask.top+rcTask.bottom-size.cy)/2;
635-
else if (uEdge==ABE_TOP)
636-
rcButton.top=rcTask.top;
637-
else
638-
rcButton.top=rcTask.bottom-size.cy;
639-
}
640-
rcButton.right=rcButton.left+size.cx;
641-
rcButton.bottom=rcButton.top+size.cy;
642-
g_bAllowMoveButton=true;
643-
button.SetWindowPos(HWND_TOP,&rcButton,SWP_SHOWWINDOW|SWP_NOOWNERZORDER|SWP_NOACTIVATE);
644-
g_bAllowMoveButton=false;
645-
646-
RECT rc;
647-
IntersectRect(&rc,&rcButton,&info.rcMonitor);
648-
HRGN rgn=CreateRectRgn(rc.left-rcButton.left,rc.top-rcButton.top,rc.right-rcButton.left,rc.bottom-rcButton.top);
649-
if (!SetWindowRgn(button,rgn,FALSE))
650-
{
651-
AddTrackedObject(rgn);
652-
DeleteObject(rgn);
653-
}
654-
655-
button.UpdateButton();
656614
return button.m_hWnd;
657615
}
658616

Src/StartMenu/StartMenuDLL/StartButton.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ enum TStartButtonType
1212
// START_BUTTON_METRO,
1313
};
1414

15-
HWND CreateStartButton( int taskbarId, HWND taskBar, HWND rebar, const RECT &rcTask );
15+
HWND CreateStartButton( int taskbarId, HWND taskBar, HWND rebar );
1616
void DestroyStartButton( int taskbarId );
1717
void UpdateStartButton( int taskbarId );
1818
void PressStartButton( int taskbarId, bool bPressed );

0 commit comments

Comments
 (0)