|

Using CXPTabCtrl, XP Themes Tab Control, left, bottom and right orientation
Introduction
The article shows how to solve a problem, which appears on the Windows Tab Control when using Windows XP operating system with XP Themes enabled. Tab control behaves as if it has only one orientation - top. In fact, it has all four orientations, but all four of them (for some reason) have the same appearance.
It is demonstrated how to use the proposed class CXPTabCtrl, Windows tab control extension as a solution to this problem. CXPTabCtrl detects the operating system and tab control orientation:
- If it is not XP system or XP Themes are not enabled - it uses default Windows tab behavior (it does not do anything extra).
- If it is XP system and XP Themes are enabled - it draws tab control properly in appropriate direction.
CXPTabCtrl control also works properly if the state of XP Themes enabling is changed during the running of the application. Tab control hot tracking is also supported.
Background
There are a lots of Windows applications developed for earlier Windows versions, which use bottom or other "not-top" oriented Windows tab control. The problem is: if the application is running on an XP system with XP Themes, Windows tab control is not shown properly as it used to be.

Problems when using default SysTabControl32 (CTabCtrl) with XP Themes, bottom orientation
One possibility to solve this problem is to change all tab controls in these applications to be top oriented. This would involve change of the look of the applications and painful Windows resource changes and possible code changes.
Another possibility (used for CXPTabCtrl) is to use a thin wrapper around the tab control and to simulate missing orientations. CXPTabCtrl uses available XP Themes "top-tab" look as a template and adapts it for other tab orientations:
- Bottom orientation:
- use top background bitmap,
- mirror it vertically,
- draw icon and text on mirrored background.

- Left orientation:
- use top background bitmap,
- draw icon and text on the background,
- rotate the bitmap for 90°.

- Right orientation:
- use top background bitmap,
- mirror it vertically,
- draw icon and text on the background,
- rotate the bitmap for 90°.

- Top orientation (used only for test purposes, could use default from XP Themes Windows XP):
- use top background bitmap,
- draw icon and text.

Notice also that the body of the tab control has to be manipulated, mirrored or rotated, not only the "tab" parts of the tab control (because a "tab body" has texture and shadows).
How to use it
The CXPTabCtrl class is simple to use. To add it to your project, please follow the steps below:
- Put its source files (XPTabCtrl.cpp and XPTabCtrl.h) into the proper project folder and add their file names to your Visual Studio project.
- Include its header to the appropriate header file - usually dialog class header where class
CXPTabCtrl is used. If you plan to use CXPTabCtrl in several places of your application, you can add it only to your StdAfx.h file: #include "XPTabCtrl.h"
- You should replace
CTabCtrl with CXPTabCtrl everywhere in the project where you want new XP Themes tab behavior. CXPTabCtrl m_tabCtrl
- If
CXPTabCtrl has images, then appropriate bitmap IDB_TABIMAGES (or other with correct tab images) should be included as resource bitmap. It is also necessary to call InitImageList(IDB_TABIMAGES) function, from OnInitDialog or other appropriate initializing place: m_tabCtrl.InitImageList(IDB_TABIMAGES);
Although tab control orientation is usually set in resource editor or in Tab's Create function, CXPTabCtrl orientation can be changed any time while application is running.
Points of Interest
This sample could also be used as an example of how to solve some other problems in Windows programming. Other techniques shown in this sample include:
- How to mirror bitmap image vertically fast and simply by using only two Windows calls
GetDIBits and SetDIBits. This works in any color resolution.
- How to rotate rectangular bitmap image fast and in any color resolution.
- How to use inline assembler for lengthy repetitive processing, in this case, rotating bitmap image pixels. If image is of large dimensions (large tab control body), a C style coding could take considerable more time than assembler version.
- How to use XP Themes functions in applications, which can run on earlier operating systems.
- How to enable XP Themes dialog texture background.
- How to make applications XP Themes aware by simply copying XP manifest, resource "24", ID "1" from one application resource to another.
- How to use tab ToolTips.
Please note
- The sample is created and compiled on VC++ 6.0 service pack 5.
- The sample has been tested on Windows XP (XP Themes enabled or disabled while sample was running).
- The sample has also been tested on Windows 2000, Windows NT 4.0 (
CXPTabCtr does not have effect).
- Other Windows systems could have possible problems (?)
- The sample has been tested on the following color resolutions: 8 bit, 16 bit, 24 bit and 32 bit colors.
- The sample has not been tested on multi-line (stacked) tabs, could be problems (?)
Correspondence
Please post your questions, suggestions and bug reports only to the forum below.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 56 (Total in Forum: 56) (Refresh) | FirstPrevNext |
|
 |
