关于自绘Button的问题,请教大家,欢迎讨论

Dr.Yao 2009-07-13 10:14:59
关于自绘Button的问题。

我使用的WTL,我想自己写一个XP风格的按钮类
在参考了有限的资料之后,我大致这样做的:

继承CWindowImpl,CMouseHover,COffscreenDraw
了解WTL的朋友应该知道,我就不废话了
其中CMouseHover 处理一些鼠标消息
COffscreenDraw则是响应WM_PAINT,WM_PRINTCLINET以及WM_ERASEBKGND消息,派生类只要重写它提供的DoPaint就可以进行重绘
这两个类来自atlgdix.h,百度有.

template<class T,class TBase = CButton,class TWinTraits = CControlWinTraits>
class ATL_NO_VTABLE CButtonXPImpl:
public CWindowImpl<T,TBase,TWinTraits>,
public CMouseHover<T>,
public COffscreenDraw<T>
{
public:
DECLARE_WND_SUPERCLASS(NULL,TBase::GetWndClassName())

BEGIN_MSG_MAP(CButtonXPImpl)
CHAIN_MSG_MAP( COffscreenDraw<T> )
MESSAGE_HANDLER(WM_CREATE,OnCreate);
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnRefresh)
MESSAGE_HANDLER(WM_KILLFOCUS, OnRefresh)
MESSAGE_HANDLER(WM_SETFOCUS, OnRefresh)
MESSAGE_HANDLER(WM_ENABLE, OnRefresh)
MESSAGE_HANDLER(BM_CLICK, OnStateChange)
MESSAGE_HANDLER(BM_SETSTYLE, OnStateChange)
MESSAGE_HANDLER(BM_SETSTATE, OnStateChange)
MESSAGE_HANDLER(WM_UPDATEUISTATE,OnRefresh)
MESSAGE_HANDLER(WM_SETTEXT,OnRefresh)
CHAIN_MSG_MAP( CMouseHover< T > )
DEFAULT_REFLECTION_HANDLER()
ALT_MSG_MAP(1)
END_MSG_MAP()

//.......
//.....

void DoPaint(CDCHandle dc)
{
//重载COffscreenDraw的DoPaint,一顿乱画..
}

//OnRefresh,OnStateChange这些函数就是Invalidate一下
}



代码很乱但是很简单,主要是试来试去弄的乱七八糟我就先不全贴出来了

意思就是,我通过响应WM_PAINT重绘按钮
并且在其他一些涉及到状态改变的消息的时候刷新按钮
画出来的按钮没问题,问题在于,在我按下按钮的时候,会瞬间闪现出原始按钮的画面
就是说系统还是在按下按钮的时候重画了按钮,虽然很快又被我画回去
但是闪来闪去,一个是我内心纠结,再一个我想知道:
在不用OwnerDraw(也就是在OnDrawItem),而在WM_PAINT重绘按钮,如果做到全面接管?
因为看样子系统的确在按钮状态改变的时候画出了按下的按钮

另外:我知道在WM_DRAWITEM消息的时候重绘是可以的,或者就我现在的代码,给按钮加上OwnerDraw的style也可以避免我所说的问题。我的意思不是要解决这个问题,而是想弄明白...

抱歉语言组织的乱七八糟,跟我的代码风格一样

分不够我会加的,重在讨论...
...全文
150 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
biweilun 2009-07-13
  • 打赏
  • 举报
回复
能抓到老鼠的就是好猫
Dr.Yao 2009-07-13
  • 打赏
  • 举报
回复
恩,谢谢楼上的各位。
看来还是响应WM_DRAWITEM方便一些
我也不继续纠结了,做出来就行,哈哈
ringphone 2009-07-13
  • 打赏
  • 举报
回复
OnLButtonDown是不是返回了基类的OnLButtonDown?很有可能是基类在这个事件里进行了绘制,因此按下按钮的时候,会瞬间闪现出原始按钮的画面。用API子类化进行处理没这个问题。
Ryanwen 2009-07-13
  • 打赏
  • 举报
回复
你的问题是因为你没有重绘按钮被按下时的样子

自绘按钮一般会重绘四种状态,这些状态可以通过DRAWITEMSTRUCT结构的itemState得到,但是这个结构没有提供别的接口,只能通过WM_DRAWITEM消息得到,所以最好的方法就是在响应WM_DRAWITEM了
button state owner_draw state
Normal Normal
Pressed Pressed
Input focus -------
Default Default
Unavailable Unavailable


Dr.Yao 2009-07-13
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 spring203 的回复:]
楼主既然是用WTL,不知道WTL有一个CBitmapButton?在atlctrlx.h上面呀,如果觉得它不够用,继承它好了, 省得写这么多代码!
[/Quote]

我看了CBitmapButton,并不是我要的效果
不过很有参考性,关键在于

// We need this style to prevent Windows from painting the button
ModifyStyle(0, BS_OWNERDRAW);



我是在想,如果不要求BS_OWNERDRAW的情况下,如何做到完全重绘

有办法的朋友请不吝赐教
实在不行那也就这么着了
Dr.Yao 2009-07-13
  • 打赏
  • 举报
回复
谢谢楼上提醒,我先试试再说
spring203 2009-07-13
  • 打赏
  • 举报
回复
楼主既然是用WTL,不知道WTL有一个CBitmapButton?在atlctrlx.h上面呀,如果觉得它不够用,继承它好了, 省得写这么多代码!
Dr.Yao 2009-07-13
  • 打赏
  • 举报
回复
谢谢楼上的好心人。
但是我的问题并不是这个造成的,COffscreenDraw 的功能基本上就是实现了你给的资料里的方法
fengrx 2009-07-13
  • 打赏
  • 举报
回复
给楼主点资料吧:

VC防止窗口和控件闪烁的方法

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