Introduction
This article is about customizing the Windows standard slider control through Custom Drawing fuctionalities provided by Windows itself. Although, here a Adobe photoshop style slider control is drawn, but it is upto the user to follow the guideline and come up with a nice slider control with custom looks.
Background
In one of my projects I was asked to provide a control which looks like the adobe section cut control, but have all the APIs and features of a slider. Therefore I just handled the NM_CUSTOMDRAW Reflection message of the slider and came up with this nice looking (though i do say so myself) slider.
Using the code
Place a slider control in your Dialog from resource, add a member variable for the slider through the MFC Wizard and change the classname to CAdobeSliderCtrl
so that it would look similar to this in your header file of the parent dialog.
CAdobeSliderCtrl m_adobeSliderCtrl;
Guess what, you are finished. Now your slider should look like the one you see in the image on top.
Points of Interest
void CCustomDrawSliderCtrl::OnCustomDraw ( NMHDR* pNMHDR, LRESULT* pResult)
{
NMCUSTOMDRAW nmcd = *(LPNMCUSTOMDRAW) pNMHDR;
UINT drawStage = nmcd.dwDrawStage;
UINT itemSpec = (UINT)nmcd.dwItemSpec;
switch ( drawStage )
{
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT ;
break;
case CDDS_PREERASE: case CDDS_POSTERASE: case CDDS_ITEMPREERASE: case CDDS_ITEMPOSTERASE: *pResult = CDRF_DODEFAULT;
break;
case CDDS_ITEMPREPAINT:
switch (itemSpec)
{
case TBCD_CHANNEL:
*pResult = CDRF_SKIPDEFAULT;
break;
case TBCD_TICS:
*pResult = CDRF_DODEFAULT;
break;
case TBCD_THUMB:
{
CDC* pDC = CDC::FromHandle( nmcd.hdc );
Draw(pDC, &nmcd);
*pResult = CDRF_SKIPDEFAULT;
}
break;
}
break;
case CDDS_ITEMPOSTPAINT: switch ( itemSpec )
{
case TBCD_TICS:
*pResult = CDRF_DODEFAULT;
break;
case TBCD_THUMB:
*pResult = CDRF_DODEFAULT;
break;
}
break;
}
}
I would like to attract the reader's attention to the code pasted above.
See how the the item prepaints and post paints are handled and the place where Draw is invoked. This is not standard coding when it comes to the slider, but this is a trick to easily achieve any type of drawing overriding for the slider.
And to address the nonstandard invokation of drawing of the whole slider control from inside drawing the thumb, the Draw function has a minor hack as you can see below nicely pointed out in the code comments:
void CCustomDrawSliderCtrl::Draw(CDC *pDC, LPNMCUSTOMDRAW lpcd)
{
CRect rc;
GetWindowRect(rc);
GetClientRect(rc);
OnDraw(pDC, rc);
CClientDC dc(this);
OnDraw(&dc, rc);
}
I hope you can guess that the CCustomDrawSliderCtrl
gives a base for complete owner drawing of the slider control which should be done by the derived controls in the OnDraw overridable method like it is done in the CAdobeSliderCtrl
(inherited of-course from CCustomDrawSliderCtrl
).
So, the purpose of this article is to provide a base for drawing the slider at your will. Of-course, apart from very few specific cases I personally wouldn't advise to change too much the drawing of the standard windows control unless absolutely required.
History
Article posted: 3rd January, 2012 (How about that.. begining the new year with an article :) !!)