Adobe 风格的滑块控件






4.85/5 (6投票s)
自定义标准滑块控件,
引言
本文介绍如何通过 Windows 自身提供的自定义绘制功能来定制 Windows 标准滑块控件。虽然这里绘制了一个 Adobe Photoshop 风格的滑块控件,但用户可以根据指南创建具有自定义外观的漂亮滑块控件。
背景
在一个项目中,我被要求提供一个外观类似于 Adobe 部分截取控件,但同时具有滑块所有 API 和功能的控件。因此,我处理了滑块的 NM_CUSTOMDRAW 反射消息,并创建了这个外观不错的(虽然我自己这么认为)滑块。
使用代码
从资源中在对话框中放置一个滑块控件,通过 MFC 向导为滑块添加一个成员变量,并将类名更改为 CAdobeSliderCtrl
,以便在父对话框的头文件中看起来像这样。
CAdobeSliderCtrl m_adobeSliderCtrl;
猜猜怎么着,你完成了。现在你的滑块应该看起来像顶部的图像中的那个。
关注点
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: // most important of the drawing stages must return CDRF_NOTIFYITEMDRAW or else we will not get further // NM_CUSTOMDRAW notifications for this drawing cycle we also return CDRF_NOTIFYPOSTPAINT // so that we will get post-paint notifications *pResult = CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT ; break; case CDDS_PREERASE: // Before the erase cycle begins case CDDS_POSTERASE: // After the erase cycle is complete case CDDS_ITEMPREERASE: // Before an item is erased case CDDS_ITEMPOSTERASE: // After an item has been erased *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: // After an item has been drawn switch ( itemSpec ) { case TBCD_TICS: *pResult = CDRF_DODEFAULT; break; case TBCD_THUMB: *pResult = CDRF_DODEFAULT; break; } break; } }
我想引起读者对上面粘贴的代码的注意。
看看如何处理项目预绘和后绘,以及调用 Draw 的位置。这与滑块的标准编码不同,但这是一个轻松实现滑块任何类型绘制覆盖的技巧。
为了解决从拇指内部调用整个滑块控件绘制的非标准问题,Draw 函数有一个小技巧,如下面的代码注释中清晰地指出了。
void CCustomDrawSliderCtrl::Draw(CDC *pDC, LPNMCUSTOMDRAW lpcd) { CRect rc; GetWindowRect(rc); GetClientRect(rc); // The first drawing is to make sure the thumb area is painted properly with the background // and the edges OnDraw(pDC, rc); // The next drawing is to make sure the control is drawn properly covering the whole client area CClientDC dc(this); OnDraw(&dc, rc); }
我希望你能猜到 CCustomDrawSliderCtrl
为滑块控件的完全所有者绘制提供了一个基础,这应该由派生控件在 OnDraw 可重写方法中完成,就像在 CAdobeSliderCtrl
中完成的那样(当然是从 CCustomDrawSliderCtrl
继承而来)。
因此,本文的目的是提供一个根据你的意愿绘制滑块的基础。当然,除了极少数特定情况外,我个人不建议过多更改标准 Windows 控件的绘制,除非绝对必要。
历史
文章发布日期:2012 年 1 月 3 日(怎么样.. 以一篇新文章开始新的一年 :) !!)