分享
 
 
 

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

王朝c/c++·作者佚名  2006-01-06
窄屏简体版  字體: |||超大  

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

1、按钮的外观类似静态控件类CStatic 产生的对象。

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

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

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

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

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

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

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

virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)

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

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有