|

With this class you can easily give a skin to your buttons in few steps:
- Add xSkinButton.cpp and xSkinButton.h to the project.
- Include xSkinButton.h in the header file where the controls are defined
- Create (or edit) a member variable for each button you want to customize as
CxSkinButton. If the Class Wizard doesn't show the CxSkinButton type, select CButton and then edit the code manually.
- Add the bitmap resource for the buttons:
- NORMAL bitmap: default button image.
- DOWN bitmap: pushed button image.
- OVER bitmap:(optional) image to shown when the mouse is over the button. If NULL, NORMAL bitmap will be used.
- DISABLED bitmap: (optional) image for the disabled state. If NULL, NORMAL bitmap will be used.
- FOCUS bitmap: (optional) image for the focused state. If NULL, NORMAL bitmap will be used.
- MASK bitmap: (optional) clipping region. If you don't use the MASK, the button will be a rectangular owner-draw control. The default transparent color is RGB(255,255,255).
- In the window initialization add the
CxSkinButton methods:
BOOL CxSkinButtonDemoDlg::OnInitDialog()
{
m_btn1.SetTextColor(RGB(255,0,0));
m_btn1.SetToolTipText("Button1");
m_btn1.SetSkin(IDB_B1NORM,IDB_B1DOWN,IDB_B1OVER,IDB_B1GRAY,
0,IDB_B1MASK,0,0,0);
The SetTextColor and SetToolTipText are self explaining; SetSkin is:
void CxSkinButton::SetSkin(UINT normal,UINT down,UINT over,
UINT disabled, UINT focus,UINT mask,
short drawmode, short border,
short margin)
- normal, down, over, disabled, focus, mask = bitmap resource IDs
- drawmode = if mask is not NULL, this should be 0 (normal); else you can try 1 (stretch) or 2 (tiled).
- border = if mask is not NULL or is not rectangular, this should be 0; else you can try 1 to draw the standard 3D border around the button.
- margin = if mask is not NULL or is not rectangular, this should be 0; else you can try to change this value to draw a dotted rectangle over the button when the control has the focus.
Remarks
- The BS_OWNERDRAW style is added automatically, you don't need to set the "Owner draw" property in the resource editor.
- only NORMAL and DOWN bitmaps are essential; OVER bitmap is a plus.
- DISABLED bitmap is not necessary if the button is always enabled. You can also use the button text (automatically etched) to show the disabled state.
- MASK bitmap is not necessary if the button is rectangular.
- for rectangular buttons you should set the margin parameter greater than 0 (4 is a good choice), or use the FOCUS bitmap.
- for rectangular buttons you can use 'flat' bitmaps and set the border parameter to 1. In this situation, NORMAL and DOWN bitmaps can also share the same resource.
Release History
v1.00 - 15/03/2001 - basic implementation and interface. v1.10 - 28/03/2001 enhanced mouse tracking implementation (by Milan Gardian). - SetCapture removed: accelerators now are dispatched. - Double-click handling. - Better behavior during "button-pressed" (mouse button down & holding) phase v1.20 - 02/04/2001 - New CreateRgnFromBitmap() implementation. Mask bitmap now works in any display color mode, any mask color depth and any mask size. v1.21 - 14/04/2001 - OnMouseLeave cast error fixed. - Fixed FocusRect defect when OVER bitmap was NULL. v1.30 - 25/04/2001 - Fixed CreateRgnFromBitmap failure under WinNT4.0 v1.40 - 29/06/2001 - check & radio button add on. - added "focus" bitmap. - fixed CreateRgnFromBitmap bug. - fixed shortcut bug. - fixed text drawing code. v1.41 - 27/10/2001 - Fixed memory leakage in CreateRgnFromBitmap v1.50 - 07/07/2008 - fixed memory leaks using SelectObject and GetDC (thanks to sachelis and Bernd Giesen) - added SetToolTipColor (thanks to Mykel)
Compatibility
Win95,WinNT = Yes, requires IE3.0 or higher Win98, WinME, W2k, WinXP = Yes
Thanks to all the Code Project developers! Special thanks to: Milan Gardian for mouse and keyboard tracking code. Fable(at)aramszu(dot)net for ExtCreateRegion replacement code. Rainer Mangold for radio-button and check-box code. Andy Green and Cameron Epp for suggestions & debugging.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 76 (Total in Forum: 76) (Refresh) | FirstPrevNext |
|
|
 |
|
|
I hope the other endevors were as rewarding. You must be good in anything you do. Thanks for all the contributions.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
i recently building a mfc regular dll using xSkinButton but if i use a radio button, when check one radio button ,the other radio buttons can't automatically uncheck itself, who knows why this happen? how to solve the problem?
thanks a lot!
arlerzhang
life is like a pack of chaocolite
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
I found this really useful, and want to use this in my application ! Can I use this in a commercial application? Does the license permit it ?
|
| Sign In·View Thread·PermaLink | 1.83/5 (3 votes) |
|
|
|
 |
|
|
Whenever I Use the Mask Bmp the Button Gets Disabled please help me why button gets Disable when I use Mask image.
m_Button_ScanTool2.SetSkin(IDB_CROP_NORMAL,IDB_CROP_PRESSED,IDB_CROP_HOVER,IDB_CROP_PRESSED,0,IDB_MASK,0,0,0);
|
| Sign In·View Thread·PermaLink | 3.00/5 (2 votes) |
|
|
|
 |
|
|
 |
|
|
I'd like to automatically map appropriate images according to resource ID. What's the easiest way to get nIDCtl from the subclass?
Is it possible to use: OnDrawItem(UINT nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
Instead of: DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
Or, is there another way that I could try?
Thanks!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
My dialog have 10-20 "CxSkinButton" buttons And some buttons does now draw text! In debug version - it's ok But in release - there are no text on the buttons!
Can anyone help me?
ps Compiled with VC++ 6.0, Windows 98 SE
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
My dialog have 10-20 "CxSkinButton" buttons And some buttons does now draw text! In debug version - it's ok But in release - there are no text on the buttons!
Can anyone help me?
ps Compiled with VC++ 6.0, Windows 98 SE
|
| Sign In·View Thread·PermaLink | 2.33/5 (3 votes) |
|
|
|
 |
|
|
In xSkinButton.cpp, line 311, change the code as follows:
< dcBmp.SelectObject(hBmp); > HBITMAP hOldBitmap = (HBITMAP)dcBmp.SelectObject(hBmp);
Then add the following line 356 (just before dcBmp.DeleteDC()):
dcBmp.SelectObject( hOldBitmap );
Otherwise, you will be deleting the DC with the bitmap still selected.
Steve
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
There are many other places where SelectObject() needs to store the return value and then select the old object before calling DeleteDC(). Here are a few, but it's best if you simply search for all calls to SelectObject() and DeleteDC().
For example, SelectObject() calls near lines 198, 202, and 207 need to be changed so they store the return value. For example:
HBITMAP hOldBitmap1 = (HBITMAP)hdcMem.SelectObject(hBitmap);
Then you need to deselect the old bitmap just before the calls to DeleteDC() (near lines 225, 228, and 243) by adding code similar to:
hdcMem.SelectObject( hOldBitmap1 );
Steve
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
There is still at east on other GDI leak in the SetSkin() method assuming one will set the skin more than once:
Change the the follwing lines in CxSkinButton::SetSkin(...):
SetWindowRgn(m_hClipRgn, TRUE); SelectClipRgn((HDC) GetDC(),m_hClipRgn);
to: SetWindowRgn(m_hClipRgn, TRUE); CDC *pDC = GetDC(); SelectClipRgn(pDC->GetSafeHdc(), m_hClipRgn); ReleaseDC(pDC);
to ensure, that the DC is properly released.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
There's IMO a flaw in CxSkinButton::DrawItem method. If the CxSkinButton object represents e.g. a checkbox with "normal" button text, the text in the pushed/checked state of the button is not displayed properly if the button becomes disabled. That is the position of the checked, disabled button text is wrong.
To fix this change the appropriate section in the DrawItem() method as follows:
// Select the correct skin if (lpDrawItemStruct->itemState & ODS_DISABLED){ // DISABLED BUTTON if(m_bDisabled.m_hObject==NULL) // no skin selected for disabled state -> standard button pDC->FillSolidRect(&r,GetSysColor(COLOR_BTNFACE)); else // paint the skin DrawBitmap(pDC,(HBITMAP)m_bDisabled,r,m_DrawMode); // if needed, draw the standard 3D rectangular border if (m_Border) pDC->DrawEdge(&r,EDGE_RAISED,BF_RECT); // paint the etched button text pDC->SetTextColor(GetSysColor(COLOR_3DHILIGHT)); //Fix: Check if button is in checked/pushed state if (m_Checked) OffsetRect(&tr,1,1);
pDC->DrawText(sCaption,&tr,DT_SINGLELINE|DT_VCENTER|DT_CENTER); pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT)); //Fix: Remove this line: OffsetRect(&tr,-1,-1); pDC->DrawText(sCaption,&tr,DT_SINGLELINE|DT_VCENTER|DT_CENTER); } else { // SELECTED (DOWN) BUTTON ...
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Great class! 
I'm working on a user-skinnable application so I need to load the images from files. The way I accomplished this was to replace the UINT's with LPCTSTR's in the SetSkin() parameters and modified the following code:
if (normal>0) //m_bNormal.LoadBitmap(normal); { HBITMAP hNormal=(HBITMAP)::LoadImage(AfxGetInstanceHandle(), normal, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); m_bNormal.Attach(hNormal); }
My question is, will this cause any problems, or is there any additional clean-up that I need to be concerned with? I'm fairly new to C++.
Thanks, Wolf
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
WolfSupernova wrote: Great class!
thanks 
WolfSupernova wrote: will this cause any problems
you must release the bitmaps in the destructor or before you Attach a bitmap over an existing one. With resources this was not necessary
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
I want to have the same effect on key board usage. What I mean is that when you push up-arrow key the button change the state from normal to mouse over
Thanks Shin
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hey. I have a question. In my program, i want to hide the buttons so they dont' show up in some pages, any of you know how to do that ?
thanks.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi again. I just figured it out =) groups.google.com is a good resource as well. I used the ShowWindow function.
ShowWindow(SW_SHOW); or ShowWindow(SW_HIDE);
thanks anyways
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hey. I have a question. In my program, i want to hide the buttons so they dont' show up in some pages, any of you know how to do that ?
thanks.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I'm currently using the cxSkinButton class and noticed some problems with it under VC++7. It's not a huge deal but kind of annoying. If I create a new project using the wizard and include the manifest the tool tips don't work 100%. They will show up but if I click a button the tool tip for that button doesn't come back. Also, if I hold my mouse over a button until the tool tip goes away it won't come back again either. I'm only able to get the tool tip to come back if I pop up an AfxMessageBox and then close it. If I create another new project without a manifest the tool tips work perfectly. Has anybody else had this problem? I'm not even adding anything into the manifest. It only contains the stuff that VC++ puts in there by default. I could just remove the manifest but then I'd lose the newer interface features like the rounded buttons etc. I guess I could just use the skin control and make them whatever I want anyway but I'd like to find away to make the tool tips work right with the manifest and cxSkinButton.
-scully12
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hi scully12,
I have the same problem here with the lost tooltips, independent if I use the CxSkinButton class or simply the CButton class. So, CxSkinButton is not the reason why, it seems to be a general problem in VC++7 (the same sources built with VC++6 work perfectly, w/o the manifest, of course).
Did you find any solution in the meantime fro the issue?
Bernd
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Bernd, I never did find a solution. I ended up just removing the manifest and using it that way. I was hoping that it really was a bug in VC and it would get fixed eventually. It's good to hear that I'm not crazy though.
-scully12
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hi scully12,
I have the same problem, I add some code at when the button losted focus. //code : if ( m_ctrlTooltip.m_hWnd != NULL ) m_ctrlTooltip.Pop(); //code end;
now, my button work fine!
sorry, my english was very pool
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi!
I have a small improvement for the tooltip of a CxSkinButton. With this function you can colorize the tooltip as you want. The first COLORREF ist the text color, the second is the background color.
void CxSkinButton::SetToolTipColor(COLORREF crText, COLORREF crBkgnd) { if(m_tooltip.m_hWnd != NULL) { if(crText != NULL ) m_tooltip.SetTipTextColor(crText);
if(crBkgnd != NULL) m_tooltip.SetTipBkColor(crBkgnd); } }
Perhaps someone will have use for it... 
bye...
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|