Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

This should actually fix issue #351 #367

Merged
merged 1 commit into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 45 additions & 46 deletions src/TabBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ CTabBar::CTabBar(HINSTANCE hInst)
, m_tabBarDefaultProc(nullptr)
, m_tabBarSpinDefaultProc(nullptr)
, m_spin(nullptr)
, m_bIsSpinVisible(false)
, m_currentHoverTabItem(-1)
, m_bIsCloseHover(false)
, m_whichCloseClickDown(-1)
Expand Down Expand Up @@ -157,7 +156,6 @@ int CTabBar::InsertAtEnd(const wchar_t *subTabName)
// remove the selection so it can be selected properly later.
if (m_nItems == 1)
TabCtrl_SetCurSel(*this, -1);
SubclassSpinBox();
InvalidateRect(*this, nullptr, FALSE);
return index;
}
Expand Down Expand Up @@ -187,7 +185,6 @@ int CTabBar::InsertAfter(int index, const wchar_t *subTabName)
if (m_nItems == 0)
TabCtrl_SetCurSel(*this, -1);
++m_nItems;
SubclassSpinBox();
InvalidateRect(*this, nullptr, FALSE);
return ret;
}
Expand Down Expand Up @@ -405,6 +402,28 @@ LRESULT CTabBar::RunProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PARENTNOTIFY:
{
UINT childMessage = LOWORD(wParam);

switch (childMessage)
{
case WM_CREATE:
{
wchar_t className[100]{};
GetClassName((HWND)lParam, className, _countof(className));
if (wcscmp(UPDOWN_CLASS, className) == 0)
{
SetWindowLongPtr((HWND)lParam, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));

m_tabBarSpinDefaultProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr((HWND)lParam, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(TabBarSpin_Proc)));
m_spin = (HWND)lParam;
}
}
break;
}
}
break;
case WM_ERASEBKGND:
{
HDC hDC = reinterpret_cast<HDC>(wParam);
Expand Down Expand Up @@ -484,7 +503,7 @@ LRESULT CTabBar::RunProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

DrawMainBorder(&dis);

if (m_bIsSpinVisible)
if (IsSpinVisible())
{
RECT rcSpin{};
GetWindowRect(m_spin, &rcSpin);
Expand Down Expand Up @@ -517,7 +536,9 @@ LRESULT CTabBar::RunProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
dis.rcItem.right = min(dis.rcItem.right, rPage.right);
if (dis.rcItem.right != rPage.right || (dis.rcItem.right - dis.rcItem.left) > CDPIAware::Instance().Scale(*this, MIN_TAB_WIDTH))
{
DrawItem(&dis, static_cast<float>(Animator::GetValue(m_animVars[GetIDFromIndex(nTab).GetValue()])));
}
}
}
}
Expand All @@ -538,7 +559,9 @@ LRESULT CTabBar::RunProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
dis.rcItem.right = min(dis.rcItem.right, rPage.right);
if (dis.rcItem.right != rPage.right || (dis.rcItem.right - dis.rcItem.left) > CDPIAware::Instance().Scale(*this, MIN_TAB_WIDTH))
{
DrawItem(&dis, static_cast<float>(Animator::GetValue(m_animVars[GetIDFromIndex(nSel).GetValue()])));
}
}
}
}
Expand Down Expand Up @@ -678,7 +701,7 @@ LRESULT CTabBar::RunProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
auto index = GetTabIndexAt(xPos, yPos);
RECT rcItem{};
TabCtrl_GetItemRect(*this, index, &rcItem);
if (m_bIsSpinVisible)
if (IsSpinVisible())
{
RECT rcSpin{};
GetWindowRect(m_spin, &rcSpin);
Expand Down Expand Up @@ -755,7 +778,7 @@ LRESULT CTabBar::RunProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
RECT rPage{};
GetClientRect(*this, &rPage);
TabCtrl_AdjustRect(*this, FALSE, &rPage);
if (m_bIsSpinVisible)
if (IsSpinVisible())
{
RECT rcSpin{};
GetWindowRect(m_spin, &rcSpin);
Expand Down Expand Up @@ -1273,13 +1296,6 @@ LRESULT CTabBar::TabBarSpin_Proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
{
case WM_PAINT:
{
// as WM_SHOWWINDOW is only ever sent with wParam == FALSE, use WM_PAINT instead
// of WM_SHOWWINDOW with wParam == TRUE
// alternatives might be WM_NCPAINT or 1125, which also both seem to be only
// sent when updown control is unhidden
if (!pTab->m_bIsSpinVisible)
pTab->m_bIsSpinVisible = true;

PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
HDC hdc = ps.hdc;
Expand Down Expand Up @@ -1479,24 +1495,31 @@ LRESULT CTabBar::TabBarSpin_Proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
InvalidateRect(hwnd, nullptr, false);
}
break;
case WM_SHOWWINDOW:
{
if (wParam == FALSE) //< checked and is only ever sent with wParam == FALSE
pTab->m_bIsSpinVisible = false;
else
pTab->m_bIsSpinVisible = true;
break;
}
case WM_DESTROY:
{
pTab->m_bIsSpinVisible = false;
pTab->m_spin = nullptr;
break;
}
default:
break;
}
return CallWindowProc(pTab->m_tabBarSpinDefaultProc, hwnd, message, wParam, lParam);
}

bool CTabBar::IsSpinVisible() const
{
// Tried WM_SHOWWINDOW in TabBarSpin_Proc, but this was only ever sent with wParam == FALSE
// Then tried using WM_PAINT in TabBarSpin_Proc instead of WM_SHOWWINDOW with wParam == TRUE
// This was sent after WM_PAINT in RunProc, thus would create artifacts
// As I couldn't find any proof of guaranteed order, the below should always work

if (!m_spin)
{
return false;
}

LONG spinStyle = GetWindowLong(m_spin, GWL_STYLE);
return (spinStyle & WS_VISIBLE) != 0 ? true : false;
}

DocID CTabBar::GetIDFromIndex(int index) const
Expand Down Expand Up @@ -1534,30 +1557,6 @@ void CTabBar::NotifyTabDelete(int tab)
::SendMessage(m_hParent, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&nmHdr));
}

