打造自己的CButton

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


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: 在此添加消息处理程序代码和/或调用默认值
 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: 在此添加消息处理程序代码和/或调用默认值
 this->m_nState = MOUSE_DOWN;
 this->Invalidate();

 CButton::OnMButtonDown(nFlags, point);
}

void d1_dynamicBtn::OnLButtonUp(UINT nFlags, CPoint point)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 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" );
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值