Repository navigation
Open
Labels
BugSomething isn't working right.Something isn't working right.
Description
This is a file, patched by Travis that allegedly fixes the issue with the Start button positioning, but I have not tested it.
Could you build a test version so I could assess it?
// Open-Shell (c) 2017-2018, The Open-Shell Team
// Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author
#include "stdafx.h"
#include "resource.h"
#include "Translations.h"
#include "Settings.h"
#include "SettingsUI.h"
#include "ResourceHelper.h"
#include "ItemManager.h"
#include "StartMenuDLL.h"
#include "StartButton.h"
#include "MenuContainer.h"
#include "TouchHelper.h"
#include "dllmain.h"
#include <uxtheme.h>
#include <vsstyle.h>
#include <vssym32.h>
#include <dwmapi.h>
static int START_ICON_SIZE=0;
const int START_BUTTON_PADDING=3;
const int START_BUTTON_OFFSET=0;
const int START_TEXT_PADDING=1;
const int BLEND_PRECISION=1000;
bool g_bAllowMoveButton;
// CStartButton - implementation of a start button (for Windows 8)
class CStartButton: public CWindowImpl<CStartButton>
{
public:
DECLARE_WND_CLASS_EX(L"OpenShell.CStartButton",CS_DBLCLKS,COLOR_MENU)
CStartButton( void );
// message handlers
BEGIN_MSG_MAP( CStartButton )
MESSAGE_HANDLER( WM_CREATE, OnCreate )
MESSAGE_HANDLER( WM_DESTROY, OnDestroy )
MESSAGE_HANDLER( WM_CLOSE, OnClose )
MESSAGE_HANDLER( WM_MOUSEACTIVATE, OnMouseActivate )
MESSAGE_HANDLER( WM_MOUSEMOVE, OnMouseMove )
MESSAGE_HANDLER( WM_ERASEBKGND, OnEraseBkgnd )
MESSAGE_HANDLER( WM_TIMER, OnTimer )
MESSAGE_HANDLER( WM_SETTINGCHANGE, OnSettingChange )
MESSAGE_HANDLER( WM_THEMECHANGED, OnThemeChanged )
MESSAGE_HANDLER( WM_POINTERDOWN, OnPointer )
MESSAGE_HANDLER( WM_POINTERUPDATE, OnPointer )
MESSAGE_HANDLER( WM_POINTERUP, OnPointer )
END_MSG_MAP()
void SetPressed( bool bPressed );
void UpdateButton( void );
void TaskBarMouseMove( void );
SIZE GetSize( void ) const { return m_Size; }
bool GetSmallIcons( void ) const { return m_bSmallIcons; }
protected:
LRESULT OnCreate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
LRESULT OnClose( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { return 0; }
LRESULT OnEraseBkgnd( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { return 1; }
LRESULT OnMouseActivate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { return MA_NOACTIVATE; }
LRESULT OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
LRESULT OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
LRESULT OnSettingChange( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
LRESULT OnThemeChanged( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
LRESULT OnPointer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
private:
enum { TIMER_BLEND=1, TIMER_LEAVE=2 };
size_t m_TaskbarId;
SIZE m_Size;
HBITMAP m_Bitmap, m_Blendmap;
unsigned int *m_Bits, *m_BlendBits;
HICON m_Icon;
HFONT m_Font;
bool m_bHot, m_bPressed;
bool m_bTrackMouse;
bool m_bClassic;
bool m_bRTL;
bool m_bSmallIcons;
int m_HotBlend; // 0..BLEND_PRECISION
CWindow m_Tooltip;
HTHEME m_Theme;
// animations
int m_YOffset;
int m_Frames[3];
struct Animation
{
std::vector<int> frames;
int duration; // in ms
bool bBlend;
};
Animation m_Animations[2];
void ParseAnimation( Animation &animation, const std::vector<unsigned int> &pixels, int &index, int totalFrames );
void LoadBitmap( void );
void SetHot( bool bHot );
};
CStartButton::CStartButton( void )
{
m_Size.cx=m_Size.cy=0;
m_TaskbarId=-1;
m_Bitmap=m_Blendmap=NULL;
m_Bits=m_BlendBits=NULL;
m_Icon=NULL;
m_Font=NULL;
m_bHot=m_bPressed=false;
m_bTrackMouse=false;
m_bClassic=m_bSmallIcons=false;
m_bRTL=false;
m_HotBlend=0;
m_Theme=NULL;
}
LRESULT CStartButton::OnCreate( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
size_t params=(intptr_t)(((CREATESTRUCT*)lParam)->lpCreateParams);
m_bRTL=(params&1)!=0;
m_TaskbarId=params>>1;
m_bSmallIcons=IsTaskbarSmallIcons();
std::vector<HMODULE> modules;
m_Icon=NULL;
START_ICON_SIZE=0;
CString iconPath=GetSettingString(L"StartButtonIcon");
if (_wcsicmp(iconPath,L"none")!=0)
{
START_ICON_SIZE=GetSettingInt(L"StartButtonIconSize");
if (START_ICON_SIZE==0)
START_ICON_SIZE=GetSystemMetrics(m_bSmallIcons?SM_CXSMICON:SM_CXICON);
if (START_ICON_SIZE<8) START_ICON_SIZE=8;
if (START_ICON_SIZE>64) START_ICON_SIZE=64;
m_Icon=LoadIcon(START_ICON_SIZE,iconPath,modules);
for (std::vector<HMODULE>::const_iterator it=modules.begin();it!=modules.end();++it)
FreeLibrary(*it);
if (!m_Icon)
m_Icon=(HICON)LoadImage(g_Instance,MAKEINTRESOURCE(IDI_APPICON),IMAGE_ICON,START_ICON_SIZE,START_ICON_SIZE,LR_DEFAULTCOLOR);
}
int dpi=CItemManager::GetDPI(false);
NONCLIENTMETRICS ncm = { sizeof(NONCLIENTMETRICS) };
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
m_Font = CreateFontIndirect(&ncm.lfCaptionFont);
int val=1;
DwmSetWindowAttribute(m_hWnd,DWMWA_EXCLUDED_FROM_PEEK,&val,sizeof(val));
val=DWMFLIP3D_EXCLUDEABOVE;
DwmSetWindowAttribute(m_hWnd,DWMWA_FLIP3D_POLICY,&val,sizeof(val));
LoadBitmap();
m_Tooltip=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_TRANSPARENT|(m_bRTL?WS_EX_LAYOUTRTL:0),TOOLTIPS_CLASS,NULL,WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP,0,0,0,0,NULL,NULL,g_Instance,NULL);
OnThemeChanged(WM_THEMECHANGED,0,0,bHandled);
m_bPressed=true;
SetPressed(false);
ResizeClient(m_Size.cx,m_Size.cy);
bHandled=FALSE;
return 0;
}
LRESULT CStartButton::OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
if (m_Bitmap) DeleteObject(m_Bitmap);
if (m_Blendmap) DeleteObject(m_Blendmap);
if (m_Icon) DestroyIcon(m_Icon);
if (m_Font) DeleteObject(m_Font);
if (m_Theme) CloseThemeData(m_Theme);
m_Tooltip.DestroyWindow();
KillTimer(TIMER_BLEND);
bHandled=FALSE;
return 0;
}
void CStartButton::UpdateButton( void )
{
BLENDFUNCTION func={AC_SRC_OVER,0,255,AC_SRC_ALPHA};
HDC hSrc=CreateCompatibleDC(NULL);
RECT rc;
GetWindowRect(&rc);
SIZE size={rc.right-rc.left,rc.bottom-rc.top};
if (m_bClassic)
{
if (m_bRTL)
SetLayout(hSrc,LAYOUT_RTL);
HGDIOBJ bmp0=SelectObject(hSrc,m_Blendmap);
RECT rc={0,0,m_Size.cx,m_Size.cy};
FillRect(hSrc,&rc,(HBRUSH)GetStockObject(BLACK_BRUSH));
InflateRect(&rc,-START_BUTTON_OFFSET,-START_BUTTON_OFFSET);
int offset=0;
if (m_Theme)
{
int state=m_bPressed?PBS_PRESSED:(m_bHot?PBS_HOT:PBS_NORMAL);
DrawThemeBackground(m_Theme,hSrc,BP_PUSHBUTTON,state,&rc,NULL);
}
else
{
DrawFrameControl(hSrc,&rc,DFC_BUTTON,DFCS_BUTTONPUSH|(m_bPressed? DFCS_PUSHED:0));
offset=m_bPressed?1:0;
}
if (m_Icon)
DrawIconEx(hSrc,START_BUTTON_PADDING+START_BUTTON_OFFSET+1+offset,(m_Size.cy-START_ICON_SIZE)/2+offset,m_Icon,0,0,0,NULL,DI_NORMAL|DI_NOMIRROR);
rc.left+=START_BUTTON_PADDING+START_ICON_SIZE+START_TEXT_PADDING+2+offset;
rc.top+=START_BUTTON_PADDING+offset;
rc.right-=+START_TEXT_PADDING-offset;
rc.bottom-=START_BUTTON_PADDING-offset;
HFONT font0=(HFONT)SelectObject(hSrc,m_Font);
NONCLIENTMETRICS ncm = { sizeof(NONCLIENTMETRICS) };
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
m_Font = CreateFontIndirect(&ncm.lfCaptionFont);
COLORREF color=GetSysColor(COLOR_BTNTEXT);
if (m_Theme)
{
int state=m_bPressed?PBS_PRESSED:(m_bHot?PBS_HOT:PBS_NORMAL);
if (FAILED(GetThemeColor(m_Theme,BP_PUSHBUTTON,state,TMT_TEXTCOLOR,&color)))
color=GetSysColor(COLOR_BTNTEXT);
}
SetTextColor(hSrc,color);
SetBkMode(hSrc,TRANSPARENT);
CString startStr=GetSettingString(L"StartButtonText");
const wchar_t *startText=startStr;
if (startText[0]=='$')
startText=FindTranslation(startText+1,L"Start");
DrawText(hSrc,startText,-1,&rc,DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER);
SelectObject(hSrc,bmp0);
// mark the button pixels as opaque
for (int y=START_BUTTON_OFFSET;y<m_Size.cy-START_BUTTON_OFFSET;y++)
for (int x=START_BUTTON_OFFSET;x<m_Size.cx-START_BUTTON_OFFSET;x++)
m_BlendBits[y*m_Size.cx+x]|=0xFF000000;
SelectObject(hSrc,m_Blendmap);
POINT pos={0,0};
UpdateLayeredWindow(m_hWnd,NULL,NULL,&size,hSrc,&pos,0,&func,ULW_ALPHA);
SelectObject(hSrc,font0);
SelectObject(hSrc,bmp0);
LoadBitmap();
ResizeClient(m_Size.cx, m_Size.cy);
}
else
{
int image=-1;
int frame1, frame2, blend;
if (m_bPressed) image=m_Frames[2];
else if (m_HotBlend==0) image=m_Frames[0];
else if (m_HotBlend==BLEND_PRECISION) image=m_Frames[1];
else
{
const Animation &animation=m_Animations[m_bHot?0:1];
int count=(int)animation.frames.size()-1;
blend=m_bHot?m_HotBlend:(BLEND_PRECISION-m_HotBlend);
if (count<1 || animation.duration==0)
{
image=m_Frames[m_bHot?1:0];
}
else if (!animation.bBlend)
{
int index=(blend*count+50)/BLEND_PRECISION; // [0..count]
image=animation.frames[index];
}
else
{
int index=(blend*count)/BLEND_PRECISION; // [0..count-1]
blend=(blend*count)%BLEND_PRECISION;
frame1=animation.frames[index];
frame2=animation.frames[index+1];
}
}
if (image!=-1)
{
HGDIOBJ bmp0=SelectObject(hSrc,m_Bitmap);
POINT pos={0,image*m_Size.cy+m_YOffset};
UpdateLayeredWindow(m_hWnd,NULL,NULL,&size,hSrc,&pos,0,&func,ULW_ALPHA);
SelectObject(hSrc,bmp0);
}
else if (m_Bits)
{
// blend the two images
int n=m_Size.cx*m_Size.cy;
int n1=frame1*n;
int n2=frame2*n;
for (int i=0;i<n;i++)
{
unsigned int pixel1=m_Bits[i+n1];
unsigned int pixel2=m_Bits[i+n2];
int a1=(pixel1>>24);
int r1=(pixel1>>16)&255;
int g1=(pixel1>>8)&255;
int b1=(pixel1)&255;
int a2=(pixel2>>24);
int r2=(pixel2>>16)&255;
int g2=(pixel2>>8)&255;
int b2=(pixel2)&255;
int a=a1+(a2-a1)*blend/BLEND_PRECISION;
int r=r1+(r2-r1)*blend/BLEND_PRECISION;
int g=g1+(g2-g1)*blend/BLEND_PRECISION;
int b=b1+(b2-b1)*blend/BLEND_PRECISION;
m_BlendBits[i]=(a<<24)|(r<<16)|(g<<8)|b;
}
HGDIOBJ bmp0=SelectObject(hSrc,m_Blendmap);
POINT pos={0,0};
UpdateLayeredWindow(m_hWnd,NULL,NULL,&size,hSrc,&pos,0,&func,ULW_ALPHA);
SelectObject(hSrc,bmp0);
}
}
DeleteDC(hSrc);
}
void CStartButton::SetHot( bool bHot )
{
if (m_bHot!=bHot)
{
m_bHot=bHot;
if (!m_bPressed)
{
if (bHot)
CMenuContainer::PlayMenuSound(SOUND_BUTTON_HOVER);
SetTimer(TIMER_BLEND,30);
}
}
}
LRESULT CStartButton::OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
SetTimer(TIMER_LEAVE,30);
SetHot(true);
return 0;
}
void CStartButton::TaskBarMouseMove( void )
{
SetHot(true);
SetTimer(CStartButton::TIMER_LEAVE,30);
}
LRESULT CStartButton::OnTimer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
if (wParam==TIMER_BLEND)
{
int duration=m_Animations[m_bHot?0:1].duration;
int blend;
if (duration>0)
{
int dp=(30*BLEND_PRECISION)/duration;
blend=m_HotBlend+(m_bHot?dp:-dp);
if (blend<0) blend=0;
if (blend>BLEND_PRECISION) blend=BLEND_PRECISION;
}
else
{
blend=m_bHot?BLEND_PRECISION:0;
}
if (blend!=m_HotBlend)
{
m_HotBlend=blend;
UpdateButton();
}
else
KillTimer(TIMER_BLEND);
}
else if (wParam==TIMER_LEAVE)
{
CPoint pt(GetMessagePos());
if (WindowFromPoint(pt)!=m_hWnd && !PointAroundStartButton(m_TaskbarId))
{
KillTimer(TIMER_LEAVE);
SetHot(false);
}
}
else
bHandled=FALSE;
return 0;
}
LRESULT CStartButton::OnSettingChange( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
UpdateButton();
bHandled=FALSE;
return 0;
}
LRESULT CStartButton::OnThemeChanged( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
if (m_Theme) CloseThemeData(m_Theme);
m_Theme=NULL;
HIGHCONTRAST contrast={sizeof(contrast)};
if (GetWinVersion()>=WIN_VER_WIN8 && SystemParametersInfo(SPI_GETHIGHCONTRAST,sizeof(contrast),&contrast,0) && (contrast.dwFlags&HCF_HIGHCONTRASTON))
{
// only use themes on Win8 with high contrast
m_Theme=OpenThemeData(m_hWnd,L"button");
UpdateButton();
}
UpdateButton();
return 0;
}
LRESULT CStartButton::OnPointer( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
POINTER_INPUT_TYPE type;
GetPointerType2(GET_POINTERID_WPARAM(wParam),&type);
if (type==PT_TOUCH)
return GetParent().SendMessage(uMsg,wParam,lParam);
bHandled=FALSE;
return 0;
}
void CStartButton::SetPressed( bool bPressed )
{
if (m_bPressed!=bPressed)
{
m_bPressed=bPressed;
m_HotBlend=m_bHot?BLEND_PRECISION:0;
KillTimer(TIMER_BLEND);
TOOLINFO tool={sizeof(tool),TTF_CENTERTIP|TTF_SUBCLASS|TTF_IDISHWND|TTF_TRANSPARENT|(m_bRTL?TTF_RTLREADING:0U),m_hWnd};
tool.uId=(UINT_PTR)m_hWnd;
CString startStr=GetSettingString(L"StartButtonTip");
const wchar_t *startText=startStr;
if (startText[0]=='$')
startText=FindTranslation(startText+1,L"Start");
wchar_t buf[256];
Strcpy(buf,_countof(buf),startText);
DoEnvironmentSubst(buf,_countof(buf));
tool.lpszText=buf;
m_Tooltip.SendMessage(bPressed?TTM_DELTOOL:TTM_ADDTOOL,0,(LPARAM)&tool);
UpdateButton();
}
}
TStartButtonType GetStartButtonType( void )
{
bool bDef;
TStartButtonType buttonType=(TStartButtonType)GetSettingInt(L"StartButtonType",bDef);
if (bDef)
{
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));
}
buttonType=bClassic?START_BUTTON_CLASSIC:START_BUTTON_AERO;
}
return buttonType;
}
void CStartButton::ParseAnimation( Animation &animation, const std::vector<unsigned int> &pixels, int &index, int totalFrames )
{
animation.duration=0;
animation.bBlend=true;
if (index>=(int)pixels.size())
{
animation.frames.clear();
return;
}
animation.duration=((pixels[index]&255)*1000)/60;
animation.bBlend=((pixels[index]>>16)&255)==1;
int ranges=(pixels[index]>>8)&255;
if (ranges>0 && index+ranges<(int)pixels.size())
{
animation.frames.clear();
for (int r=1;r<=ranges;r++)
{
int from=pixels[index+r]&255;
if (from>totalFrames-1) from=totalFrames-1;
int to=(pixels[index+r]>>16)&255;
if (to>totalFrames-1) to=totalFrames-1;
if (from<to)
{
for (int i=from;i<=to;i++)
animation.frames.push_back(i);
}
else if (from>to)
{
for (int i=from;i>=to;i--)
animation.frames.push_back(i);
}
else
{
animation.frames.push_back(from);
}
}
}
index+=ranges+1;
}
void CStartButton::LoadBitmap( void )
{
m_Size.cx=m_Size.cy=0;
if (m_Bitmap) DeleteObject(m_Bitmap);
if (m_Blendmap) DeleteObject(m_Blendmap);
m_Bitmap=m_Blendmap=NULL;
m_Bits=m_BlendBits=NULL;
TStartButtonType buttonType=GetStartButtonType();
m_bClassic=(buttonType==START_BUTTON_CLASSIC);
wchar_t path[_MAX_PATH];
SIZE size={0,0};
if (buttonType==START_BUTTON_CUSTOM)
{
Strcpy(path,_countof(path),GetSettingString(L"StartButtonPath"));
DoEnvironmentSubst(path,_countof(path));
size.cx=GetSettingInt(L"StartButtonSize");
}
m_YOffset=0;
m_Frames[0]=0; // Normal
m_Frames[1]=1; // Hot
m_Frames[2]=2; // Pressed
m_Animations[0].frames.resize(2); m_Animations[0].frames[0]=0; m_Animations[0].frames[1]=1; m_Animations[0].duration=300; m_Animations[0].bBlend=true; // NH
m_Animations[1].frames.resize(2); m_Animations[1].frames[0]=1; m_Animations[1].frames[1]=0; m_Animations[1].duration=300; m_Animations[1].bBlend=true; // HN
if (m_bClassic)
{
// classic theme
HDC hdc=CreateCompatibleDC(NULL);
HFONT font0=(HFONT)SelectObject(hdc,m_Font);
RECT rc={0,0,0,0};
CString startStr=GetSettingString(L"StartButtonText");
const wchar_t *startText=startStr;
if (startText[0]=='$')
startText=FindTranslation(startText+1,L"Start");
DrawText(hdc,startText,-1,&rc,DT_NOPREFIX|DT_SINGLELINE|DT_CALCRECT);
m_Size.cx=rc.right+START_ICON_SIZE+4*START_TEXT_PADDING+6;
m_Size.cy=rc.bottom;
if (m_Size.cy<START_ICON_SIZE) m_Size.cy=START_ICON_SIZE;
m_Size.cy+=2*START_BUTTON_PADDING+2*START_BUTTON_OFFSET;
DeleteDC(hdc);
}
else
{
bool bResource=false;
std::vector<unsigned int> buttonAnim;
if (*path)
{
m_Bitmap=LoadImageFile(path,&size,true,true,&buttonAnim);
}
if (!m_Bitmap)
{
int id;
int dpi=GetDpi(GetParent());
if (dpi<120)
id=IDB_BUTTON96;
else if (dpi<144)
id=IDB_BUTTON120;
else if (dpi<168)
id=IDB_BUTTON144;
else
id=IDB_BUTTON180;
m_Bitmap=LoadImageResource(g_Instance,MAKEINTRESOURCE(id),true,true);
bResource=true;
}
BITMAP info;
GetObject(m_Bitmap,sizeof(info),&info);
m_Size.cx=info.bmWidth;
m_Size.cy=info.bmHeight;
m_Bits=(unsigned int*)info.bmBits;
if (buttonAnim.empty() && info.bmWidth>=10 && (m_Bits[0]&0xFFFFFF)==ANIM_BUTTON_TAG1 && (m_Bits[1]&0xFFFFFF)==ANIM_BUTTON_TAG2)
{
m_YOffset=(m_Bits[2]>>16)&255;
if (m_YOffset>info.bmHeight) m_YOffset=info.bmHeight;
if (m_YOffset>0)
{
int size=info.bmWidth*m_YOffset;
buttonAnim.resize(size);
memcpy(&buttonAnim[0],m_Bits,size*4);
m_Bits+=size;
m_Size.cy=info.bmHeight-m_YOffset;
}
}
if (!buttonAnim.empty())
{
int total=buttonAnim[2]&255;
if (total<1) total=1;
if (total>info.bmHeight-1) total=info.bmHeight-1;
m_Size.cy/=total;
m_Frames[0]=buttonAnim[3]&255; // Normal
if (m_Frames[0]>total-1) m_Frames[0]=total-1;
m_Frames[1]=buttonAnim[4]&255; // Hot
if (m_Frames[1]>total-1) m_Frames[1]=total-1;
m_Frames[2]=buttonAnim[5]&255; // Pressed
if (m_Frames[2]>total-1) m_Frames[2]=total-1;
m_Animations[0].frames[0]=m_Animations[1].frames[1]=m_Frames[0];
m_Animations[0].frames[1]=m_Animations[1].frames[0]=m_Frames[1];
int index=6;
ParseAnimation(m_Animations[0],buttonAnim,index,total);
ParseAnimation(m_Animations[1],buttonAnim,index,total);
}
else
{
m_Size.cy/=3;
}
}
if (m_Size.cx>0)
{
BITMAPINFO bi={0};
bi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth=m_Size.cx;
bi.bmiHeader.biHeight=-m_Size.cy;
bi.bmiHeader.biPlanes=1;
bi.bmiHeader.biBitCount=32;
HDC hdc=CreateCompatibleDC(NULL);
m_Blendmap=CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&m_BlendBits,NULL,0);
DeleteDC(hdc);
}
}
static std::map<int,CStartButton> g_StartButtons;
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)));
return button.m_hWnd;
}
void DestroyStartButton( int taskbarId )
{
std::map<int,CStartButton>::iterator it=g_StartButtons.find(taskbarId);
if (it!=g_StartButtons.end())
{
if (it->second.m_hWnd)
it->second.DestroyWindow();
g_StartButtons.erase(it);
}
}
void UpdateStartButton( int taskbarId )
{
std::map<int,CStartButton>::iterator it=g_StartButtons.find(taskbarId);
if (it!=g_StartButtons.end())
it->second.UpdateButton();
}
void PressStartButton( int taskbarId, bool bPressed )
{
std::map<int,CStartButton>::iterator it=g_StartButtons.find(taskbarId);
if (it!=g_StartButtons.end())
it->second.SetPressed(bPressed);
}
SIZE GetStartButtonSize( int taskbarId )
{
std::map<int,CStartButton>::iterator it=g_StartButtons.find(taskbarId);
if (it!=g_StartButtons.end())
return it->second.GetSize();
SIZE size={0,0};
return size;
}
bool IsStartButtonSmallIcons( int taskbarId )
{
std::map<int,CStartButton>::iterator it=g_StartButtons.find(taskbarId);
if (it!=g_StartButtons.end())
return it->second.GetSmallIcons();
return false;
}
bool IsTaskbarSmallIcons( void )
{
CRegKey regKey;
if (regKey.Open(HKEY_CURRENT_USER,L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced")!=ERROR_SUCCESS)
return true;
DWORD val;
return regKey.QueryDWORDValue(L"TaskbarSmallIcons",val)!=ERROR_SUCCESS || val;
}
void TaskBarMouseMove( int taskbarId )
{
std::map<int,CStartButton>::iterator it=g_StartButtons.find(taskbarId);
if (it!=g_StartButtons.end())
it->second.TaskBarMouseMove();
}
Area of issue
Taskbar
To reproduce
Classic theme
Expected behavior
No response
Open-Shell version
Current
Windows version
Windows 11
Additional context
No response
Metadata
Metadata
Assignees
Labels
BugSomething isn't working right.Something isn't working right.
Activity
OrthodoxWindows commentedon Dec 27, 2025
This needs to be tested. However, it seems more likely that the reason why the version modified by Travis does not have the bug of the start button being offset by one pixel to the right, and that he claims to have compiled his modifications into version 4.4.190 (on the winclassic forum). However, the problem occurs (as mentioned elsewhere) starting with version 4.4.191. Furthermore, Travis claimed (again on the forum) to have modified only StartButton.cpp, as can be seen in the modified version above. However, according to anixx, it seems that StartMenuDLL.cpp is more likely to be the cause.
OrthodoxWindows commentedon Dec 27, 2025
On the other hand, another bug occurs with the classic theme, also concerning the positioning of the start button, which, when the taskbar is set with large icons, is displayed one pixel too high. This occurs in versions later than 4.4.170. I plan to test all versions between 4.4.170 and 4.4.190 to see in which version this bug appears.
Anixx commentedon Jan 28, 2026
It is offset not by 1 pixel but more likely by 3.