mirror of
https://github.com/voiceip/tinyphone
synced 2026-08-07 02:26:03 -04:00
581 lines
17 KiB
C++
581 lines
17 KiB
C++
#include "stdafx.h"
|
|
#include "mainDlg.h"
|
|
#include "ClosableTabCtrl.h"
|
|
#include "VisualStylesXP.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
// _WIN32_WINNT >= 0x0501 (XP only)
|
|
#define _WM_THEMECHANGED 0x031A
|
|
#define _ON_WM_THEMECHANGED() \
|
|
{ _WM_THEMECHANGED, 0, 0, 0, AfxSig_l, \
|
|
(AFX_PMSG)(AFX_PMSGW) \
|
|
(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(void) > (_OnThemeChanged)) \
|
|
},
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CClosableTabCtrl
|
|
|
|
IMPLEMENT_DYNAMIC(CClosableTabCtrl, CTabCtrl)
|
|
|
|
BEGIN_MESSAGE_MAP(CClosableTabCtrl, CTabCtrl)
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_LBUTTONDBLCLK()
|
|
ON_WM_MBUTTONUP()
|
|
ON_WM_CREATE()
|
|
ON_WM_SYSCOLORCHANGE()
|
|
ON_WM_CONTEXTMENU()
|
|
_ON_WM_THEMECHANGED()
|
|
ON_WM_CTLCOLOR_REFLECT()
|
|
ON_WM_CTLCOLOR()
|
|
ON_WM_ERASEBKGND()
|
|
ON_WM_MEASUREITEM()
|
|
ON_WM_MEASUREITEM_REFLECT()
|
|
END_MESSAGE_MAP()
|
|
|
|
CClosableTabCtrl::CClosableTabCtrl()
|
|
{
|
|
m_bCloseable = true;
|
|
memset(&m_iiCloseButton, 0, sizeof m_iiCloseButton);
|
|
m_ptCtxMenu.SetPoint(-1, -1);
|
|
iTabClose = -1;
|
|
}
|
|
|
|
CClosableTabCtrl::~CClosableTabCtrl()
|
|
{
|
|
}
|
|
|
|
void CClosableTabCtrl::GetCloseButtonRect(int iItem, const CRect& rcItem, CRect& rcCloseButton, bool bItemSelected, bool bVistaThemeActive)
|
|
{
|
|
rcCloseButton.top = rcItem.top + 2;
|
|
rcCloseButton.bottom = rcCloseButton.top + (m_iiCloseButton.rcImage.bottom - m_iiCloseButton.rcImage.top);
|
|
rcCloseButton.right = rcItem.right - 2;
|
|
rcCloseButton.left = rcCloseButton.right - (m_iiCloseButton.rcImage.right - m_iiCloseButton.rcImage.left);
|
|
if (bVistaThemeActive)
|
|
rcCloseButton.left -= 1; // the close button does not look 'symetric' with a width of 16, give it 17
|
|
if (bItemSelected) {
|
|
rcCloseButton.OffsetRect(-1, 0);
|
|
if (bVistaThemeActive) {
|
|
int iItems = GetItemCount();
|
|
if (iItems > 1 && iItem == iItems - 1)
|
|
rcCloseButton.OffsetRect(-2, 0);
|
|
}
|
|
}
|
|
else {
|
|
if (bVistaThemeActive) {
|
|
int iItems = GetItemCount();
|
|
if (iItems > 1 && iItem < iItems - 1)
|
|
rcCloseButton.OffsetRect(2, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
int CClosableTabCtrl::GetTabUnderPoint(CPoint point) const
|
|
{
|
|
int iTabs = GetItemCount();
|
|
for (int i = 0; i < iTabs; i++)
|
|
{
|
|
CRect rcItem;
|
|
GetItemRect(i, rcItem);
|
|
rcItem.InflateRect(2, 2); // get the real tab item rect
|
|
if (rcItem.PtInRect(point))
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int CClosableTabCtrl::GetTabUnderContextMenu() const
|
|
{
|
|
if (m_ptCtxMenu.x == -1 || m_ptCtxMenu.y == -1)
|
|
return -1;
|
|
return GetTabUnderPoint(m_ptCtxMenu);
|
|
}
|
|
|
|
bool CClosableTabCtrl::SetDefaultContextMenuPos()
|
|
{
|
|
int iTab = GetCurSel();
|
|
if (iTab != -1)
|
|
{
|
|
CRect rcItem;
|
|
if (GetItemRect(iTab, &rcItem))
|
|
{
|
|
rcItem.InflateRect(2, 2); // get the real tab item rect
|
|
m_ptCtxMenu.x = rcItem.left + rcItem.Width()/2;
|
|
m_ptCtxMenu.y = rcItem.top + rcItem.Height()/2;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void CClosableTabCtrl::OnMButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
if (m_bCloseable)
|
|
{
|
|
int iTab = GetTabUnderPoint(point);
|
|
if (iTab != -1) {
|
|
GetParent()->SendMessage(UM_CLOSETAB, (WPARAM)iTab);
|
|
return;
|
|
}
|
|
}
|
|
|
|
CTabCtrl::OnMButtonUp(nFlags, point);
|
|
}
|
|
|
|
void CClosableTabCtrl::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
if (iTabClose != -1) {
|
|
GetParent()->SendMessage(UM_CLOSETAB, (WPARAM)iTabClose);
|
|
iTabClose = -1;
|
|
} else {
|
|
CTabCtrl::OnLButtonUp(nFlags, point);
|
|
}
|
|
}
|
|
|
|
void CClosableTabCtrl::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
if (m_bCloseable)
|
|
{
|
|
int iTab = GetTabUnderPoint(point);
|
|
if (iTab != -1)
|
|
{
|
|
CRect rcItem;
|
|
GetItemRect(iTab, rcItem);
|
|
rcItem.InflateRect(2, 2); // get the real tab item rect
|
|
|
|
bool bVistaThemeActive = IsVistaThemeActive();
|
|
CRect rcCloseButton;
|
|
GetCloseButtonRect(iTab, rcItem, rcCloseButton, iTab == GetCurSel(), bVistaThemeActive);
|
|
|
|
// The visible part of our close icon is one pixel less on each side
|
|
if (!bVistaThemeActive) {
|
|
rcCloseButton.top += 1;
|
|
rcCloseButton.left += 1;
|
|
rcCloseButton.right -= 1;
|
|
rcCloseButton.bottom -= 1;
|
|
}
|
|
|
|
if (rcCloseButton.PtInRect(point)) {
|
|
iTabClose = iTab;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
CTabCtrl::OnLButtonDown(nFlags, point);
|
|
}
|
|
|
|
void CClosableTabCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
int iTab = GetTabUnderPoint(point);
|
|
if (iTab != -1) {
|
|
GetParent()->SendMessage(UM_DBLCLICKTAB, (WPARAM)iTab);
|
|
return;
|
|
}
|
|
CTabCtrl::OnLButtonDblClk(nFlags, point);
|
|
}
|
|
|
|
// It would be nice if there would the option to restrict the maximum width of a tab control.
|
|
// We would need that feature actually for almost all our tab controls. Especially for the
|
|
// search results list - those tab control labels can get quite large. But I did not yet a
|
|
// find a way to limit the width of tabs. Although MSDN says that an owner drawn
|
|
// tab control receives a WM_MEASUREITEM, I never got one.
|
|
|
|
// Vista: This gets never called for an owner drawn tab control
|
|
void CClosableTabCtrl::OnMeasureItem(int iCtlId, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
|
|
{
|
|
TRACE("CClosableTabCtrl::OnMeasureItem\n");
|
|
__super::OnMeasureItem(iCtlId, lpMeasureItemStruct);
|
|
}
|
|
|
|
// Vista: This gets never called for an owner drawn tab control
|
|
void CClosableTabCtrl::MeasureItem(LPMEASUREITEMSTRUCT)
|
|
{
|
|
TRACE("CClosableTabCtrl::MeasureItem\n");
|
|
}
|
|
|
|
void CClosableTabCtrl::DrawItem(LPDRAWITEMSTRUCT lpDIS)
|
|
{
|
|
CRect rect(lpDIS->rcItem);
|
|
int nTabIndex = lpDIS->itemID;
|
|
if (nTabIndex < 0)
|
|
return;
|
|
|
|
TCHAR szLabel[256];
|
|
TC_ITEM tci;
|
|
tci.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_STATE;
|
|
tci.pszText = szLabel;
|
|
tci.cchTextMax = _countof(szLabel);
|
|
tci.dwStateMask = TCIS_HIGHLIGHTED;
|
|
if (!GetItem(nTabIndex, &tci))
|
|
return;
|
|
szLabel[_countof(szLabel) - 1] = _T('\0');
|
|
//TRACE("CClosableTabCtrl::DrawItem: item=%u, state=%08x, color=%08x, rc=%3d,%3d,%3dx%3d\n", nTabIndex, tci.dwState, GetTextColor(lpDIS->hDC), lpDIS->rcItem.left, lpDIS->rcItem.top, lpDIS->rcItem.right - lpDIS->rcItem.left, lpDIS->rcItem.bottom - lpDIS->rcItem.top);
|
|
|
|
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
|
|
if (!pDC)
|
|
return;
|
|
|
|
CRect rcFullItem(lpDIS->rcItem);
|
|
bool bSelected = (lpDIS->itemState & ODS_SELECTED) != 0;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////
|
|
// Adding support for XP Styles (Vista Themes) for owner drawn tab controls simply
|
|
// does *not* work under Vista. Maybe it works under XP (did not try), but that is
|
|
// meaningless because under XP a owner drawn tab control is already rendered *with*
|
|
// the proper XP Styles. So, for XP there is no need to care about the theme API at all.
|
|
//
|
|
// However, under Vista, a tab control which has the TCS_OWNERDRAWFIXED
|
|
// style gets additional 3D-borders which are applied by Vista *after* WM_DRAWITEM
|
|
// was processed. Thus, there is no known workaround available to prevent Vista from
|
|
// adding those old fashioned 3D-borders. We can render the tab control items within
|
|
// the WM_DRAWITEM handler in whatever style we want, but Vista will in each case
|
|
// overwrite the borders of each tab control item with old fashioned 3D-borders...
|
|
//
|
|
// To complete this experience, tab controls also do not support NMCUSTOMDRAW. So, the
|
|
// only known way to customize a tab control is by using TCS_OWNERDRAWFIXED which does
|
|
// however not work properly under Vista.
|
|
//
|
|
// The "solution" which is currently implemented to prevent Vista from drawing those
|
|
// 3D-borders is by using "ExcludeClipRect" to reduce the drawing area which is used
|
|
// by Windows after WM_DRAWITEM was processed. This "solution" is very sensitive to
|
|
// the used rectangles and offsets in general. Incrementing/Decrementing one of the
|
|
// "rcItem", "rcFullItem", etc. rectangles makes the entire "solution" flawed again
|
|
// because some borders would become visible again.
|
|
//
|
|
HTHEME hTheme = NULL;
|
|
int iPartId = TABP_TABITEM;
|
|
int iStateId = TIS_NORMAL;
|
|
bool bVistaHotTracked = false;
|
|
bool bVistaThemeActive = IsVistaThemeActive();
|
|
if (bVistaThemeActive)
|
|
{
|
|
// To determine if the current item is in 'hot tracking' mode, we need to evaluate
|
|
// the current foreground color - there is no flag which would indicate this state
|
|
// more safely. This applies only for Vista and for tab controls which have the
|
|
// TCS_OWNERDRAWFIXED style.
|
|
bVistaHotTracked = pDC->GetTextColor() == GetSysColor(COLOR_HOTLIGHT);
|
|
|
|
hTheme = g_xpStyle.OpenThemeData(m_hWnd, L"TAB");
|
|
if (hTheme)
|
|
{
|
|
if (bSelected) {
|
|
// get the real tab item rect
|
|
rcFullItem.left += 1;
|
|
rcFullItem.right -= 1;
|
|
rcFullItem.bottom -= 1;
|
|
}
|
|
else
|
|
rcFullItem.InflateRect(2, 2); // get the real tab item rect
|
|
|
|
CRect rcBk(rcFullItem);
|
|
if (bSelected)
|
|
{
|
|
iStateId = TTIS_SELECTED;
|
|
if (nTabIndex == 0) {
|
|
// First item
|
|
if (nTabIndex == GetItemCount() - 1)
|
|
iPartId = TABP_TOPTABITEMBOTHEDGE; // First & Last item
|
|
else
|
|
iPartId = TABP_TOPTABITEMLEFTEDGE;
|
|
}
|
|
else if (nTabIndex == GetItemCount() - 1) {
|
|
// Last item
|
|
iPartId = TABP_TOPTABITEMRIGHTEDGE;
|
|
}
|
|
else {
|
|
iPartId = TABP_TOPTABITEM;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rcBk.top += 2;
|
|
iStateId = bVistaHotTracked ? TIS_HOT : TIS_NORMAL;
|
|
if (nTabIndex == 0) {
|
|
// First item
|
|
if (nTabIndex == GetItemCount() - 1)
|
|
iPartId = TABP_TABITEMBOTHEDGE; // First & Last item
|
|
else
|
|
iPartId = TABP_TABITEMLEFTEDGE;
|
|
}
|
|
else if (nTabIndex == GetItemCount() - 1) {
|
|
// Last item
|
|
iPartId = TABP_TABITEMRIGHTEDGE;
|
|
}
|
|
else {
|
|
iPartId = TABP_TABITEM;
|
|
}
|
|
}
|
|
if (g_xpStyle.IsThemeBackgroundPartiallyTransparent(hTheme, iPartId, iStateId))
|
|
g_xpStyle.DrawThemeParentBackground(m_hWnd, *pDC, &rcFullItem);
|
|
g_xpStyle.DrawThemeBackground(hTheme, *pDC, iPartId, iStateId, &rcBk, NULL);
|
|
}
|
|
}
|
|
|
|
// Following background clearing is needed for:
|
|
// WinXP/Vista (when used without an application theme)
|
|
// Vista (when used with an application theme but without a theme for the tab control)
|
|
if ( (!g_xpStyle.IsThemeActive() || !g_xpStyle.IsAppThemed())
|
|
|| (hTheme == NULL && bVistaThemeActive) ) {
|
|
CRect rectFill;
|
|
rectFill.left = rect.left+1;
|
|
rectFill.top = rect.top+1;
|
|
rectFill.right = rect.right-1;
|
|
rectFill.bottom = rect.bottom;
|
|
COLORREF clref = ::GetSysColor(COLOR_BTNFACE);
|
|
if (bSelected) {
|
|
BYTE r = GetRValue(clref);
|
|
BYTE g = GetGValue(clref);
|
|
BYTE b = GetBValue(clref);
|
|
if (r==g && g==b && b==255) {
|
|
clref = RGB(224, 224, 224);
|
|
} else {
|
|
clref = RGB(255, 255, 255);
|
|
}
|
|
}
|
|
pDC->FillSolidRect(rectFill, clref);
|
|
}
|
|
|
|
int iOldBkMode = pDC->SetBkMode(TRANSPARENT);
|
|
|
|
// Draw image on left side
|
|
CImageList *piml = GetImageList();
|
|
if (tci.iImage >= 0 && piml && piml->m_hImageList)
|
|
{
|
|
IMAGEINFO ii;
|
|
piml->GetImageInfo(0, &ii);
|
|
rect.left += bSelected ? 8 : 4;
|
|
piml->Draw(pDC, tci.iImage, CPoint(rect.left, rect.top + (bSelected?2:1)), ILD_TRANSPARENT);
|
|
rect.left += (ii.rcImage.right - ii.rcImage.left);
|
|
if (!bSelected)
|
|
rect.left += 4;
|
|
}
|
|
|
|
bool bCloseable = m_bCloseable;
|
|
if (bCloseable && GetParent()->SendMessage(UM_QUERYTAB, nTabIndex))
|
|
bCloseable = false;
|
|
|
|
// Draw 'Close button' at right side
|
|
if (bCloseable && m_ImgLstCloseButton.m_hImageList)
|
|
{
|
|
CRect rcCloseButton;
|
|
GetCloseButtonRect(nTabIndex, rect, rcCloseButton, bSelected, bVistaThemeActive);
|
|
|
|
HTHEME hThemeNC = bVistaThemeActive ? g_xpStyle.OpenThemeData(m_hWnd, L"WINDOW") : NULL;
|
|
if (hThemeNC) {
|
|
// Possible "Close" parts: WP_CLOSEBUTTON, WP_SMALLCLOSEBUTTON, WP_MDICLOSEBUTTON
|
|
int iPartId = WP_SMALLCLOSEBUTTON;
|
|
int iStateId = (bSelected || bVistaHotTracked) ? CBS_NORMAL : CBS_DISABLED;
|
|
if (g_xpStyle.IsThemeBackgroundPartiallyTransparent(hTheme, iPartId, iStateId))
|
|
g_xpStyle.DrawThemeParentBackground(m_hWnd, *pDC, &rcCloseButton);
|
|
g_xpStyle.DrawThemeBackground(hThemeNC, *pDC, iPartId, iStateId, rcCloseButton, NULL);
|
|
g_xpStyle.CloseThemeData(hThemeNC);
|
|
}
|
|
else {
|
|
m_ImgLstCloseButton.Draw(pDC, (bSelected || bVistaHotTracked) ? 0 : 1, rcCloseButton.TopLeft(), ILD_TRANSPARENT);
|
|
}
|
|
|
|
rect.right = rcCloseButton.left - 2;
|
|
if (bSelected)
|
|
rect.left += hTheme ? 4 : 2;
|
|
}
|
|
|
|
COLORREF crOldColor = CLR_NONE;
|
|
if (tci.dwState & TCIS_HIGHLIGHTED)
|
|
crOldColor = pDC->SetTextColor(RGB(192, 0, 0));
|
|
else if (bVistaHotTracked)
|
|
crOldColor = pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT));
|
|
|
|
rect.top += bSelected ? 4 : 3;
|
|
// Vista: Tab control has troubles with determining the width of a tab if the
|
|
// label contains one '&' character. To get around this, we use the old code which
|
|
// replaces one '&' character with two '&' characters and we do not specify DT_NOPREFIX
|
|
// here when drawing the text.
|
|
//
|
|
// Vista: "DrawThemeText" can not be used in case we need a certain foreground color. Thus we always us
|
|
// "DrawText" to always get the same font and metrics (just for safety).
|
|
pDC->DrawText(szLabel, rect, DT_SINGLELINE | DT_TOP | DT_CENTER /*| DT_NOPREFIX*/);
|
|
|
|
if (crOldColor != CLR_NONE)
|
|
pDC->SetTextColor(crOldColor);
|
|
pDC->SetBkMode(iOldBkMode);
|
|
|
|
if (hTheme)
|
|
{
|
|
CRect rcClip(rcFullItem);
|
|
if (bSelected) {
|
|
rcClip.left -= 2 + 1;
|
|
rcClip.right += 2 + 1;
|
|
}
|
|
else {
|
|
rcClip.top += 2;
|
|
}
|
|
pDC->ExcludeClipRect(&rcClip);
|
|
g_xpStyle.CloseThemeData(hTheme);
|
|
}
|
|
}
|
|
|
|
void CClosableTabCtrl::PreSubclassWindow()
|
|
{
|
|
CTabCtrl::PreSubclassWindow();
|
|
InternalInit();
|
|
}
|
|
|
|
int CClosableTabCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if (CTabCtrl::OnCreate(lpCreateStruct) == -1)
|
|
return -1;
|
|
InternalInit();
|
|
return 0;
|
|
}
|
|
|
|
void CClosableTabCtrl::InternalInit()
|
|
{
|
|
ModifyStyle(0, TCS_OWNERDRAWFIXED);
|
|
|
|
#if 1
|
|
// Under Vista Aero, all tab controls get by default the TCS_HOTTRACK
|
|
// style even if it was not specified within the resource file. Though, to 'see'
|
|
// the hot tracking effect the control also need to get initialized explicitly with
|
|
// the WS_CLIPCHILDREN style within a *seperate* function call. Yes, there is no
|
|
// logic to all this, not at all. It simply is that way.
|
|
//
|
|
// So, do *not* "optimize" that code by using only one "ModifyStyle" function call.
|
|
// The 2nd function call to "ModifyStyle" is very much by intention!
|
|
//
|
|
// However, the hot tracking effect which is achived this way does not survive a
|
|
// theme change. After the theme is changed (regardless whether we switch between
|
|
// Vista themes or from/to a non-Vista theme), the hot tracking effect is gone even
|
|
// if we try to modify the styles again within OnThemeChanged...
|
|
if (IsVistaThemeActive())
|
|
ModifyStyle(0, WS_CLIPCHILDREN);
|
|
#else
|
|
// Remove the automatically applied hot tracking effect to avoid that the tab control
|
|
// may use it when it also sets the WS_CLIPCHILDREN (for other reasons) later.
|
|
ModifyStyle(TCS_HOTTRACK, 0);
|
|
#endif
|
|
|
|
SetAllIcons();
|
|
}
|
|
|
|
void CClosableTabCtrl::OnSysColorChange()
|
|
{
|
|
CTabCtrl::OnSysColorChange();
|
|
SetAllIcons();
|
|
}
|
|
|
|
void CClosableTabCtrl::SetAllIcons()
|
|
{
|
|
if (m_bCloseable)
|
|
{
|
|
const int iIconWidth = 16;
|
|
const int iIconHeight = 16;
|
|
m_ImgLstCloseButton.DeleteImageList();
|
|
m_ImgLstCloseButton.Create(iIconWidth, iIconHeight, ILC_COLOR32 | ILC_MASK, 0, 1);
|
|
m_ImgLstCloseButton.Add(AfxGetApp()->LoadIcon(IDI_CLOSE));
|
|
m_ImgLstCloseButton.Add(AfxGetApp()->LoadIcon(IDI_CLOSE_2));
|
|
m_ImgLstCloseButton.GetImageInfo(0, &m_iiCloseButton);
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
void CClosableTabCtrl::OnContextMenu(CWnd* pWnd, CPoint point)
|
|
{
|
|
/*
|
|
if (m_bCloseable)
|
|
{
|
|
if (point.x == -1 || point.y == -1) {
|
|
if (!SetDefaultContextMenuPos())
|
|
return;
|
|
point = m_ptCtxMenu;
|
|
ClientToScreen(&point);
|
|
}
|
|
else {
|
|
m_ptCtxMenu = point;
|
|
ScreenToClient(&m_ptCtxMenu);
|
|
}
|
|
|
|
int iTab = GetTabUnderPoint(m_ptCtxMenu);
|
|
if (iTab != -1)
|
|
{
|
|
if (GetParent()->SendMessage(UM_QUERYTAB, (WPARAM)iTab) == 0)
|
|
{
|
|
CMenu menu;
|
|
menu.CreatePopupMenu();
|
|
menu.AppendMenu(MF_STRING, MP_REMOVE, GetResString(IDS_FD_CLOSE));
|
|
menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
return CTabCtrl::OnContextMenu(pWnd, point);
|
|
}
|
|
|
|
BOOL CClosableTabCtrl::OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
/*
|
|
if (wParam == MP_REMOVE)
|
|
{
|
|
if (m_ptCtxMenu.x != -1 && m_ptCtxMenu.y != -1)
|
|
{
|
|
int iTab = GetTabUnderPoint(m_ptCtxMenu);
|
|
if (iTab != -1) {
|
|
GetParent()->SendMessage(UM_CLOSETAB, (WPARAM)iTab);
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
return CTabCtrl::OnCommand(wParam, lParam);
|
|
}
|
|
|
|
LRESULT CClosableTabCtrl::_OnThemeChanged()
|
|
{
|
|
// Owner drawn tab control seems to have troubles with updating itself due to an XP theme change..
|
|
ModifyStyle(TCS_OWNERDRAWFIXED, 0); // Reset control style to not-owner drawn
|
|
Default(); // Process original WM_THEMECHANGED message
|
|
ModifyStyle(0, TCS_OWNERDRAWFIXED); // Apply owner drawn style again
|
|
return 0;
|
|
}
|
|
|
|
// Vista: This gets never called for an owner drawn tab control
|
|
HBRUSH CClosableTabCtrl::CtlColor(CDC* /*pDC*/, UINT /*nCtlColor*/)
|
|
{
|
|
// Change any attributes of the DC here
|
|
// Return a non-NULL brush if the parent's handler should not be called
|
|
return NULL;
|
|
}
|
|
|
|
// Vista: This gets never called for an owner drawn tab control
|
|
HBRUSH CClosableTabCtrl::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
|
|
{
|
|
HBRUSH hbr = CTabCtrl::OnCtlColor(pDC, pWnd, nCtlColor);
|
|
// Change any attributes of the DC here
|
|
// Return a different brush if the default is not desired
|
|
return hbr;
|
|
}
|
|
|
|
// Vista: Can not be used to workaround the problems with owner drawn tab control
|
|
BOOL CClosableTabCtrl::OnEraseBkgnd(CDC* pDC)
|
|
{
|
|
return CTabCtrl::OnEraseBkgnd(pDC);
|
|
}
|
|
|
|
BOOL CClosableTabCtrl::DeleteItem(int nItem)
|
|
{
|
|
// if we remove a tab which would lead to scrolling back to other tabs, all those become hidden for... whatever reasons
|
|
// its easy enough wo work arround by scrolling to the first visible tab _before_ we delete the other one
|
|
SetCurSel(0);
|
|
return __super::DeleteItem(nItem);
|
|
}
|
|
|
|
bool CClosableTabCtrl::IsVistaThemeActive() const
|
|
{
|
|
return g_xpStyle.IsThemeActive() && g_xpStyle.IsAppThemed();
|
|
}
|