论坛交流
首页办公自动化| 网页制作| 平面设计| 动画制作| 数据库开发| 程序设计| 全部视频教程
应用视频: Windows | Word2007 | Excel2007 | PowerPoint2007 | Dreamweaver 8 | Fireworks 8 | Flash 8 | Photoshop cs | CorelDraw 12
编程视频: C语言视频教程 | HTML | Div+Css布局 | Javascript | Access数据库 | Asp | Sql Server数据库Asp.net  | Flash AS
当前位置 > 文字教程 > C语言程序设计教程
Tag:新手,函数,指针,数据类型,对象,Turbo,入门,运算符,数组,结构,二级,,tc,游戏,试题,问答,编译,视频教程

制作风格独特的按钮—用VC6扩展CButton类

文章类别:C语言程序设计 | 发表日期:2010-12-28 9:19:22

一、 本文介绍一个CButton的派生类CLinkButton,用此派生类制作的按钮具有以下特点: 

1、按钮的外观类似静态控件类CStatic 产生的对象。(参见图一) 

217775__image001.gif(图一) 

2、当鼠标的光标移到按钮上,但并未按下时,光标改变形状,字体改变形状;按钮类似应用在工具条和菜单上的扁平钮效果。(参见图二) 

217775__image003.gif(图二) 

3、当按钮按下的情形:(参见图三) 

217775__image005.gif(图三) 

二、下面具体描述这种按钮的实现方法和步骤: 

1. 在VC6的IDE环境中,生成一个基于对话框的PROJECT。 

2. 将对话框资源中按钮的属性页打开,在“Style”标签页中选取按钮的“Owner Draw”(自绘)属性。 

3. 将光标引入到应用程序的资源中。 

4. 利用CLASSWIZARD,用CButton为基类,派生一个新类:CLinkButton。 

5. 在派生类中重载基类CButton的虚函数: 

virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 

之所以要重载这个函数是因为选择了按钮的 “Owner Draw”属性后,当按钮的可视行为发生变化时,应用程序的框架要调用这个函数来重新绘制按钮。 

6. 定制以下的消息处理: 

afx_msg void OnMouseMove(UINT nFlags, CPoint point); 

afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); 

afx_msg void OnTimer(UINT nIDEvent); 

afx_msg void OnLButtonUp(UINT nFlags, CPoint point); 

afx_msg void OnLButtonDown(UINT nFlags, CPoint point); 

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); 

afx_msg BOOL OnEraseBkgnd(CDC* pDC); 

7. 声明类成员变量定义: 

//定义字体变量 

CFont fUnderline; 

//定义光标变量 

HCURSOR hHand; 

//决定按钮是否按下 

bool bLBtnDown; 

//决定鼠标是否在按钮上 

bool bHighlight; 

二、 派生类CLinkButton 的具体实现: 

1.重载函数  DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)。 

void CLinkButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 

{ 

// 获取一个CDC指针 

CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); 

//定义按钮区域并初始化 

CRect rect(lpDrawItemStruct->rcItem); 

//设置背景模式 

COLORREF oc = pDC->GetTextColor(); 

int iObk = pDC->SetBkMode(TRANSPARENT); 

//初始化按钮状态 

UINT state = lpDrawItemStruct->itemState; 

CFont * pOldFont = NULL; 

int iYOffset = 0, iXOffset = 0; 

CString strText; 

GetWindowText(strText); 

rect.top += iYOffset; 

rect.left += iXOffset; 

if (state & ODS_DISABLED) 

{ 

//按钮置灰状态(DISABLED) 

CBrush grayBrush; 

grayBrush.CreateSolidBrush (GetSysColor (COLOR_GRAYTEXT)); 

CSize sz = pDC->GetTextExtent(strText); 

int x = rect.left + (rect.Width() - sz.cx)/2; 

int y = rect.top + (rect.Height() - sz.cy)/2; 

rect.top += 2; 

rect.left += 2; 

pDC->SetTextColor(GetSysColor(COLOR_3DHIGHLIGHT)); 

pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); 

rect.top -= 2; 

rect.left -= 2; 

pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT)); 

pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); 

} 

else 

