Enhanced Colored Button
This button is based on the work of John Wellbelove, January 8, 2002.
A problem with push button controls is that you cannot change the default drawing colors. WM_CTLCOLOR does not work for push buttons. The only way to use other colors for a push buttons is to use an owner-draw button and do the drawing by yourself.
By using CColorButton, you can:
- Change, at any time, any of the seven colors needed to draw a button
- Align the text at any position
- Use multi-line text
- Create buttons dynamically
- Change the default font of the text
What Does CColorButton Bring New?
In addition to previous controls, CControlButton allows the usage of multiline text. You can do this either by checking the multiline option in the Styles tab from the Properties window of the button, or by using the BS_MULTILINE flag when creating the control. BS_MULTILINE flag can be added to the button styles or removed from them by using the GetWindowLong and SetWindowLong methods. Lines are separated by using .\n.. See the example in the "How to Create a Dynamic CColorButton" section.
The first example here shows how to remove the multiline style, and the second how to add it.
void CColoredButtonDlg::OnButton1()
{
DWORD dwStyles = GetWindowLong(m_dynamic->GetSafeHwnd()
GWL_STYLE);
dwStyles &= ~BS_MULTILINE;
SetWindowLong(m_dynamic->GetSafeHwnd(), GWL_STYLE, dwStyles);
m_dynamic->SetWindowText("Dynamic Created");
m_dynamic->Invalidate();
}
void CColoredButtonDlg::OnButton3()
{
DWORD dwStyles = GetWindowLong(m_dynamic->GetSafeHwnd(),
GWL_STYLE);
dwStyles |= BS_MULTILINE;
SetWindowLong(m_dynamic->GetSafeHwnd(), GWL_STYLE, dwStyles);
m_dynamic->SetWindowText("Dynamic\nCreated");
m_dynamic->Invalidate();
}
CControlButton also allows text alignment in different vertical and horizontal positions. You can set the position of the text either from the Styles tab of the Properties window of the button (Horizontal Alignment and Vertical Alignment combo boxes) or by using the BS_TOP, BS_VCENTER, or BS_BOTTOM flags for vertical alignment, and BS_RIGHT, BS_CENTER, and BS_LEFT for horizontal alignment.
Here is an example of how to change the alignment of the button text from left to right.
void CColoredButtonDlg::OnButton6()
{
DWORD dwStyles = GetWindowLong(m_dynamic->GetSafeHwnd(),
GWL_STYLE);
dwStyles &= ~BS_LEFT;
dwStyles |= BS_RIGHT;
SetWindowLong(m_dynamic->GetSafeHwnd(), GWL_STYLE, dwStyles);
m_dynamic->Invalidate();
}
CColorButton Header
class CColorButton : public CButton
{
private:
enum {BUTTON_IN = 0x01,
BUTTON_OUT = 0x02,
BUTTON_BLACK_BORDER = 0x04,};
// Construction
public:
CColorButton();
CColorButton(COLORREF text, COLORREF bkgnd);
CColorButton(COLORREF text, COLORREF bkgnd, COLORREF disabled);
CColorButton(COLORREF text, COLORREF bkgnd, COLORREF disabled,
COLORREF light, COLORREF highlight,
COLORREF shadow, COLORREF darkShadow);
// Attributes
public:
private:
COLORREF m_TextColor;
COLORREF m_BkgndColor;
COLORREF m_DisabledBkgndColor;
COLORREF m_Light;
COLORREF m_Highlight;
COLORREF m_Shadow;
COLORREF m_DarkShadow;
// Operations
public:
void SetColor(COLORREF text, COLORREF bkgnd);
void SetColor(COLORREF text, COLORREF bkgnd, COLORREF disabled);
void SetColor(COLORREF text, COLORREF bkgnd, COLORREF disabled,
COLORREF light, COLORREF highlight,
COLORREF shadow, COLORREF darkShadow);
void SetColorToWindowsDefault();
private:
void DrawFrame(CDC *pDC, CRect rc, int state);
void DrawFilledRect(CDC *pDC, CRect rc, COLORREF color);
void DrawLine(CDC *pDC, long sx, long sy, long ex, long ey,
COLORREF color);
void DrawButtonText(CDC *pDC, CRect rc, CString strCaption,
COLORREF textcolor);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CColorButton)
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CColorButton();
// Generated message map functions
protected:
//{{AFX_MSG(CColorButton)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CColorButton has several contructors, allowing you to set the colors of the button. Colors also can be set by using the overloaded SetColors() method. By default, the colors used are system's ones.
If you want to set the colors to those used by the system to draw the button, call SetColorsToWindowsDefault().
How to Use CColorButton
- Include colorbutton.h and colorbutton.cpp in your project.
- Add a button to your resource dialog, (e.g. IDC_BUTTON_COLOR).
- Include colorbutton.h in your dialog class header.
- Using ClassWizard and a control variable for the button (e.g. m_button).
- Replace CButton with CColorButton as the type of the new added control variable:
CColorButton m_button;
m_button1.SetColor(RGB(255,0,0), RGB(255,255,255));
How to Create a Dynamic CColorButton
- Declare a variable in your header:
CColorButton* m_dynamic;
m_dynamic = new CColorButton(BLUE, LBLUE);
m_dynamic->Create("Dynamic\nCreated",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|
BS_OWNERDRAW|BS_MULTILINE,
rc,this,IDC_BUTTON_DYN);
m_dynamic->ShowWindow(SW_SHOW);
BOOL CColoredButtonDlg::DestroyWindow()
{
m_dynamic->DestroyWindow();
delete m_dynamic;
m_dynamic = NULL;
return CDialog::DestroyWindow();
}

