|
Another cause might be that I was using an older version MFC (MFC42) and a old compiler.
|
|
|
|
|
when not all tabs can be shown, little navigation arrows appear on the right of the tab control. If we turn on "flat" and "color background" styles, navigating through the tabs using these arrows leaves a small space below them, and it is not correctly repainted (compared to common tab control). Moreover, since these arrows are not handled correctly in the code, they sometimes even become invisible (for instance, when they are attached to MDI document and it is being serialized).
Михаил
|
|
|
|
|
Really Excellent work!!
How can i use it in PropertySheet?
Do you have any source code sample?
Thank you a lot
Thomas
|
|
|
|
|
hi thomas,
have a look at the very bottom of the article. what you have to do is derive your own class from CPropertySheet and then subclass the tabcontrol in OnInitDialog, just as the code snippet does.
if you have any problems just let me know.
.dan.g.
AbstractSpoon Software
abstractspoon2_at_optusnet_dot_com_dot_au
|
|
|
|
|
Hi,
is it possible to create the tab buttons as we can see in MSN messenger, I mean the tab options we will get once we login to MSN, with a bitmap loaded in it.
Any Suggestions please, How can I achive this?
thanks
|
|
|
|
|
I have no idea how to do it.
Say I have 4 tabs, 3 of which has pages. The 4th tab does not have a tab page. It function as a button and must look like a command button, can it be done?
|
|
|
|
|
i don't think you can mix and match the tab styles, which was my first first thought.
so the easiest way would be to add a child button to the underlying tab control.
if you are using a standard CTabCtrl then i would suggest deriving your own class from it and then creating and managing the button within it.
where you want the button to be located may complicate things because if you want it on the left side then i've no idea how to offset the tabs to make space. having it on the right is easier since you just need to get the rect of the rightmost tab and position the button after it.
good luck.
.dan.g.
AbstractSpoon Software
|
|
|
|
|
i have a dialog based app, and 5 tabs, but into the client rect can be placed only 3, so a spin button appears. well, when i scroll tabs and the last one became visible, i got a tail of latters. just like this, for exanple, i have a text in the last tab "Project", and i see Projectttttttt.
i tried to overload WM_HSCROLL message and call Invalidate in it, but i have no sucsess. what to do?
|
|
|
|
|
;);):-DI found this very nice article thanks
how can I change tab size? I tried with SetItemSize but it works only in vertical direction and not on Horizontal direction.
I also had problem with using true color icons. Icons were displayed using 16 colors only
Imantha
|
|
|
|
|
hi imantha,
i did a quick check on msdn for the TCM_SETITEMSIZE message (which is wrapped by SetItemSize()) and its comments that this only works for fixed width or owner draw tabs.
so either this is the issue or there's a bug in my code.
try it out and let me know. if its my code then i'll have a look when i get back from the conference i'm currently on.
rgds
.dan.g.
AbstractSpoon Software
|
|
|
|
|
hello DanG
Although SetItemSize() does not work to set width of tab I have succeeded with SetMinTabWidth() to set width of tab.
thanks for y'r reply
Imantha
|
|
|
|
|
First thanks for your great article!
One question: How can you display bitmaps or icons with a color depth of 256 and higher? When trying it, it seems that MFC always reduces the color depth to 16! Do you have any idea?
Thanks a lot!
Ralph
|
|
|
|
|
hi ralph,
provided you've managed to get the bitmap into your exe file correctly it should be possible to just load it straight into an imagelist.
if this is what you're doing and its not working, perhaps you could post the code that you're using and i'll have a quick look.
rgds
.dan.g.
AbstractSpoon Software
|
|
|
|
|
After all, sorry by my english.
I make some changes on original code, to make tab on bottom correctly and to show the selcted tab text in bold.
DWORD CTabCtrlEx::m_sdwCustomLook = 0;
enum { PADDING = 3, EDGE = 20};
//////////////////////////////////////////////////////////////////////////////
// helpers
COLORREF Darker(COLORREF crBase, float fFactor)
{
ASSERT ( fFactor < 1.0f && fFactor > 0.0f );
fFactor = min ( fFactor, 1.0f );
fFactor = max ( fFactor, 0.0f );
BYTE bRed, bBlue, bGreen;
BYTE bRedShadow, bBlueShadow, bGreenShadow;
bRed = GetRValue ( crBase );
bBlue = GetBValue ( crBase );
bGreen = GetGValue ( crBase );
bRedShadow = ( BYTE )( bRed * fFactor );
bBlueShadow = ( BYTE )( bBlue * fFactor );
bGreenShadow = ( BYTE )( bGreen * fFactor );
return RGB ( bRedShadow, bGreenShadow, bBlueShadow );
}
COLORREF Lighter(COLORREF crBase, float fFactor)
{
ASSERT ( fFactor > 1.0f );
fFactor = max ( fFactor, 1.0f );
BYTE bRed, bBlue, bGreen;
BYTE bRedHilite, bBlueHilite, bGreenHilite;
bRed = GetRValue ( crBase );
bBlue = GetBValue ( crBase );
bGreen = GetGValue ( crBase );
bRedHilite = ( BYTE )min ( ( int )( bRed * fFactor ), 255 );
bBlueHilite = ( BYTE )min ( ( int )( bBlue * fFactor ), 255 );
bGreenHilite = ( BYTE )min ( ( int )( bGreen * fFactor ), 255 );
return RGB ( bRedHilite, bGreenHilite, bBlueHilite );
}
CSize FormatText(CString& sText, CDC* pDC, int nWidth)
{
CRect rect ( 0, 0, nWidth, 20 );
UINT uFlags = DT_CALCRECT | DT_SINGLELINE | DT_MODIFYSTRING | DT_END_ELLIPSIS;
::DrawText ( pDC->GetSafeHdc (), sText.GetBuffer ( sText.GetLength () + 4 ), -1, rect, uFlags );
sText.ReleaseBuffer ();
return pDC->GetTextExtent ( sText );
}
// helpers
////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CTabCtrlEx
CTabCtrlEx::CTabCtrlEx(int nType)
{
m_crBack = ( COLORREF )-1; // use default color
m_nDrawType = TCF_NONE;
m_nOldSel = -1;
EnableDraw ( nType );
}
CTabCtrlEx::~CTabCtrlEx()
{
}
BEGIN_MESSAGE_MAP(CTabCtrlEx, CTabCtrl)
//{{AFX_MSG_MAP(CTabCtrlEx)
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTabCtrlEx message handlers
BOOL CTabCtrlEx::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
CTabCtrl::OnEraseBkgnd(pDC);
Invalidate ( FALSE );
return TRUE;
}
void CTabCtrlEx::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CTabCtrl::OnPaint() for painting messages
if ( m_nDrawType == TCF_NONE )
Default();
else if ( m_nDrawType == TCF_TABS )
{
ASSERT ( GetStyle () & TCS_OWNERDRAWFIXED );
Default ();
}
else // all
{
CPaintDC dc ( this ); // device context for painting
DRAWITEMSTRUCT dis;
dis.CtlType = ODT_TAB;
dis.CtlID = GetDlgCtrlID ();
dis.hwndItem = GetSafeHwnd ();
dis.hDC = dc.GetSafeHdc ();
dis.itemAction = ODA_DRAWENTIRE;
// draw the rest of the border
CRect rClient, rPage;
GetClientRect ( &dis.rcItem );
rPage = dis.rcItem;
AdjustRect ( FALSE, rPage );
BOOL bBottom = ( GetStyle () & TCS_BOTTOM ) == TCS_BOTTOM;
if ( bBottom )
dis.rcItem.bottom = rPage.bottom;
else
dis.rcItem.top = rPage.top - 2;
DrawMainBorder ( &dis );
// paint the tabs first and then the borders
int nTab = GetItemCount () - 1;
int nSel = GetCurSel ();
if ( !nTab ) // no pages added
return;
// prepare dc
CFont* currFont = GetFont ();
CFont* pOldFont = dc.SelectObject ( currFont );
VERIFY ( GetItemRect ( 0, &dis.rcItem ) );
for ( int iTab = 0; iTab < nTab; iTab++ )
{
VERIFY ( GetItemRect ( iTab, &dis.rcItem ) );
if ( iTab != nSel )
{
dis.itemID = iTab;
dis.itemState = 0;
dis.rcItem.bottom -= bBottom ? 3 : 2;
DrawItem ( &dis );
DrawItemBorder ( &dis );
}
}
// now selected tab
dis.itemID = nSel;
dis.itemState = ODS_SELECTED;
VERIFY ( GetItemRect ( nSel, &dis.rcItem ) );
dis.rcItem.bottom += bBottom ? 3 : 2;
dis.rcItem.top -= bBottom ? 3 : 2;
DrawItem ( &dis );
DrawItemBorder ( &dis );
dc.SelectObject ( pOldFont );
}
}
void CTabCtrlEx::DrawItem(LPDRAWITEMSTRUCT lpdis)
{
CDC* pDC = CDC::FromHandle ( lpdis->hDC );
HIMAGELIST hilTabs = ( HIMAGELIST )TabCtrl_GetImageList ( GetSafeHwnd () );
BOOL bSelected = ( lpdis->itemID == ( UINT )GetCurSel () );
BOOL bColor = ( m_sdwCustomLook & TCF_COLOR );
BOOL bBottom = ( GetStyle () & TCS_BOTTOM ) == TCS_BOTTOM;
CRect rItem ( lpdis->rcItem );
CString sTemp;
TC_ITEM tci;
tci.mask = TCIF_TEXT | TCIF_IMAGE;
tci.pszText = sTemp.GetBuffer ( 100 );
tci.cchTextMax = 99;
GetItem ( lpdis->itemID, &tci );
sTemp.ReleaseBuffer();
if ( bSelected )
{
CFont font;
LOGFONT lgFont;
GetFont ()->GetLogFont ( &lgFont );
lgFont.lfWeight = FW_BOLD;
font.CreateFontIndirect ( &lgFont );
pDC->SelectObject ( &font );
rItem.bottom -= bBottom ? 2 : 1;
}
else
{
if ( bBottom )
{
rItem.top -= 1;
rItem.bottom += 1;
}
else
rItem.bottom += 2;
}
// tab
// blend from back color to COLOR_3DFACE if 16 bit mode or better
COLORREF crFrom = GetTabColor ( bSelected );
if ( m_sdwCustomLook & TCF_GRADIENT && pDC->GetDeviceCaps ( BITSPIXEL ) >= 16 )
{
COLORREF crTo = bSelected ? ::GetSysColor ( COLOR_3DFACE ) :
Darker ( !bColor || m_crBack == -1 ? ::GetSysColor ( COLOR_3DFACE ) : m_crBack, 0.6f );
//crFrom = bSelected ? GetTabColor ( bSelected ) : Lighter ( ::GetSysColor ( COLOR_3DFACE ), 1.7f );
int nROrg = GetRValue ( crFrom );
int nGOrg = GetGValue ( crFrom );
int nBOrg = GetBValue ( crFrom );
int nRDiff = GetRValue ( crTo ) - nROrg;
int nGDiff = GetGValue ( crTo ) - nGOrg;
int nBDiff = GetBValue ( crTo ) - nBOrg;
int nHeight = rItem.Height ();
for ( int nLine = 0; nLine < nHeight; nLine += 2 )
{
int nRed = nROrg + ( nLine * nRDiff ) / nHeight;
int nGreen = nGOrg + ( nLine * nGDiff ) / nHeight;
int nBlue = nBOrg + ( nLine * nBDiff ) / nHeight;
if ( bBottom )
pDC->FillSolidRect ( CRect ( rItem.left, rItem.bottom - nLine - 2, rItem.right, rItem.bottom - nLine ), RGB ( nRed, nGreen, nBlue ) );
else
pDC->FillSolidRect ( CRect ( rItem.left, rItem.top + nLine, rItem.right, rItem.top + nLine + 2 ), RGB ( nRed, nGreen, nBlue ) );
}
}
else // simple solid fill
pDC->FillSolidRect ( rItem, crFrom );
// text & icon
rItem.left += PADDING;
if ( bBottom )
rItem.top += PADDING + ( bSelected ? 1 : -2 );
else
rItem.top += PADDING + ( bSelected ? 1 : 0 );
pDC->SetBkMode ( TRANSPARENT );
// icon
if ( hilTabs )
{
ImageList_Draw ( hilTabs, tci.iImage, *pDC, rItem.left, rItem.top, ILD_TRANSPARENT );
rItem.left += 16 + PADDING;
}
// text
rItem.left -= (PADDING + 1);
pDC->SetTextColor ( GetTabTextColor ( bSelected ) );
pDC->DrawText ( sTemp, rItem, DT_NOPREFIX | DT_CENTER );
}
void CTabCtrlEx::DrawItemBorder(LPDRAWITEMSTRUCT lpdis)
{
ASSERT ( m_sdwCustomLook & TCF_FLAT );
BOOL bSelected = ( lpdis->itemID == ( UINT )GetCurSel () );
BOOL bBackTabs = ( m_sdwCustomLook & TCF_BACKTABS );
BOOL bBottom = ( GetStyle () & TCS_BOTTOM ) == TCS_BOTTOM;
CRect rItem ( lpdis->rcItem );
CDC* pDC = CDC::FromHandle ( lpdis->hDC );
COLORREF crTab = GetTabColor ( bSelected );
COLORREF crHighlight = Lighter ( crTab, 1.5f );
COLORREF crShadow = Darker ( crTab, 0.75f );
if ( bSelected || bBackTabs )
{
if ( bBottom )
{
if ( m_nOldSel != -1 && lpdis->itemID == ( UINT )m_nOldSel )
{
CRect rect;
GetItemRect ( m_nOldSel, &rect );
rect.InflateRect ( 0, 5 );
InvalidateRect ( &rect, TRUE );
m_nOldSel = -1;
}
// edges
if ( bSelected )
{
pDC->FillSolidRect ( CRect ( rItem.left, rItem.top, rItem.left + 1, rItem.bottom - 2 ), crHighlight );
pDC->FillSolidRect ( CRect ( rItem.left, rItem.bottom - 3, rItem.right, rItem.bottom - 2 ), crShadow );
pDC->FillSolidRect ( CRect ( rItem.right - 1, rItem.top, rItem.right, rItem.bottom - 2 ), crShadow );
}
else
{
pDC->FillSolidRect ( CRect ( rItem.left, rItem.top - 1, rItem.left + 1, rItem.bottom + 1 ), crHighlight );
pDC->FillSolidRect ( CRect ( rItem.left + 1, rItem.bottom, rItem.right, rItem.bottom + 1 ), crShadow );
pDC->FillSolidRect ( CRect ( rItem.right - 1, rItem.top - 1, rItem.right, rItem.bottom ), crShadow );
}
}
else
{
rItem.bottom += bSelected ? -1 : 1;
// edges
pDC->FillSolidRect ( CRect ( rItem.left, rItem.top, rItem.left + 1, rItem.bottom ), crHighlight );
pDC->FillSolidRect ( CRect ( rItem.left, rItem.top, rItem.right, rItem.top + 1 ), crHighlight );
pDC->FillSolidRect ( CRect ( rItem.right - 1, rItem.top, rItem.right, rItem.bottom ), crShadow );
}
}
else // draw simple dividers
{
if ( bBottom )
{
pDC->FillSolidRect ( CRect ( rItem.left, rItem.top - 1, rItem.left + 1, rItem.bottom ), crShadow );
pDC->FillSolidRect ( CRect ( rItem.right - 1, rItem.top - 1, rItem.right, rItem.bottom ), crShadow );
}
else
{
pDC->FillSolidRect ( CRect ( rItem.left - 1, rItem.top, rItem.left, rItem.bottom ), crShadow );
pDC->FillSolidRect ( CRect ( rItem.right - 1, rItem.top, rItem.right, rItem.bottom ), crShadow );
}
}
}
void CTabCtrlEx::DrawMainBorder(LPDRAWITEMSTRUCT lpdis)
{
CRect rBorder ( lpdis->rcItem );
CDC* pDC = CDC::FromHandle ( lpdis->hDC );
COLORREF crTab = GetTabColor();
COLORREF crHighlight = Lighter ( crTab, 1.5f );
COLORREF crShadow = Darker ( crTab, 0.75f );
pDC->Draw3dRect ( rBorder, crHighlight, crShadow );
}
void CTabCtrlEx::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
CTabCtrl::PreSubclassWindow();
if ( m_nDrawType != TCF_NONE )
ModifyStyle ( 0, TCS_OWNERDRAWFIXED );
}
void CTabCtrlEx::SetBkgndColor(COLORREF color)
{
// set new color
m_crBack = color;
// redraw
if ( GetSafeHwnd () )
Invalidate ();
}
BOOL CTabCtrlEx::EnableDraw(int nType)
{
ASSERT ( nType >= TCF_NONE && nType <= TCF_ALL );
if ( nType < TCF_NONE || nType > TCF_ALL )
return FALSE;
m_nDrawType = nType;
if ( GetSafeHwnd () )
{
if ( m_nDrawType != TCF_NONE )
ModifyStyle ( 0, TCS_OWNERDRAWFIXED );
else
ModifyStyle ( TCS_OWNERDRAWFIXED, 0 );
Invalidate ();
}
return TRUE;
}
void CTabCtrlEx::SetText(int index, CString strText)
{
TCITEM tci;
tci.mask = TCIF_TEXT;
tci.pszText = ( LPTSTR )( LPCTSTR )strText;
SetItem ( index, &tci );
}
CString CTabCtrlEx::GetText(int index)
{
TCITEM tci;
tci.mask = TCIF_TEXT;
GetItem ( index, &tci );
return tci.pszText;
}
COLORREF CTabCtrlEx::GetTabColor(BOOL bSelected)
{
BOOL bColor = ( m_sdwCustomLook & TCF_COLOR );
BOOL bHiliteSel = ( m_sdwCustomLook & TCF_SELECTION );
BOOL bBackTabs = ( m_sdwCustomLook & TCF_BACKTABS );
BOOL bFlat = ( m_sdwCustomLook & TCF_FLAT );
if ( bSelected && bHiliteSel )
{
if ( bColor )
return Lighter ( ( m_crBack == -1 ) ? ::GetSysColor ( COLOR_3DFACE ) : m_crBack, 1.4f );
else
return Lighter ( ::GetSysColor ( COLOR_3DFACE ), 1.4f );
}
else if ( !bSelected )
{
if ( bBackTabs || !bFlat )
{
if ( bColor )
return Darker ( ( m_crBack == -1 ) ? ::GetSysColor ( COLOR_3DFACE ) : m_crBack, 0.9f );
else
return Darker ( ::GetSysColor ( COLOR_3DFACE ), 0.9f );
}
else
return ( m_crBack == -1 ) ? ::GetSysColor ( COLOR_3DFACE ) : m_crBack;
}
// else
return ::GetSysColor ( COLOR_3DFACE );
}
COLORREF CTabCtrlEx::GetTabTextColor(BOOL bSelected)
{
BOOL bColor = ( m_sdwCustomLook & TCF_COLOR );
BOOL bFlat = ( m_sdwCustomLook & TCF_FLAT );
if ( bSelected )
{
return ::GetSysColor ( COLOR_WINDOWTEXT );
}
else
{
if (bColor || bFlat)
return Darker ( ( m_crBack == -1 ) ? ::GetSysColor ( COLOR_3DFACE ) : m_crBack, 0.5f );
else
return Darker ( ::GetSysColor ( COLOR_3DFACE ), 0.5f );
}
// else
return Darker ( ::GetSysColor ( COLOR_3DFACE ), 0.5f );
}
void CTabCtrlEx::EnableCustomLook(DWORD dwStyle)
{
m_sdwCustomLook = dwStyle;
}
BOOL CTabCtrlEx::GetItemRect(int nItem, LPRECT lpRect) const
{
BOOL bRet = CTabCtrl::GetItemRect ( nItem, lpRect );
if ( bRet && nItem )
{
int nItens = GetItemCount () - 1;
int nWidth = (lpRect->right - lpRect->left);
lpRect->left += ( 10 * (nItem) );
lpRect->right = lpRect->left + nWidth + 10;
}
else
lpRect->right += 10;
return bRet;
}
int CTabCtrlEx::HitTestEx(CPoint point) const
{
int nTabs = GetItemCount () - 1;
for ( int iTab = 0; iTab < nTabs; iTab++ )
{
CRect rect;
VERIFY ( GetItemRect ( iTab, &rect ) );
if ( rect.PtInRect ( point ) )
return iTab;
}
return -1;
}
void CTabCtrlEx::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//CTabCtrl::OnLButtonDown(nFlags, point);
m_nOldSel = GetCurSel ();
int nSel = HitTestEx ( point );
SetCurSel ( nSel );
NMHDR hdr;
hdr.hwndFrom = this->GetSafeHwnd ();
hdr.code = TCN_SELCHANGE;
hdr.idFrom = IDC_TAB_VIEW;
GetParent ()->SendMessage ( WM_NOTIFY, 0, ( LPARAM )&hdr );
Invalidate ( FALSE );
}
|
|
|
|
|
This is exactly what i want!! thanks.
|
|
|
|
|
Hi
I am creating a project (base in a single document), I modified the initial class *View(at the end of the wizard) to be based in CFormView, so that the project is like one based on dialogs (but with other classes and format).
I set up a tabcontrol in the window, and I want to get the other frames because nothing appears in the tab.
I made some other examples but as this one is based on other classes, I have no idea how to get the information.
Can anybody help?
Thanks
rubencmos@hotmail.com
|
|
|
|
|
coloring the tab control when tab control uses a bottom
(upside down) style did not work so I modified the code:
BOOL CBaseTabCtrl::OnEraseBkgnd(CDC* pDC)
{
CRect rClient, rTab, rTotalTab, rBkgnd, rEdge;
COLORREF crBack;
int nTab, nTabHeight = 0;
CTabCtrl::OnEraseBkgnd(pDC);
// calc total tab width
GetClientRect(rClient);
nTab = GetItemCount();
rTotalTab.SetRectEmpty();
while (nTab--)
{
GetItemRect(nTab, rTab);
rTotalTab.UnionRect(rTab, rTotalTab);
}
nTabHeight = rTotalTab.Height();
// add a bit
rTotalTab.InflateRect(2, 3);
rEdge = rTotalTab;
// then if background color is set, paint the visible background
// area of the tabs in the bkgnd color
// note: the mfc code for drawing the tabs makes all sorts of assumptions
// about the background color of the tab control being the same as the page
// color - in some places the background color shows thru' the pages!!
// so we must only paint the background color where we need to, which is that
// portion of the tab area not excluded by the tabs themselves
crBack = (m_crBack == -1) ? ::GetSysColor(COLOR_3DFACE) : m_crBack;
pDC->SetBkColor(crBack);
if ( GetStyle() & TCS_RIGHT )
{
// full width of tab ctrl below bottom of tabs
rBkgnd = rClient;
rBkgnd.top = rBkgnd.bottom - 3;
pDC->ExtTextOut(rBkgnd.left, rBkgnd.top, ETO_CLIPPED | ETO_OPAQUE, rBkgnd, "", NULL);
// width of tab ctrl visible bkgnd including bottom pixel of tabs to left of tabs
rBkgnd = rClient;
rBkgnd.right = 2;
rBkgnd.top = rBkgnd.bottom - (nTabHeight + 2);
pDC->ExtTextOut(rBkgnd.left, rBkgnd.top, ETO_CLIPPED | ETO_OPAQUE, rBkgnd, "", NULL);
// to right of tabs
rBkgnd = rClient;
rBkgnd.left += rTotalTab.Width() - 2;
rBkgnd.top = rBkgnd.bottom - (nTabHeight + 2);
pDC->ExtTextOut(rBkgnd.left, rBkgnd.top, ETO_CLIPPED | ETO_OPAQUE, rBkgnd, "", NULL);
}
else
{
// full width of tab ctrl above top of tabs
rBkgnd = rClient;
rBkgnd.bottom = rTotalTab.top + 3;
pDC->ExtTextOut(rBkgnd.left, rBkgnd.top, ETO_CLIPPED | ETO_OPAQUE, rBkgnd, "", NULL);
// width of tab ctrl visible bkgnd including bottom pixel of tabs to left of tabs
rBkgnd = rClient;
rBkgnd.right = 2;
rBkgnd.bottom = rBkgnd.top + (nTabHeight + 2);
pDC->ExtTextOut(rBkgnd.left, rBkgnd.top, ETO_CLIPPED | ETO_OPAQUE, rBkgnd, "", NULL);
// to right of tabs
rBkgnd = rClient;
rBkgnd.left += rTotalTab.Width() - 2;
rBkgnd.bottom = rBkgnd.top + (nTabHeight + 2);
pDC->ExtTextOut(rBkgnd.left, rBkgnd.top, ETO_CLIPPED | ETO_OPAQUE, rBkgnd, "", NULL);
}
return TRUE;
}
Robert Tessler
|
|
|
|
|
|
I have been asked to provide a spin control for a tab control which has the standard 'left/right' buttons and also 'first/last' button. Any suggestions would be gratefully appreciated.
Happy programming!!
|
|
|
|
|
all i can suggest is to derive a class from CSpinButtonCtrl and add the extra buttons manually to the left and right ends and then subclass the default spinbutton control in the tabcontrol like so:
int CMyTabCtrl::OnCreate(...)
{
if (CTabCtrl::OnCreate(...) == -1)
return -1;
CWnd* pSpin = GetDlgItem(1); // spin control always has ID == 1
m_mySpinCtrl.SubclassDlgItem(pSpin, this);
}
i'm assuming that the first and last buttons would send WM_HSCROLL messages to the tab control (just like the default spinbuttonctrl) so you'll also need a handler for these messages.
what i'm not sure about is whether or not the tab control will take any account of the wider spin control or not. i think you'll need to experiment a bit.
regards
|
|
|
|
|
Thank you. My thinking was along these lines, however as is often the case I'm having problems getting the subclassing to work. The other problem then is determin the of rectangle the default control would like to use and double its width to allow for the extra 2 buttons.
Maybe it is easier to detect if the mouse click is in conjunction with the Shift or Ctrl keys and use that to do the same job without the need for the extra 2 buttons.
Happy programming!!
|
|
|
|
|
How would I go about implementing it incase of bitmapped dialogs?
|
|
|
|
|
you would need to derive a new class from CBaseTabCtrl and override:
virtual void DrawMainBorder(LPDRAWITEMSTRUCT lpDrawItemStruct);<br />
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);<br />
virtual void DrawItemBorder(LPDRAWITEMSTRUCT lpDrawItemStruct);
|
|
|
|
|
Is it possible to somehow remove the spin control from the tab control?
|
|
|
|
|
2 ways:
1. enumerate all the children of the tab control until you find one with the class name "msctls_updown32" and then hide and disable it.
2. use spy++ to determine the ctrlID of the spin ctrl, use this to get a handle to the CWnd* and then hide and disable it.
|
|
|
|
|