打造自己的CButton

[复制链接]
查看1830 | 回复1 | 2006-5-18 00:40:00 | 显示全部楼层 |阅读模式

里面用到了很多常用的技巧

////////////////////////////////////////////////////////////////////////////////
1、单字节字符转化为双字节字符
...
WCHAR str[256];
ZeroMemory( str , 256 );

CString stra;
this->GetWindowText( stra );

int len = sizeof( stra.GetBuffer() );
MultiByteToWideChar( CP_ACP , 0 , (LPCSTR)stra.GetBuffer() , len , str , len );
...
与 MultiByteToWideChar() 对应的,有一个 WideCharToMultiByte()
后者把双字节字符转为单字节GDI+编程中经常用到
char szANSIString[MAX_PATH];
WideCharToMultiByte(
CP_ACP , WC_COMPOSITECHECK ,
wszSomeString , -1 ,
szANSIString , sizeof( szANSIString ) ,
NULL , NULL
);

这里有一个A2W与W2A宏
char temp[] = "how are you";
USES_CONVERSION;
LPWSTR string = A2W( temp );
...
USES_CONVERSION;
szANSIString = W2A( wszSomeString );

参考资料:
《精通GDI+编程》清华大学出版社

////////////////////////////////////////////////////////////////////////////////
2、当鼠标进入按钮区域后,又移动时,检测指针是否移出了该区域

当鼠村进入按钮区域并移动时,会触发 OnMouseMove() 事件
这时你可以用
::SetCapture( this->GetSafeHwnd() );
把鼠标梆定到该按钮
这样在 OnMouseMove() 事件处理函数中,可以检测出指针是否已经离开区域
...
CRect rect;
GetClientRect( rect );
BOOL ptIn = rect.PtInRect( point );
...
if( !ptIn )
{
//哈哈,鼠标已经移出按钮区域啦
//你可以用
::ReleaseCapture();
//释放刚才的梆定
}
具体可以看下面的代码,要结合上下文才能理解噢!

////////////////////////////////////////////////////////////////////////////////

文件:
d1_dynamicBtn.h
d1_dynamicBtn.cpp
定义按钮外形、鼠标移动到上面时色彩的变化。

文件:
userBtn1.h
userBtn1.cpp
继承 class d1_dynamicBtn
里面只需实现 构造函数 及 响应必要的按钮行为,如clicked

源文件

////////////////////////////////////////////////////////////////////////////////
// d1_dynamicBtn.h
// 程序员:黄江斌
// 功能:动态按钮类声明
// 时间:20:05 2005-10-1
// 最后修改时间:20:05 2005-10-1
////////////////////////////////////////////////////////////////////////////////

#pragma once


// d1_dynamicBtn