|
|
 |
|
|
 |
|
|
How can I to use CXPTabCtrl with ATL if I have a Tab control in a Dialog Box ?
Can some body tell to me?
Thanks in advance.
JPMPHOENIX
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
I don't mean to be disrespectful, so please don't get too offended.
I downloaded your source code and have had closer look at it and I'm sorry to say that I found it extremely hard to follow.
One example is the way you build a flag of some sort where you write: uiVertBottm =(m_eTabOrientation&1)? 8 ; uiVertBottm|=(m_eTabOrientation&2)?16 ;
Why not, in the name of pedagogy, write something like below?!? if (m_eTabOrientation == e_tabBottom) uiVertBottm = 8; if (m_eTabOrientation == e_tabLeft || m_eTabOrientation == e_tabRight) uiVertBottm |= 16;
I think stupid guys like me would find it easer to understand (and that is, or at least I would like to think it is, the point of posting stuph here, to educate others in some way).
Half way in the "CXPTabCtrl::OnPaint()" function I found comments which simply isn't descriptive at all (what does // TABP_PANE=9,0,'TAB' mean for example?!?).
I also found strange instantiations like "CRect ;" (line 105, the same function) which I still today don't see the point of.
Now, I'm far from a senior programmer or anything like that, but I do believe in the concept of "Simple is beautiful" and I personally would have enough pride in craftsmanship to clean up my code if I was to post it in a public media.
cheers
-- modified at 8:17 Friday 6th July, 2007
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I think its just a matter of opinion. I for example find the original code more simple and beautiful. But perhaps I am just a fossil since I have been programming since the dinosaur days of Kernighan and Ritchie C.
-David Delaune
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi!
Thanks for your great tabcontrol, but there seems to be a problem with the drawing of the tabs, if the scrollbar appears. If I add 8 or 9 Tabs, the area right of the last tab and around the arrows of the scrollbar is not drawn correctly. Sometimes the hidden tabs have a dashed orange line above, when I scroll back to them.
Am I making something wrong or is there a bugfix?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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 // source index mov edi, pcImgRotate // destination index xor ebx, ebx // vertical counter loop_height: mov ecx, nWidth // horizontal counter cmp ebx, nHeight1 // check is it the last line jne loop_width dec ecx // if it is decremnt for the last pixel je do_last // if width was one do the last pixel now loop_width: movsd // copies 4 bytes and increments dec edi // adjust edi to 'as incremented by 3' add esi,nBmpWdtPS // adjust esi to the next source line loop loop_width // loop one hotizontal destination line
cmp ebx, nHeight1 // check is it the last line je do_last // if not last, do incrementing here inc ebx // increment vertical counter add edi, nPadD // adjust destination index by possible padding to DWORD mov esi, ebx // reset the source index: add vertical counter * 3 shl esi, 1 // (is the same as * 2 +1*) add esi, ebx // +1* add esi, pcImg // add to the beginning of the source jmp loop_height // loop whole height
do_last: // the last pixel is done by movsw // moving first two bytes movsb // and than by moving the very last byte }
-- modified at 2:43 Wednesday 20th June, 2007
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
version="1.0.0.0" processorArchitecture="X86" name="T-Mobile.RAN.netViewer" type="win32" /> netViewer mobile network performance monitoring tool.
type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*" />
--- maximum 500 characters
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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,
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
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.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | 1.50/5 (2 votes) |
|
|
|
 |
|
|
Have you already implemented this tab control with edit option in tab items? If you have implemented, could you send me the code source?
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
|
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 | | | ------------ ----
Thanks for your helps.
|
| Sign In·View Thread·PermaLink | 1.00/5 (2 votes) |
|
|
|
 |
|
|
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.
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
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 !
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
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?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | 1.50/5 (2 votes) |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | 1.14/5 (5 votes) |
|
|
|
 |
|
|
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.
|
| Sign In·View Thread·PermaLink | 2.50/5 (2 votes) |
|
|
|
 |
|
|
When left or right and have many buttons, appear a vertival spin button.
but the vertical spin button are not active.
|
| Sign In·View Thread·PermaLink | 3.50/5 (2 votes) |
|
|
|
 |
|
|
Line 266 in XPTabCtrl.cpp says: "if(pcImg) delete pcImg;"
it should say: "if(pcImg) delete [] pcImg;"
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
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 }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | 2.00/5 (3 votes) |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|