MFC自绘-WzdButton按钮类
来源:互联网 发布:淘宝网首页不显示图片 编辑:程序博客网 时间:2024/06/08 12:22
这次来说说在窗口类里用到的按钮类的设计。
还是先看头文件:
#include "WzdImage.h"class CWzdButton : public CButton{ DECLARE_DYNAMIC(CWzdButton)protected: bool m_bExpand; // 能否拉伸 bool m_isHovering; // 是否悬停 COLORREF m_crTextColor; // 字体颜色 CWzdImage m_imageButton; // 按钮图片public: CWzdButton(); virtual ~CWzdButton(); // 加载位图 bool SetButtonImage(LPCTSTR pszFileName, bool bExpandImage = false); bool SetButtonImage(HINSTANCE hInstance, LPCTSTR pszResourceName, bool bExpandImage = false); bool SetTextColor(COLORREF crTextColor); // 设置字体颜色 bool FixButtonSize(); // 调整按钮大小protected: virtual void PreSubclassWindow(); // 子类化 virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); // 界面绘画函数 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg LRESULT OnMouseLeave(WPARAM wparam, LPARAM lparam); afx_msg BOOL OnEraseBkgnd(CDC* pDC); DECLARE_MESSAGE_MAP()};
同样需要加载图片,因此包含WzdImage.h。
m_bExpand控制按钮图片能否根据按钮大小拉伸,m_bHovering标记鼠标是否悬停。
接着先看看构造函数,默认不拉伸、没有悬停、字体颜色为黑色。
CWzdButton::CWzdButton(): m_bExpand(false), m_isHovering(false), m_crTextColor(RGB(0,0,0)){}
同样有两种加载图片的方式,资源加载和路径加载,还有设置字体颜色的接口。
bool CWzdButton::SetButtonImage(LPCTSTR pszFileName, bool bExpandImage/*=false*/){ if (NULL == pszFileName) return false; // 加载位图 m_bExpand = bExpandImage; if (!m_imageButton.IsNull()) { m_imageButton.DestroyImage(); } m_imageButton.LoadImage(pszFileName); if (!m_bExpand) FixButtonSize(); // 调整按钮大小 if (GetSafeHwnd()) Invalidate(FALSE); return true;}bool CWzdButton::SetButtonImage(HINSTANCE hInstance,LPCTSTR pszResourceName, bool bExpandImage/*=false*/){ if (NULL == pszResourceName) return false; // 加载位图 m_bExpand = bExpandImage; if (!m_imageButton.IsNull()) { m_imageButton.DestroyImage(); } m_imageButton.LoadImage(hInstance,pszResourceName); if (!m_bExpand) FixButtonSize(); // 调整按钮大小 if (GetSafeHwnd()) Invalidate(FALSE); return true;}bool CWzdButton::SetTextColor(COLORREF crTextColor){ m_crTextColor = crTextColor; if (GetSafeHwnd()) Invalidate(FALSE); return true;}
FixButtonSize(),用于在按钮不拉伸时,改变按钮的大小。为什么按钮背景图宽度要除去4呢?默认采用的图片都是4种按钮背景(正常、悬停、点击、无效)水平排列,所以按钮大小就是图片大小的四分之一。
bool CWzdButton::FixButtonSize(){ if (!m_imageButton.IsNull() && GetSafeHwnd()) { SetWindowPos(NULL, 0, 0, m_imageButton.GetWidth() / 4, m_imageButton.GetHeight(), SWP_NOMOVE); return true; } return false;}
可以看到有PreSubclassWindow(),它是在按钮不是动态创建的时候,在创建之前会调用到这个函数。在这里只改变风格,让按钮支持自绘。
void CWzdButton::PreSubclassWindow(){ SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW); CButton::PreSubclassWindow();}
那动态创建的时候自然就是在OnCreate()里改变风格。
int CWzdButton::OnCreate(LPCREATESTRUCT lpCreateStruct){ if (-1 == CButton::OnCreate(lpCreateStruct)) return -1; SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW); return 0;}
最关键的就是重写DrawItem()绘制按钮。先绘制背景,因为在WzdDialog窗口中设置了WS_CLIPCHILDREN 属性,窗口不对子控件背景进行重绘。而这里使用的是PNG透明图片,不自绘背景会是默认画刷的颜色,而我们需要窗口的背景色(只支持单色背景)。接着是根据按钮状态绘画不同的图像,最后绘画文字。
void CWzdButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){ CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CRect rcClient; GetClientRect(rcClient); //CRect ParRect; //GetWindowRect(&ParRect); //GetParent()->ScreenToClient(&ParRect); // 获取父窗口的背景,自己绘制背景,防止窗口背景重绘时的闪烁 CDC* BkDc= GetParent()->GetDC(); pDC->BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), BkDc, 0, 0, SRCCOPY); bool bDisable = !!((lpDrawItemStruct->itemState & ODS_DISABLED)); bool bButtonDown = !!((lpDrawItemStruct->itemState & ODS_SELECTED)); if (!m_imageButton.IsNull()) { // 计算位图位置 int nWidth = m_imageButton.GetWidth() / 4; int nDrawPos = 0; if (bDisable) nDrawPos = nWidth * 3; else if (bButtonDown) nDrawPos = nWidth * 2; else if (m_isHovering) nDrawPos = nWidth * 1; // 绘画按钮 if (!m_bExpand) m_imageButton.DrawImage(pDC , 0, 0, rcClient.Width(), rcClient.Height(), nDrawPos, 0); else m_imageButton.DrawImage(pDC, 0, 0, rcClient.Width(), rcClient.Height(), nDrawPos, 0, nWidth, m_imageButton.GetHeight()); } // 绘画字体 CString strText; GetWindowText(strText); rcClient.top+=1; pDC->SetBkMode(TRANSPARENT); if (bDisable) pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT)); else pDC->SetTextColor(m_crTextColor); pDC->DrawText(strText, strText.GetLength(), rcClient, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);}
响应鼠标移动,重载OnMouseMove。m_isHovering是鼠标悬停在按钮上,TrackMouseEvent那段代码是因为MouseLeave的消息发送存在问题,需要自己来触发MouseLeave消息,实现鼠标离开时m_isHovering状态的改变。
void CWzdButton::OnMouseMove(UINT nFlags, CPoint point){ if (!m_isHovering) { m_isHovering = true; Invalidate(FALSE); // 注册消息 TRACKMOUSEEVENT TrackMouseEvent; TrackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT); TrackMouseEvent.dwFlags = TME_LEAVE; TrackMouseEvent.hwndTrack = GetSafeHwnd(); TrackMouseEvent.dwHoverTime = HOVER_DEFAULT; _TrackMouseEvent(&TrackMouseEvent); } CButton::OnMouseMove(nFlags, point);}void CWzdButton::OnMouseLeave(){ m_isHovering = false; Invalidate(FALSE); CButton::OnMouseLeave();}
0 0
- MFC自绘-WzdButton按钮类
- mfc 按钮自绘
- MFC 按钮的自绘
- MFC-自绘贴图按钮
- MFC 下自绘按钮
- MFC自绘按钮的实现
- MFC下按钮自绘的实现
- MFC按钮自绘消息分析
- MFC 自绘按钮的实现
- MFC的自绘位图按钮
- MFC + CxImage 实现自绘半透明按钮
- MFC按钮 自绘 鼠标滑过
- MFC + CxImage 实现自绘半透明按钮
- MFC自绘按钮的实现
- MFC 自绘按钮的实现
- MFC(4)自绘按钮
- MFC下按钮自绘的实现
- (VC++2013)MFC自绘圆形按钮
- 安卓开发之引入第三方库导致jar包冲突解决办法
- iOS开发--TDD的iOS开发初步以及Kiwi使用入门
- 清除浮动
- 最小表示法--让你速度gank序列
- 第19章 事务
- MFC自绘-WzdButton按钮类
- SPOJ COTCount on a tree(树上路径第k小 主席树)
- HDU 2602:Bone Collector【01背包】
- Word2Vec之Deep Learning in NLP (一)词向量和语言模型
- PHP生成PDF文件
- 帮Facebook把用户做到7亿 他只做了三件事
- Android Studio奇技淫巧一览 大幅度提升工作效率
- Mr. Process的一生-Linux内核的社会视角 (1) 调度
- TextView和EditText的显示