我来说下自画按钮的背景色刷新问题
前段时间问过, 今天解决了, 所以贴上来跟大家共享一下.
zz from my blog
http://www.blogbus.com/public/tb.php/2570931
--------------------------------
2006-05-30
自画按钮的背景色刷新问题
TAG:我爱编程_WinCE
给button设置了BS_OWNERDRAW之后就可以在DrawItem()函数里面做自定义绘制了. 不过button的一些特性还是比较奇怪, 例如说在MoveWindow(), 或者失去焦点需要重绘的时候, button还是会先用默认的button背景色刷新一道背景, 而对于一般的图片显示来说, 都是把背景色刷成白色或者黑色的, 而WinCE上的默认button背景色却是浅色(跟当前theme有关, 例如默认theme下为浅蓝色). 这样做刷新的时候闪烁多少有些难看. 解决办法在无意间找到的, 嗯.
简单的思路是, 首先需要重载OnCtlColor()函数以处理WM_CTLCOLOR消息, 之后根据pWnd信息判断是否是需要处理的button, 若是则返回希望使用的brush即可. 示范代码如下:
HBRUSH CPlayMMDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
if (pWnd->GetSafeHwnd() == _image_info.GetSafeHwnd())
{
hbr = (HBRUSH)(::GetStockObject(NULL_BRUSH));
}
// TODO: Return a different brush if the default is not desired
return hbr;
}
示例中用的NULL_BRUSH也即不刷新背景, 可以进一步减少闪烁. 不过带来的问题是, 如果button的显示区域中有未处理绘制的区域, 则那一块区域就不会被刷新. 这个也是今天遇到的问题, 从IImage读取到的一个具有透明背景的gif, 背景就没有被更新. 这个时候就只好先刷一遍背景了(其实这里设为WHITE_BRUSH倒也可以的, 不过button中设定的空白区域背景色是COLOR_WINDOW, 也不能保证这个就一定是白色啊, 还是用NULL_BRUSH+FillRect()的办法了). 在其他情况下这个办法倒是工作得还不错哈.
顺带说一句, 这个办法对没有BS_OWNERDRAW的button似乎不管用, MSDN上看到的解释(WM_CTLCOLORBTN): Buttons with the BS_PUSHBUTTON, BS_DEFPUSHBUTTON, or BS_PUSHLIKE styles do not use the returned brush. Buttons with these styles are always drawn with the default system colors. 懒得去求证了, 嗯.