|
I have modified the code for a straight c application and ran into a problem with a crash when the width dropped to 1. It gets to one by laying another window over the tabs. I had to modify the asm code to this:
__asm
{
mov esi, pcImg
mov edi, pcImgRotate
xor ebx, ebx
loop_height:
mov ecx, nWidth
cmp ebx, nHeight1
jne loop_width
dec ecx
je do_last
loop_width:
movsd
dec edi
add esi,nBmpWdtPS
loop loop_width
cmp ebx, nHeight1
je do_last
inc ebx
add edi, nPadD
mov esi, ebx
shl esi, 1
add esi, ebx
add esi, pcImg
jmp loop_height
do_last:
movsw
movsb
}
-- modified at 2:43 Wednesday 20th June, 2007
|
|
|
|
|
Not sure where you got the manifest but you may want to update the name ... this was part of the project (note: T-Mobile.RAN.netViewer
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestversion="1.0">
<assemblyidentity
version="1.0.0.0"
="" processorarchitecture="X86" name="T-Mobile.RAN.netViewer" type="win32">
<description>netViewer mobile network performance monitoring tool.
<dependency>
<dependentassembly>
<assemblyidentity
type="win32"
="" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorarchitecture="X86" publickeytoken="6595b64144ccf1df" language="*">
---
maximum 500 characters
|
|
|
|
|
Hi,
I am working on the UI application for a mouse driver.The UI has around 6-7 tabs in
its tab control.We need to redraw two of those tabs based on the user's option.To do
so,We are setting the tab control style of the tab as ownerdrawfixed and on getting
the WM_DRAWITEM message,We call textout() to make the text of the tab gray in
color.This application works fine on XP but on Vista,the tabs lose their theme(the
controls in the tab like Check boxes and buttons still retain the Vista theme).If we
donot set the tab style as ownerdrawfixed,the tabs regain their theme but I would not
be able to redraw the text of the tabs.
What could be going wrong with the application?How can I get back the Vista theme to
the tabs and also redraw the text of the tabs in gray?
Thanks,
|
|
|
|
|
Hi. I've ported most of this code to pure win32 (no MFC). I've left out afew things, but here it is anyway. Feel free to use it anyhow you please. Here is the code with a simple app demonstrating its use.
http://www.geocities.com/adelamro2004/files/TabWin32.zip
Happy coding, everyone.
|
|
|
|
|
Hi,
one problem I have in understanding your code is why you have used 3 CRect structures for a simple operation such as getting the dimensions of a Tab Control ? Since your code doesnt have any comments on this regard and since its difficuilt for me to comprehend the code in context, I would like an explanation on the use of
// 1st paint the tab body
CRect rcPage,rcItem,rcClient;
Why have these rects funny names as in Page, Item and Client ?
Yes, I am a beginner in control programming.
thanx, hoping to hear an answer from you soon !
Eraj.
|
|
|
|
|
Hi,
Thanks for writing such wonderful code. I am new to VC++, i include XPTabCtrl in my project, everything seems to be alright until when i am pointing to other tabs there was no highlight as in the example. Can i know why is this happen to my project ? Is that any DLL i have to include ? By the way when i use it in multiline i found out that when i am clicking to upper tabs, the lower tab that i click before is highlight as well. Why is this happen ?
Thanks for your help.
David
|
|
|
|
|
Have you already implemented this tab control with edit option in tab items?
If you have implemented, could you send me the code source?
|
|
|
|
|
I tried to use the buttom style on XP. When there are more tabs than the tab control can showm the spin buttons appears. However, when I used the spin button to view from the beginning tab to the end tab and end tab to begining, the outline of previous tab are showed and it looks like there are extra tabs but there isnt'. Do you have ideas that I fix it? Or , anyway, I can detect the spin button is pressed? Any ideas?
| last tab | | | <spin buttons="">
------------ ----
Thanks for your helps.
|
|
|
|
|
Whenver I choose my tab style as vertical in the dialog editor, it does not show tab labels. This problem is not occured while setting this style in the code using ModifyStyle, but after doing that tab labels are not shown when XP Theme is not active.
|
|
|
|
|
Hi Im experiencing the same problem too.
Infact this is the same reason, we are unable to use this great control on a CWnd.
You gotta create this in a CDialog ( dialog designer ) and set the "Visible" value to False. Thereafter in code the ModifyStyle method should be called and only in here should the vertical style be set so as to let the control have vertical text !
Hope this issue / BUG gets resolved soon !
|
|
|
|
|
When runing the App with xp themes, the the first page in the app is blank until you click on the tab the it populates it with a dialogue, in win2K it displays the first page by default!
i call SetCurSel in OnInitDialog but still does the same?\
Has anybody had this problem?
|
|
|
|
|
I've noticed several people on the list discussing their patches but not
all of the patches have been posted. Is it possible to get them?
Thanks
|
|
|
|
|
I had a look at this thread last week and I study about using this class or write my own one...
During reading some stuff @ newsgroups I found a article abaout XP Style and controls.
So I decide to use Applname.manifest to do the work (only under Windows XP)
Now any Standart controls lookz XP-like...
To test U can create within U /res directoy a .manifest file (XML) if not exists already..
just add a resource in U resource.h file
#define IDR_MANIFEST 1
#define RT_MANIFEST 24
within U .rc2 file U add a line
IDR_MANIFEST RT_MANIFEST MOVEABLE PURE "res\appname.manifest"
If U appl. runs under W2K it uses the W2K standart controls under XP it used the new XP Controls.
For me the better solution to deal with XP....
Hope it helkps somebody
C'ya
|
|
|
|
|
Sorry, but you've completely missed the point. The manifest is indeed a prerequisite for using XP themes in applications. Without it, your app will just look like a normal Win2k app.
The problem here, however, is that the XP implementation of tab controls is buggy and doesn't support any orientations other than vertical-top.
|
|
|
|
|
When left or right and have many buttons, appear a vertival spin button.
but the vertical spin button are not active.
|
|
|
|
|
Line 266 in XPTabCtrl.cpp says:
"if(pcImg) delete pcImg;"
it should say:
"if(pcImg) delete [] pcImg;"
|
|
|
|
|
Here's a fix so that true color images can be displayed on the tabs
void CXPTabCtrl::InitImageList(UINT nBitmapID, int nImageCount/*=0*/)
{
if(!::IsWindow(GetSafeHwnd()) || m_ilTabs.operator HIMAGELIST()){
ASSERT(FALSE);
return;
}
CBitmap bitmap;
if(bitmap.LoadBitmap(nBitmapID)){
BITMAP bmp;
if(bitmap.GetBitmap(&bmp)){
if(!nImageCount)
nImageCount = bmp.bmWidth / bmp.bmHeight; // use square images
if(m_ilTabs.Create(bmp.bmWidth / nImageCount, bmp.bmHeight, ILC_COLORDDB | ILC_MASK , nImageCount, 1)){
m_ilTabs.Add(&bitmap, RGB(255,0,255)); // transparency color magenta
SetImageList(&m_ilTabs);
return; // ok
}
}
}
ASSERT(FALSE); // error
}
|
|
|
|
|
Hi,
The control is great on XP with themes enabled - just what I needed.
But I need the control in left orientation showing text (with or without themes), and as discussed below - the text shows up horizontal instead of vertical (with themes disabled).
Has anyone fixed this ????
Can anyone say why the text isn't rotated ???
AFAIK, the comctrl5 CTabCtrl *IS* able to rotate the label text. I used this when I was developing under Win2k before. Now I am developing under XP, switching back and forth between Classic and XP look to test the control.
Thanks,
Fred
|
|
|
|
|
Being new to C++ I am having a few problems adding a page to a tab.
I have previously used m_tabPages[0]->Create(IDD_TAB_ONE, this); under CTabCtrl.
But am unsure how to approach it now.
Any help is appreciated.
Regards
Steve Kelly
|
|
|
|
|
Same problem here from a beginners point of view
|
|
|
|
|
OK, my problem with the XPTabCtrl + MadButch patch was that it doesn't allow for owner-drawn tabs. However, the fix for this is not too difficult. The problem is that the DrawTabItem function assumes the standard case (text/image list). So we need to test for the owner-draw flag, and if activated, call DrawItem with the correct info, thusly:
void CXPTabCtrl::DrawTabItem(CDC* pDC, int ixItem, const CRect& rcItemC, UINT uiFlags)<br />
{<br />
if (GetStyle() & TCS_OWNERDRAWFIXED)<br />
{<br />
DrawOwnerDrawTabItem(pDC, ixItem, rcItemC, uiFlags);<br />
}<br />
else<br />
{<br />
}<br />
}<br />
<br />
void CXPTabCtrl::DrawOwnerDrawTabItem(CDC* pDC,int ixItem,const CRect& rcItemC,UINT uiFlags)<br />
{<br />
DRAWITEMSTRUCT dis;<br />
TCITEM tcitem;<br />
<br />
ASSERT(pDC);<br />
if (pDC)<br />
{<br />
dis.CtlID = GetDlgCtrlID();<br />
dis.CtlType = ODT_TAB;<br />
dis.hDC = pDC->m_hDC;<br />
dis.hwndItem = GetSafeHwnd();<br />
dis.itemAction = ODA_DRAWENTIRE;<br />
<br />
VERIFY(TabCtrl_GetItem(GetSafeHwnd(), ixItem, &tcitem));<br />
dis.itemData = tcitem.lParam;<br />
<br />
dis.itemID = ixItem;<br />
dis.itemState = ((uiFlags&2)? ODS_SELECTED:0); <br />
dis.rcItem = rcItemC;<br />
<br />
DrawItem(&dis);<br />
}<br />
}<br />
I hope I got the DRAWITEMSTRUCT stuff right. There may be some minor detail I missed.
This fixes the problem...almost. If your custom drawing in DrawItem is done via the DC passed via the DRAWITEMSTRUCT, you're fine. However, I have sinned because I don't do this. I create some custom controls on the tabs and they don't get passed the DC, they just repaint themselves. This means that they get overpainted by the code at the end of DrawThemesXpTabItem, which dumps the content of the MemDC into the window DC. So I have come up with an ugly patch for this. Improvements welcome.
What I do is simply flag the owner-draw case and delay the call to DrawTabItem to the end. I have to save the ixItem variable because it's changed afterwards and I didn't want to inquire too closely as to why.
void CXPTabCtrl::DrawThemesXpTabItem(CDC* pDC, int ixItem, const CRect& rcItem, UINT uiFlag) <br />
{
<br />
BOOL bBody =(uiFlag& 1)?TRUE:FALSE;<br />
BOOL bSel =(uiFlag& 2)?TRUE:FALSE;<br />
BOOL bHot =(uiFlag& 4)?TRUE:FALSE;<br />
BOOL bBottom=(uiFlag& 8)?TRUE:FALSE;
BOOL bVertic=(uiFlag&16)?TRUE:FALSE;
BOOL bLeftTab=!bBottom && bVertic && !bBody;<br />
<br />
bool bDelayDrawItem = ((GetStyle() & TCS_OWNERDRAWFIXED) != 0);<br />
int ixDelayItem = -1;<br />
<br />
CSize szBmp=rcItem.Size();<br />
if(bVertic) SwapVars(szBmp.cx,szBmp.cy);<br />
<br />
...<br />
<br />
if(bVertic)<br />
{ if(bBody || !bBottom) bihOut.biHeight=-szBmp.cy;<br />
if(!bBottom && !bBody && ixItem>=0)
{ if(bSel) rcMem.bottom--;<br />
<br />
if (!bDelayDrawItem)<br />
{<br />
DrawTabItem(&dcMem, ixItem, rcMem, uiFlag);<br />
}<br />
else<br />
{<br />
ixDelayItem = ixItem;<br />
}<br />
ixItem=-1;<br />
} }
...<br />
<br />
if(!bBody && ixItem>=0)
{ if(bSel) rcMem.bottom--;<br />
<br />
if (!bDelayDrawItem)<br />
{<br />
DrawTabItem(&dcMem, ixItem, rcMem, uiFlag);<br />
}<br />
else<br />
{<br />
ixDelayItem = ixItem;<br />
}<br />
<br />
if(bVertic)
{ bihOut.biHeight=-szBmp.cy;<br />
GetDIBits(*pDC, bmpMem.operator HBITMAP(),nStart,szBmp.cy-nLenSub,pcImg,&biOut,DIB_RGB_COLORS);<br />
} }<br />
<br />
...<br />
<br />
pDC->BitBlt(rcItem.left,rcItem.top,szBmp.cx,szBmp.cy,&dcMem,0,0,SRCCOPY);
dcMem.SelectObject(pBmpOld);<br />
<br />
if (bDelayDrawItem && ixDelayItem != -1)<br />
{<br />
DrawTabItem(&dcMem, ixDelayItem, rcMem, uiFlag);<br />
}<br />
}<br />
Well, it's not pretty but it's working for me at the moment. I'll keep you posted.
|
|
|
|
|
Alas, all is not well with my fix. I've discovered that it can cause nasty random crashes. Well, not random really. "Random" means "whose cause I do not yet understand".
I'm looking into it.
|
|
|
|
|
OK, I think I fixed it. Apart from the prudent addition of a call to ZeroMemory, which I shouldn't have omitted, the only change is to omit passing lParam from TCITEM to itemData in DRAWITEMSTRUCT. It now seems clear that this is *NOT* what you are supposed to do. Apparently you just use the lParam data for your purposes in other tab control functions. But I haven't been able to dig up much information on the use of itemData either; the documentation only mentions its use in the case of combos and lists.
All that's needed is to replace my original version of DrawOwnerDrawTabItem with this one:
<br />
void CXPTabCtrl::DrawOwnerDrawTabItem(CDC* pDC,int ixItem,const CRect& rcItemC,UINT uiFlags)<br />
{<br />
DRAWITEMSTRUCT dis;<br />
<br />
ASSERT(pDC);<br />
if (pDC)<br />
{<br />
ZeroMemory( (void *)&dis, sizeof(DRAWITEMSTRUCT) ); <br />
dis.CtlID = GetDlgCtrlID();<br />
dis.CtlType = ODT_TAB;<br />
dis.hDC = pDC->m_hDC;<br />
dis.hwndItem = GetSafeHwnd();<br />
dis.itemAction = ODA_DRAWENTIRE;<br />
dis.itemData = 0;<br />
dis.itemID = ixItem;<br />
dis.itemState = ((uiFlags&2)? ODS_SELECTED:0); <br />
dis.rcItem = rcItemC;<br />
<br />
DrawItem(&dis);<br />
}<br />
}<br />
Have fun.
|
|
|
|
|
When resizing the tab, ghosting appears in the part of the screen where labels could be drawn (but are not). Let's say you have a tab control of 400 pixels wide, with 2 tabs under it, both 50 pixels wide. You would then have an area to the right (300 pixels wide) that would not be redrawn on resizing.
I wrote an "as flicker free as possible" solution for it, and here is the code:
(this is old code , and this is new code )
<br />
void CXPTabCtrl::OnPaint() <br />
{<br />
if(!IsExtendedTabTheamedXP())
{ Default(); return; } <br />
CPaintDC dc(this);
<br />
CRect rcClip; rcClip.SetRectEmpty();<br />
dc.GetClipBox(rcClip);<br />
<br />
CRect rcPage,rcItem,rcClient;<br />
GetClientRect(&rcPage);<br />
rcClient=rcPage;<br />
AdjustRect(FALSE,rcPage);<br />
<br />
switch(m_eTabOrientation)<br />
{ case e_tabTop: rcClient.top =rcPage.top -2; break;<br />
case e_tabBottom: rcClient.bottom=rcPage.bottom+3; break;<br />
case e_tabLeft: rcClient.left =rcPage.left -1; break;<br />
case e_tabRight: rcClient.right =rcPage.right +3; break;<br />
default: ASSERT(FALSE); return;<br />
}<br />
UINT uiVertBottm;<br />
uiVertBottm =(m_eTabOrientation&1)? 8:0;
uiVertBottm|=(m_eTabOrientation&2)?16:0;
UINT uiFlags=1|uiVertBottm;
DrawThemesXpTabItem(&dc, -1, rcClient,uiFlags);
<br />
int nTab=GetItemCount();
if(!nTab) return;
<br />
<br />
CRgn rgnItem;
CRgn rgnRepaintArea;
CRect rcRepaintArea;
<br />
VERIFY( GetItemRect( 0, &rcItem) );<br />
if( m_eTabOrientation == e_tabTop )<br />
{<br />
rcRepaintArea.top = rcItem.top - 2;
rcRepaintArea.bottom = rcItem.bottom;<br />
rcRepaintArea.left = rcClient.left;<br />
rcRepaintArea.right = rcClient.right;<br />
}<br />
else if( m_eTabOrientation == e_tabBottom )<br />
{<br />
rcRepaintArea.top = rcItem.top;<br />
rcRepaintArea.bottom = rcItem.bottom + 2;
rcRepaintArea.left = rcClient.left;<br />
rcRepaintArea.right = rcClient.right;<br />
}<br />
else if( m_eTabOrientation == e_tabLeft )<br />
{<br />
rcRepaintArea.top = rcClient.top;<br />
rcRepaintArea.bottom = rcClient.bottom;<br />
rcRepaintArea.left = rcItem.left - 2;
rcRepaintArea.right = rcClient.left;
}<br />
else if( m_eTabOrientation == e_tabRight )<br />
{<br />
rcRepaintArea.top = rcClient.top;<br />
rcRepaintArea.bottom = rcClient.bottom;<br />
rcRepaintArea.left = rcItem.left;<br />
rcRepaintArea.right = rcItem.right + 2;
}<br />
<br />
rgnRepaintArea.CreateRectRgnIndirect( rcRepaintArea );<br />
rgnItem.CreateRectRgn( 0, 0, 0, 0 );<br />
<br />
<br />
TCHITTESTINFO hti; hti.flags=0;<br />
::GetCursorPos(&hti.pt); ScreenToClient(&hti.pt);<br />
int ixHot=HitTest(&hti);<br />
int ixSel=GetCurSel();<br />
<br />
for(int ixTab=0; ixTab<nTab; ixTab++)<br />
{ if(ixTab==ixSel)<br />
continue;<br />
VERIFY(GetItemRect(ixTab, &rcItem));<br />
if(m_eTabOrientation==e_tabLeft) rcItem.right++;<br />
uiFlags=uiVertBottm|(ixTab==ixHot?4:0);
DrawThemesXpTabItem(&dc,ixTab,rcItem,uiFlags);<br />
rgnItem.SetRectRgn( rcItem );<br />
rgnRepaintArea.CombineRgn( &rgnRepaintArea, &rgnItem, RGN_DIFF );<br />
}<br />
VERIFY(GetItemRect(ixSel, &rcItem));
rcItem.InflateRect(2,2);<br />
if(m_eTabOrientation==e_tabTop) rcItem.bottom--;<br />
uiFlags=uiVertBottm|2;
DrawThemesXpTabItem(&dc, ixSel, rcItem,uiFlags);<br />
rgnItem.SetRectRgn( rcItem );<br />
rgnRepaintArea.CombineRgn( &rgnRepaintArea, &rgnItem, RGN_DIFF );<br />
<br />
HBRUSH hBrBack = (HBRUSH) ::GetClassLong( GetParent()->GetSafeHwnd(), GCL_HBRBACKGROUND );<br />
if( hBrBack == 0 )<br />
{<br />
hBrBack = ::GetSysColorBrush( COLOR_BTNFACE );<br />
}<br />
dc.FillRgn( &rgnRepaintArea, CBrush::FromHandle( hBrBack ) );<br />
}<br />
|
|
|
|
|
Hi
Nice work. Just one thing - it seems like you forgot to finish the left/right orientation bit. You've left two lines commented:
and it looks as though you realised that the code before it would be valid for all orientations, but then forgot to remove the previous if statement:
if( ( m_eTabOrientation == e_tabTop ) ||<br />
( m_eTabOrientation == e_tabBottom ) )<br />
As a result, if you have left or right tabs, there's a very nasty crash indeed .
I think the solution is to remove that condition and then add code to subtract 2 from the left or right sides, depending on the orientation. I'm not sure whether there's anything else missing. I have to do some more tests.
Also, I'm not sure what I'll have to do to get this working with my tab control class, because I've overridden the DrawItem function to place controls on each tab, and it seems like this implementation just takes over the drawing completely. Anybody got any hints? I'll look at it tomorrow in any case.
|
|
|
|
|