void CTabBar::SubclassSpinBox()
{
if (m_spin == nullptr)
{
EnumChildWindows(
*this, [](HWND hChild, LPARAM lParam) -> BOOL {
auto pThis = reinterpret_cast<CTabBar *>(lParam);
wchar_t className[100]{};
GetClassName(hChild, className, _countof(className));
if (wcscmp(UPDOWN_CLASS, className) == 0)
{
SetWindowLongPtr(hChild, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pThis));

pThis->m_tabBarSpinDefaultProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hChild, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(TabBarSpin_Proc)));
pThis->m_spin = hChild;
pThis->m_bIsSpinVisible = true;
return FALSE;
}
return TRUE;
},
reinterpret_cast<LPARAM>(this));
}
}

bool CloseButtonZone::IsHit(int x, int y, const RECT &testZone) const
{
if (((x + m_width + m_fromRight) < testZone.right) || (x > (testZone.right - m_fromRight)))
Expand Down
3 changes: 1 addition & 2 deletions src/TabBar.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class CTabBar : public CWindow
int GetTabIndexAt(int x, int y) const;
bool IsPointInParentZone(POINT screenPoint) const;
void NotifyTabDelete(int tab);
void SubclassSpinBox();
bool IsSpinVisible() const;

private:
int m_nItems;
Expand All @@ -145,7 +145,6 @@ class CTabBar : public CWindow
WNDPROC m_tabBarDefaultProc;
WNDPROC m_tabBarSpinDefaultProc;
HWND m_spin;
bool m_bIsSpinVisible;

RECT m_currentHoverTabRect;
int m_currentHoverTabItem;
Expand Down
Loading