class d1_dynamicBtn : public CButton
{
DECLARE_DYNAMIC(d1_dynamicBtn)

public:
//定义是不创建,要在下文中创建按钮
d1_dynamicBtn();
//定义对象时创建按钮
d1_dynamicBtn(
LPCTSTR lpszCaption , DWORD dwStyle , const RECT &rect ,
CWnd *pParentWnd , UINT nID
);
//定义对象时创建按钮,并且指定配方方案
d1_dynamicBtn(
LPCTSTR lpszCaption , DWORD dwStyle , const RECT &rect ,
CWnd *pParentWnd , UINT nID ,
Color colorLeveal , Color colorEnter , Color colorDown , Color colorFont );

virtual ~d1_dynamicBtn();
public:
void SetColor( Color colorLeavel , Color colorEnter , Color colorDown , Color colorFont );
private:
//变量初始化,每个构造函数都要调用
void init();
private:
Color *m_colorLeavel;
Color *m_colorEnter;
Color *m_colorDown;
Color *m_colorFont;
//按钮当前状态

//0鼠标没有进入按钮区,或已经离开
//1鼠标进入按钮区
//2鼠标被按下
int m_nState;
//为 m_nState 定义的常量
static const int MOUSE_LEAVEL = 0;
static const int MOUSE_ENTER = 1;
static const int MOUSE_DOWN = 2;
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnPaint();
virtual BOOL Create(LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
};

////////////////////////////////////////////////////////////////////////////////
// d1_dynamicBtn.cpp
// 程序员:黄江斌
// 功能:动态按钮类实现
// 时间:20:05 2005-10-1
// 最后修改时间:20:05 2005-10-1
////////////////////////////////////////////////////////////////////////////////

// d1_dynamicBtn.cpp : 实现文件
//

#include "stdafx.h"
#include "d1_dynamicBtn.h"


// d1_dynamicBtn

IMPLEMENT_DYNAMIC(d1_dynamicBtn, CButton)

//构造函数

//定义是不创建,要在下文中创建按钮
d1_dynamicBtn::d1_dynamicBtn()
{
this->init();
this->m_colorLeavel = new Color( 255 , 0 , 0 , 0 );
this->m_colorEnter = new Color( 255 , 255 , 0 , 0 );
this->m_colorDown = new Color( 255 , 255 , 0 , 0 );
this->m_colorFont = new Color( 255 , 255 , 255 , 255 );
}
//定义对象时创建按钮
d1_dynamicBtn::d1_dynamicBtn(
LPCTSTR lpszCaption , DWORD dwStyle , const RECT &rect ,
CWnd *pParentWnd , UINT nID )
{
this->init();
this->m_colorLeavel = new Color( 255 , 0 , 0 , 0 );
this->m_colorEnter = new Color( 255 , 255 , 0 , 0 );
this->m_colorDown = new Color( 255 , 255 , 0 , 0 );
this->m_colorFont = new Color( 255 , 255 , 255 , 255 );

this->Create( lpszCaption , dwStyle , rect , pParentWnd , nID );

}
//定义对象时创建按钮,并且指定配方方案
d1_dynamicBtn::d1_dynamicBtn(
LPCTSTR lpszCaption , DWORD dwStyle , const RECT &rect ,
CWnd *pParentWnd , UINT nID ,
Color colorLeavel , Color colorEnter , Color colorDown , Color colorFont )
{
this->init();

this->m_colorLeavel = new Color(
colorLeavel.GetA() , colorLeavel.GetR() , colorLeavel.GetG() , colorLeavel.GetB() );
this->m_colorEnter = new Color(
colorEnter.GetA() , colorEnter.GetR() , colorEnter.GetG() , colorEnter.GetB() );
this->m_colorDown = new Color(
colorDown.GetA() , colorDown.GetR() , colorDown.GetG() , colorDown.GetB() );
this->m_colorFont = new Color(
colorFont.GetA() , colorFont.GetR() , colorFont.GetG() , colorFont.GetB() );

this->Create( lpszCaption , dwStyle , rect , pParentWnd , nID );
}
d1_dynamicBtn::~d1_dynamicBtn()
{
delete this->m_colorLeavel;
delete this->m_colorEnter;
delete this->m_colorDown;
delete this->m_colorFont;
}


BEGIN_MESSAGE_MAP(d1_dynamicBtn, CButton)
ON_WM_PAINT()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
END_MESSAGE_MAP()

//自定义函数

//函数名:private void init()
//功能:变量初始化,每个构造函数都要调用
void d1_dynamicBtn::init()
{
this->m_nState = 0;
}
//
//函数名:public void SetColor()
//功能:设定按三种状态下的色彩值
void d1_dynamicBtn::SetColor( Color colorLeavel , Color colorEnter , Color colorDown , Color colorFont )
{
this->m_colorLeavel->SetValue( colorLeavel.GetValue() );
this->m_colorEnter->SetValue( colorEnter.GetValue() );
this->m_colorDown->SetValue( colorDown.GetValue() );
this->m_colorFont->SetValue( colorFont.GetValue() );

this->Invalidate();
}
//
// d1_dynamicBtn 消息处理程序


void d1_dynamicBtn::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CButton::OnPaint()
Graphics graphics( dc.m_hDC );
SolidBrush *brush;
switch( this->m_nState )
{
case 0:
brush = new SolidBrush( *this->m_colorLeavel );
break;
case 1:
brush = new SolidBrush( *this->m_colorEnter );
break;
case 2:
brush = new SolidBrush( *this->m_colorDown );
break;
}

CRect rect;
GetClientRect( rect );
RectF rectf( rect.left , rect.top , rect.Width() , rect.Height() );
graphics.FillRectangle( brush , rectf );

SolidBrush fontBrush( *this->m_colorFont );
Pen pen( &fontBrush , 10 );
graphics.DrawRectangle( &pen , rectf );

WCHAR str[256];
ZeroMemory( str , 256 );

CString stra;
this->GetWindowText( stra );

int len = sizeof( stra.GetBuffer() );
MultiByteToWideChar( CP_ACP , 0 , (LPCSTR)stra.GetBuffer() , len , str , len );

Font myFont( L"黑体" , 20 );
RectF layoutRect = rectf;
StringFormat format;
format.SetAlignment( StringAlignmentCenter );
format.SetLineAlignment( StringAlignmentCenter );

graphics.DrawString(
str ,
wcslen( str ) ,
&myFont ,
layoutRect ,
&format ,
&fontBrush
);
}

