MFC控件完全重绘从CWnd开始
来源:互联网 发布:手机股票预警软件 编辑:程序博客网 时间:2024/04/28 06:40
导读:
我并不推荐采用自绘的方式去完成一些控件(比如CStatic,CButton,RadioBox,CheckBox等)的美化,而是推荐大家从CWnd入手,把这些基本控件完全重新绘制一遍(当然,有些做的很好的控件还是需要继承来自绘的,比如CListCtrl)。为什么这么做?因为MFC对这些控件的某些操作是隐蔽的,某些限制是我们无法接受的(比如CTabCtrl的头部高度和每个Item的宽度)。我觉得掌握如下知识,绘制其他基本控件就不是绘制的问题,而是数据结构的事情了。
头文件:
#ifndef QCTRL_H#define QCTRL_H#include <afxwin.h>class QMemDC :// 我把双缓存封装到类中,这样就方便多了public CDC{private:CDC* dcSrc;CRect rect;CBitmap bmp;public:QMemDC(CDC* dc,CRect rc);void Apply();};class QCtrl :public CWnd{protected:CString szClassName;bool isMouseIn;bool isPressed;public:QCtrl();~QCtrl();bool Create(CWnd* pParent,CRect rc,CString text,DWORD id = 0,DWORD style = WS_VISIBLE|WS_CHILD);protected:void PostClickEvent();protected:afx_msg void OnMouseMove(UINT nFlags, CPoint point);afx_msg void OnMouseHover(UINT nFlags, CPoint point);afx_msg void OnMouseLeave();afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnLButtonUp(UINT nFlags, CPoint point);afx_msg BOOL OnEraseBkgnd(CDC* pDC);afx_msg void OnPaint();public:DECLARE_MESSAGE_MAP()};#endif
我们需要的基本上就是这几个消息了。
实现文件:
#include "QCtrl.h"// QMemDCQMemDC::QMemDC(CDC* dc,CRect rc){dcSrc = dc;rect = rc;// 创建内存DCCreateCompatibleDC(dc);bmp.CreateCompatibleBitmap(dc,rc.Width(),rc.Height());SelectObject(bmp);}void QMemDC::Apply(){// 将内存DC绘制到设备DC上dcSrc->BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),this,0,0,SRCCOPY);}// QCtrlQCtrl::QCtrl(){isMouseIn = false;isPressed = false;// 注册控件类szClassName = AfxRegisterWndClass(0);}QCtrl::~QCtrl(){}bool QCtrl::Create(CWnd* pParent,CRect rc,CString text,DWORD id /* = 0 */,DWORD style /* = WS_VISIBLE|WS_CHILD */){// 动态创建控件BOOL ret = CWnd::CreateEx(0,szClassName,text,style,rc,pParent,id);return ret ? true : false;}void QCtrl::PostClickEvent(){// 该函数用来向父窗口发送 单击 消息CWnd* parent = GetParent();if(parent != NULL){WPARAM wp = MAKEWPARAM(GetDlgCtrlID(),BN_CLICKED);LPARAM lp = (LPARAM) m_hWnd;parent->PostMessage(WM_COMMAND,wp,lp);}}BEGIN_MESSAGE_MAP(QCtrl, CWnd)ON_WM_MOUSEMOVE()ON_WM_MOUSEHOVER()// 此消息系统并不会给我们发送ON_WM_MOUSELEAVE()ON_WM_LBUTTONDOWN()ON_WM_LBUTTONUP()ON_WM_PAINT()ON_WM_ERASEBKGND()END_MESSAGE_MAP()// 鼠标进入和鼠标移出消息需要我们自己监听void QCtrl::OnMouseMove(UINT nFlags, CPoint point){// 只处理鼠标第一次进入时的情况if(!isMouseIn){isMouseIn = true;TRACKMOUSEEVENT evt = { sizeof(evt), TME_LEAVE, m_hWnd, 0 };TrackMouseEvent(&evt);OnMouseHover(0,CPoint());}}void QCtrl::OnMouseHover(UINT nFlags, CPoint point){// 鼠标进入Invalidate();}void QCtrl::OnMouseLeave(){// 鼠标离开isMouseIn = false;isPressed = false;Invalidate();}void QCtrl::OnLButtonDown(UINT nFlags, CPoint point){// 鼠标按下isPressed = true;Invalidate();}void QCtrl::OnLButtonUp(UINT nFlags, CPoint point){// 鼠标松开if(isPressed){isPressed = false;Invalidate();PostClickEvent();}}BOOL QCtrl::OnEraseBkgnd(CDC* pDC){return TRUE;// 阻止擦除背景,防止闪烁}void QCtrl::OnPaint(){CPaintDC dc(this); CRect rc;GetClientRect(&rc);// 采用双缓存,防止闪烁QMemDC mdc(&dc,rc);// 刷背景COLORREF bkgnd = RGB(100,0,0);if(isMouseIn){if(isPressed)bkgnd = RGB(250,0,0);elsebkgnd = RGB(180,0,0);}mdc.FillSolidRect(&rc,bkgnd);// 设置文字字体CFont font;font.CreatePointFont(110,"宋体");// 11号字体,该参数与实际字体号有10倍的关系mdc.SelectObject(font);// 获取文字CString text;GetWindowText(text);// 设置文字属性mdc.SetBkMode(TRANSPARENT);mdc.SetTextColor(RGB(0,0,0));// 绘制文本DWORD style = DT_SINGLELINE | DT_VCENTER | DT_CENTER;// 文本格式:单行+水平居中+垂直居中mdc.DrawText(text,-1,&rc,style);// 更多文本显示格式可参考百度百科DrawText说明// 使绘制生效mdc.Apply();}
如果上升到界面库设计的高度,这里的OnPaint函数应该这么写:
为QCtrl添加一个虚函数virtual void DoPaint(QMemDC &dc,CRect rc);
CPaintDC dc(this);
CRect rc;
GetClientRect(&rc);// 采用双缓存,防止闪烁
QMemDC mdc(&dc,rc);
DoPaint(mdc,rc);
如此,子类继承QCtrl只需要重写该函数即可。
由于我们不是子类化,所以只能动态创建:
在CXXDlg.h添加变量QCtrl ctrl;
在OnInitDialog中ctrl.Create(this,CRect(10,10,210,30),"Nice Work"); //此处id和style是缺省参数,当我们指定一个ID后,就可以在CXXDlg的消息映射ON_BK_CLICKED函数中接收到该控件的单击事件了。
- MFC控件完全重绘从CWnd开始
- MFC控件完全重绘从CWnd开始
- MFC控件完全重绘从CWnd开始
- MFC——自绘控件(从CWND派生的edit控件)
- MFC控件重绘
- MFC Edit控件 error:“DDX_Control”: 不能将参数 3 从“int”转换为“CWnd &”
- MFC Edit控件 error:“DDX_Control”: 不能将参数 3 从“int”转换为“CWnd &”
- MFC控件背景重绘
- MFC 控件重绘(1)
- MFC:重绘GroupBox控件
- CWND子窗口重绘
- 使用mfc CWnd 自绘实现一个类似于QQ好友的一个控件
- MFC重绘控件篇---按钮CButton
- MFC重绘控件篇---按钮CEdit
- MFC重绘控件篇---按钮CCombox
- MFC重绘控件篇---按钮CListBox
- MFC 清除重绘picture 控件
- MFC重绘的按钮控件
- PHP中的回调
- 共享内存和信号量的使用
- 游标
- Android之-中国天气网城市id数据
- Python正则表达式指南
- MFC控件完全重绘从CWnd开始
- 信息检索和网络数据挖掘领域论文技术基础
- java反射详解
- CAD二次开发 -可恶的版本问题
- error LNK2005: _DllMain@12 already defined in MSVC 2009-10-29 17:49
- Nova-Router分析
- JAVA操作Execl时生成的XML文件的编码问题
- Boost库的安装使用(Ubuntu)
- android 物理按键