Comments
I have a different problem
Posted by Hyd on 11/05/2008 07:13pmCan i use include "color.h" from multiple header files for the same Workspace. Ex: I have 2 dialogs and each of them has bunch of button controls. If i include the color.h header file for one dialog it works fine. But if i include the header for a different file but all is basically located in one workspace. It throws class type redefinition. does someone has clue on this?
-
ReplyRe: I have a different problem
Posted by cilu on 11/07/2008 01:47amYou should be able to include use this class in as many dialogs as you want. Your description is confusing. You say "include the color.h header file for one dialog", but I guess you mean "in a dialog". You say "but all is basically located in one workspace" but you didn't explain whether it's a single project, or different projects. Please clarify these.
ReplyGreat Article, it works(VC++ 6.0)
Posted by Hyd on 11/05/2008 06:24pmI've created my own colorbutton header and cpp files by taking most of the hints provided in this article. Dont forget to check Owner Draw style for the control. Thank you so much the article was very helpful.
ReplyCoun't get it to work in 2005
Posted by TJS on 12/06/2007 03:44pmI just wnat to change the color of a button's text and background window. HBRUSH CTestThingsDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { if(pWnd->GetDlgCtrlID() == IDC_BUTTON1); { // What code do I add here ?? } return (HBRUSH) CreateSolidBrush(RGB(255,0,0)); }ReplyEnabling and disabling CColorButton
Posted by toneymathew on 11/29/2005 01:00pmI use the CColorButton and found that disabling the button using EnableWindow(bool) doesnt actually disable the window but only changes the color of the button (to the disable color I specified at creation). Any clues?
ReplyCouldnt get it working in my app
Posted by toneymathew on 09/12/2005 12:22pmI was relieved to find this on codeguru and actually ran the demo, it worked just fine. I did the exact thing as you did, created a text button, made it a CColorButton and then tried changing the color in initDialog, it goes through the over-ridden SetColor function but never calls the OnDraw in the CColorObject. So, I dont see the color change in my app. I also created a sample dialog app, to make sure I didnt fiddle with any settings and mess it up. No difference, please help
-
Reply
ReplyI'm facing the same Problem, Can You please help!
Posted by Hyd on 11/05/2008 05:19pmHow you have added the skin
Posted by baji_ou on 05/23/2005 08:16amHi, thanks for your nice article, the image of the application in the article is looking very nice, how you have added the skin to the application. I want my application should use some skin. Please suggest me how can I add skin & how to use the skin controls. Have you used any activex control for it, if so please suggest me the way, how can I add skin, I have tested one activex control in vb called vbskinner, now in vc++ how to access that. Please suggest me.
-
-
-
-
-
-
-
Replyre: skin
Posted by baji_ou on 05/23/2005 03:40pmThank you Marius, but do you have any idea, how we can add some skin to an application , I just want to change the look of my application. I am sorry for wasting your precious time :), infact I am searching for the same around.
Replyre: skin
Posted by baji_ou on 05/23/2005 03:27pmThank you Marius, but do you have any idea, how we can add some skin to an application , I just want to change the look of my application. I am sorry for wasting your precious time :), infact I am searching for the same around.
Replyre: re: skin
Posted by cilu on 05/23/2005 03:25pmThis is rather a forum question (you should ask it in the forum). Here is a link for you http://www.appspeed.com/.
Replyre: skin
Posted by baji_ou on 05/23/2005 03:10pmThank you Marius, but do you have any idea, how we can add some skin to an application , I just want to change the look of my application. I am sorry for wasting your precious time :), infact I am searching for the same around.
Replyre: skin
Posted by cilu on 05/23/2005 02:03pmNo. Sorry, no skin what so ever. I just put the controls on the dialog and aranged them.
Replyregarding skin
Posted by baji_ou on 05/23/2005 12:36pmHi, thanks for your reply! but, the image of the application you have given in the article I thought you have used some skin or some control to produce the final output. I want to give the similar kind of a look to my application. Can you please help me.
Replyskin?
Posted by cilu on 05/23/2005 08:21amWhat skin are you talking about? I use no activeX or dlls for skinning the demo project. The button is a custom owner draw control. For other controls you can handle WM_CTLCOLOR if you want to change to colors. Check MSDN for more.
ReplySorry for my question and thank your answer
Posted by xiayingang on 05/16/2005 02:09ami'm sorry for yesterday's question ,yesterday i only see your .exe ,today i see your source ,i found it is easey to change the size use you resource ,but i think if you packge it to your ColorButton class is a good idea
-
Replyanswer
Posted by cilu on 05/16/2005 02:59amThere's no problem with your question. However, as I said, since changing the font is not a button specific operation, but is done the same way for all controls, I would like to keep it as it is, by inheriting CWnd's SetFont() behaviour and not providing anything specific to this custom control.
Replyanther question ???------>hwo to change the size of the text on button
Posted by xiayingang on 05/15/2005 05:26amI'm glad to see your ColorButton Class ,but i think she is not a perfect Button Class ,if you enhance the ColorButton Class and make it have the function of change the text size on the button,then three will have a lot of people to respect you .
-
-
ReplySorry for my question
Posted by xiayingang on 05/16/2005 12:58ami'm sorry for yesterday's question ,yesterday i only see your .exe ,today i see your source ,i found it is easey to change the size use you resource ,but i think if you packge it to your ColorButton class is a good idea
Replyhow to change the font
Posted by cilu on 05/15/2005 05:46amThat functionality is not button specific. See this link for changing the font for a control: http://www.codeguru.com/forum/showthread.php?t=321408
ReplyA Small Question
Posted by mfc_oracle on 11/11/2004 04:04amVery nice and useful classes thanks a lot! However, could I know how I can remove the dynamically created button without closing the dialog?
-
Replyremove the dinamically created button
Posted by cilu on 11/12/2004 05:45amJust as you remove any dynamically created control. If you just want to hide it (for the button in my demo): [code] m_dynamic->ShowWindow(SW_HIDE); [/code] If you want to destroy it: [code] m_dynamic->DestroyWindow(); // must be called first delete m_dynamic; m_dynamic = NULL; [/code] In the case of my demo CColoredButtonDlg::DestroyWindow()should be modified to test if m_dynamic is NULL before calling DestroyWindow() to avoid an invalid call. [code] BOOL CColoredButtonDlg::DestroyWindow() { fontVerdana->DeleteObject(); delete fontVerdana; fontGeorgia->DeleteObject(); delete fontGeorgia; if(m_dynamic != NULL) { m_dynamic->DestroyWindow(); delete m_dynamic; m_dynamic = NULL; } return CDialog::DestroyWindow(); } [/code]Reply