BOOL d1_dynamicBtn::Create(
LPCTSTR lpszCaption, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
// TODO: 在此添加专用代码和/或调用基类
BOOL result = CButton::Create(lpszCaption, dwStyle, rect, pParentWnd, nID);
//如果创建成功
if( result )
{
//指定按钮为 自定义风格
this->SetButtonStyle( BS_USERBUTTON );
}

return result;
}

void d1_dynamicBtn::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用[s:292]值
CRect rect;
GetClientRect( rect );
BOOL ptIn = rect.PtInRect( point );

if( ptIn && this->m_nState == 0 )
{
//鼠标进入按钮区,则设置为进入,并且 SetCapture()
this->m_nState = MOUSE_ENTER;
this->Invalidate();
::SetCapture( this->GetSafeHwnd() );
}
else if( !ptIn && this->m_nState != 0 )
{
//如果鼠标已经离开按钮区,则设置为离开,并且 ReleaseCapture()
this->m_nState = MOUSE_LEAVEL;
this->Invalidate();
::ReleaseCapture();
}
CButton::OnMouseMove(nFlags, point);
}

void d1_dynamicBtn::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用[s:292]值
this->m_nState = MOUSE_DOWN;
this->Invalidate();

CButton::OnMButtonDown(nFlags, point);
}

void d1_dynamicBtn::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用[s:292]值
CRect rect;
GetClientRect( rect );
BOOL ptIn = rect.PtInRect( point );

this->m_nState = MOUSE_LEAVEL;
if( !ptIn )
::ReleaseCapture();

CButton::OnLButtonUp(nFlags, point);
}

////////////////////////////////////////////////////////////////////////////////
// userBtn1.h
// 程序员:黄江斌
// 功能:动态按钮类应用举例声明部分
// 时间:20:05 2005-10-1
// 最后修改时间:20:05 2005-10-1
////////////////////////////////////////////////////////////////////////////////

#pragma once
#include "d1_dynamicbtn.h"

class myBtn :
public d1_dynamicBtn
{
public:
myBtn(void);
//定义是不创建,要在下文中创建按钮
//定义对象时创建按钮
myBtn( LPCTSTR lpszCaption , DWORD dwStyle , const RECT &rect , CWnd *pParentWnd , UINT nID );

virtual ~myBtn(void);
DECLARE_MESSAGE_MAP()
afx_msg void OnBnClicked();
};

////////////////////////////////////////////////////////////////////////////////
// userBtn1.cpp
// 程序员:黄江斌
// 功能:动态按钮类应用举例实现
// 时间:20:05 2005-10-1
// 最后修改时间:20:05 2005-10-1
////////////////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include ".\userBtn1.h"

myBtn::myBtn(void)
{
}
myBtn::myBtn( LPCTSTR lpszCaption , DWORD dwStyle , const RECT &rect , CWnd *pParentWnd , UINT nID )
: d1_dynamicBtn( lpszCaption , dwStyle , rect , pParentWnd , nID )
{
}
myBtn::~myBtn(void)
{
}
BEGIN_MESSAGE_MAP(myBtn, d1_dynamicBtn)
ON_CONTROL_REFLECT(BN_CLICKED, OnBnClicked)
END_MESSAGE_MAP()

void myBtn::OnBnClicked()
{
// TODO: 在此添加控件通知处理程序代码
AfxMessageBox( "hi" );
}

wwwwtttt | 2006-10-25 16:16:00 | 显示全部楼层
寒!
您需要登录后才可以回帖 登录 | 注册哦

本版积分规则