{ 

if (bHighlight)//光标在按钮上 

{ 

if (state & ODS_SELECTED) 

{ 

//按下按钮 

pDC->Draw3dRect(rect,GetSysColor(COLOR_3DSHADOW), 

                GetSysColor(COLOR_3DHILIGHT)); 

} 

else 

{//未按下按钮 

           pDC->Draw3dRect(rect,GetSysColor(COLOR_3DHILIGHT), 

                GetSysColor(COLOR_3DSHADOW)); 

} 

//字体颜色 

pDC->SetTextColor(RGB(0,0,255)); 



//加下画线(也可以用其他字体) 

if (fUnderline.GetSafeHandle() == NULL) 

{ 

CFont * pFont = GetFont(); 

ASSERT(pFont); 

LOGFONT lf; 

pFont->GetLogFont(&lf); 

lf.lfUnderline = TRUE; 

fUnderline.CreateFontIndirect(&lf); 

} 

pOldFont = pDC->SelectObject(&fUnderline); 

} 

else pDC->SetTextColor(GetSysColor(COLOR_BTNTEXT)); 

pDC->DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); 

if (pOldFont) pDC->SelectObject(pOldFont); 

} 

} 

2.定制的消息处理函数 

void OnMouseMove(UINT nFlags, CPoint point) 

{ 

//设置一个定时器 

SetTimer(1,10,NULL); 

// 

... 

} 

当鼠标光标移到按钮上时,执行此函数,定时器将发送一个 WM_TIMER消息到消息队列。 

由OnTimer(UINT nIDEvent)函数处理这个消息。 

void OnTimer(UINT nIDEvent) 

{ 

//处理WM_TIMER消息 

static bool pPainted = false; 

POINT pt; 

GetCursorPos(&pt); 

CRect rect; 

GetWindowRect (rect); 

if (bLBtnDown) 

{ 

KillTimer (1); 

if (pPainted) InvalidateRect (NULL); 

pPainted = FALSE; 

return; 

} 

if (!rect.PtInRect (pt)) 

{ 

bHighlight = false; 

KillTimer (1); 

if (pPainted) 

InvalidateRect(NULL); 

pPainted = false; 

return; 

} 

else 

{ 

bHighlight = true; 

if (!pPainted) 

{ 

pPainted = true; 

InvalidateRect(NULL); 

} 

} 

// 

CButton::OnTimer(nIDEvent); 

} 

BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 

{ 

//当鼠标光标移到按钮上时,改变光标的形象 

if (bHighlight) 

{ 

::SetCursor(hHand); 

return true; 

} 

// 

... 

} 

int OnCreate(LPCREATESTRUCT lpCreateStruct) 

{ 

... 

CFont * pFont = GetFont(); 

ASSERT(pFont); 

LOGFONT lf; 

pFont->GetLogFont(&lf); 

lf.lfUnderline = TRUE; 

fUnderline.CreateFontIndirect(&lf); 

... 

} 

这个函数由框架在显示出按钮之前自动调用,我在这里初始化在按钮上显示的字体。 

void OnLButtonUp(UINT nFlags, CPoint point) 

{ 

bLBtnDown = false; 

if (bHighlight) 

{ 

bHighlight = false; 

InvalidateRect(NULL); 

} 

... 

} 

当按下按钮又放开时调用这个函数。 

void OnLButtonDown(UINT nFlags, CPoint point) 

{ 

bLBtnDown = true; 

... 

} 

当按下按钮时调用这个函数。 

BOOL OnEraseBkgnd(CDC* pDC) 

{ 

COLORREF cr = GetSysColor(COLOR_3DFACE); 

int r = GetRValue(cr); 

int g = GetGValue(cr); 

int b = GetBValue(cr); 

if (r > 1) r -= 2; 

if (g > 1) g -= 2; 

if (r < 3 && g < 3 && b < 253) b += 2; 

COLORREF cr1 = RGB(r,g,b); 

CRect rc; 

GetClientRect(rc); 

pDC->FillSolidRect(rc, cr1); 

... 

} 

当按钮的背景需要重画时,应用程序框架调用此函数。编译并运行PROJECT LinkBtn, 效果与本文的图一、图二、图三一样。

视频教程列表
文章教程搜索
 
C语言程序设计推荐教程
C语言程序设计热门教程
看全部视频教程
购买方式/价格
购买视频教程: 咨询客服
tel:15972130058