想找自绘按钮的代码,找了很久,下载到了一个。作者不记得了。不过有点不完美。原代码没有处理,鼠标放在按钮上,按钮高亮显示功能。因此,增加了两个鼠标的CM_MOUSEENTERH和CM_MOUSELEAVE事件。
#ifndef Unit12H
#define Unit12H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Buttons.hpp>
#include <memory>
using namespace std;
//---------------------------------------------------------------------------
class TColorButton : public TButton
{
public:
__fastcall TColorButton(TComponent* Owner);
__published:
__property TColor Color ={read = GetColor, write = SetColor};
__property TColor ColorLo ={read = ColorLo_, write = SetColorLo,default = clBtnShadow};
__property TColor ColorHi ={read = ColorHi_, write = SetColorHi,default = clBtnHighlight};
protected:
// 继承的成员函数
virtual void __fastcall CreateParams(TCreateParams& Params);
virtual void __fastcall SetButtonStyle(bool ADefault);
// 引入的成员函数
virtual void __fastcall DoDrawButtonFace(const TOwnerDrawState& state);
virtual void __fastcall DoDrawButtonText(const TOwnerDrawState& state);
private:
TColor ColorLo_;
TColor ColorHi_;
std::auto_ptr<TCanvas> Canvas_;
bool draw_as_default_;
bool inButton;
TColor __fastcall GetColor();
void __fastcall SetColor(TColor Value);
void __fastcall SetColorLo(TColor Value);
void __fastcall SetColorHi(TColor Value);
MESSAGE void __fastcall CNDrawItem(TMessage& Msg);
MESSAGE void __fastcall WMLButtonDblClk(TMessage& Msg);
MESSAGE void __fastcall CMFontChanged(TMessage& Msg);
MESSAGE void __fastcall CMEnabledChanged(TMessage& Msg);
MESSAGE void __fastcall CMmouseover(TMessage & Msg);
MESSAGE void __fastcall CMmouseleave(TMessage & Msg);
void __fastcall DrawImag(AnsiString path);
public:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(CN_DRAWITEM, TMessage, CNDrawItem)
MESSAGE_HANDLER(WM_LBUTTONDBLCLK, TMessage, WMLButtonDblClk)
MESSAGE_HANDLER(CM_FONTCHANGED, TMessage, CMFontChanged)
MESSAGE_HANDLER(CM_ENABLEDCHANGED, TMessage, CMEnabledChanged)
VCL_MESSAGE_HANDLER(CM_MOUSEENTER, TMessage, CMmouseover)
VCL_MESSAGE_HANDLER(CM_MOUSELEAVE, TMessage, CMmouseleave)
END_MESSAGE_MAP(TButton)
};
void __fastcall TColorButton::CreateParams(TCreateParams& Params)
{
TButton::CreateParams(Params);
Params.Style |= BS_OWNERDRAW;
}
void __fastcall TColorButton::
SetButtonStyle(bool ADefault)
{
if (draw_as_default_ != ADefault)
{
draw_as_default_ = ADefault;
InvalidateRect(Handle, NULL, FALSE);
}
}
void __fastcall TColorButton::CNDrawItem(TMessage& Msg)
{
// 获取 DRAWITEMSTRUCT
const DRAWITEMSTRUCT* pDrawItem =reinterpret_cast<DRAWITEMSTRUCT*>(Msg.LParam);
// 保存当前状态
// 目标DC
SaveDC(pDrawItem->hDC);
// 绑定 Canvas_ 到目标 DC
Canvas_->Handle = pDrawItem->hDC;
try
{
// extract the state flags...
TOwnerDrawState state;
// 按钮具有键盘焦点
if (pDrawItem->itemState & ODS_FOCUS)
{
state = state << odFocused;
}
// 已经按下
if (pDrawItem->itemState &
ODS_SELECTED)
{
state = state << odSelected;
}
// 按钮禁用
if (pDrawItem->itemState &
ODS_DISABLED)
{
state = state << odDisabled;
}
// 画按钮
DoDrawButtonFace(state);
// 画文本
//DoDrawButtonText(state);
}
catch (...)
{
// clean up
Canvas_->Handle = NULL;
RestoreDC(pDrawItem->hDC, -1);
}
// clean up
Canvas_->Handle = NULL;
RestoreDC(pDrawItem->hDC, -1);
// reply TRUE
Msg.Result = TRUE;
}
void __fastcall TColorButton::DoDrawButtonFace(const TOwnerDrawState& state)
{
//Brush->Style = bsClear;//绘图事件里,已对图片作透明处理,不须再处理
Canvas_->Brush = Brush;
TRect RClient = ClientRect;
// 缺省按钮
// 有键盘焦点...
if (draw_as_default_ || state.Contains(odFocused))
{
DrawImag("UI\\down.bmp");
}
// 按下中...
if (state.Contains(odSelected))
{
DrawImag("UI\\down.bmp");
}
// 按钮未按下...
else
{
if(!inButton)//按钮normal
{
DrawImag("UI\\Normal.bmp");
}
else
{
DrawImag("UI\\over.bmp"); //鼠标在按钮上
}
}
}
//暂且未使用函数,图片代替,也可以启用,自绘文字
void __fastcall TColorButton::DoDrawButtonText(const TOwnerDrawState& state)
{
if (Caption.Length() == 0) return;
RECT RText = {0, 0, Width, Height};
Canvas_->Font = Font;
Canvas_->Brush = Brush;
SetBkMode(
Canvas_->Handle, TRANSPARENT
);
// 按钮按下...
if (state.Contains(odSelected))
{
// 文件偏移
OffsetRect(&RText, 1, 1);
}
// 按钮禁用...
if (!Enabled || state.Contains(odDisabled))
{
// 重绘文字
// 禁用时的文字
OffsetRect(&RText, 1, 1);
Canvas_->Font->Color = ColorHi_;
DrawText(
Canvas_->Handle, Caption.c_str(),
-1, &RText, DT_CENTER |
DT_VCENTER | DT_SINGLELINE
);
OffsetRect(&RText, -1, -1);
Canvas_->Font->Color = ColorLo_;
}
if(inButton)
{
Canvas_->Font->Color = clYellow;
DrawText(Canvas_->Handle, Caption.c_str(), -1,
&RText, DT_CENTER | DT_VCENTER |
DT_SINGLELINE
);
}
else
{
Canvas_->Pen->Color = clRed;
// 重绘文字
DrawText(
Canvas_->Handle, Caption.c_str(), -1,
&RText, DT_CENTER | DT_VCENTER |
DT_SINGLELINE
);
}
// 键盘按下时的焦点...
if (state.Contains(odFocused))
{
// 重绘选中时的矩形
TRect RFocus = ClientRect;
InflateRect(reinterpret_cast<TRect *>(&RFocus),-4, -4);
Canvas_->DrawFocusRect(RFocus);
}
}
TColor __fastcall TColorButton::GetColor()
{
return Brush->Color;
}
void __fastcall TColorButton::SetColor(TColor Value)
{
if (Brush->Color != Value)
{
Brush->Color = Value;
InvalidateRect(Handle, NULL, TRUE);
}
}
void __fastcall TColorButton::SetColorLo(TColor Value)
{
if (ColorLo_ != Value)
{
ColorLo_ = Value;
InvalidateRect(Handle, NULL, TRUE);
}
}
void __fastcall TColorButton::SetColorHi(TColor Value)
{
if (ColorHi_ != Value)
{
ColorHi_ = Value;
InvalidateRect(Handle, NULL, TRUE);
}
}
void __fastcall TColorButton::CMFontChanged(TMessage& Msg)
{
TButton::Dispatch(&Msg);
InvalidateRect(Handle, NULL, TRUE);
}
void __fastcall TColorButton::CMEnabledChanged(TMessage& Msg)
{
TButton::Dispatch(&Msg);
InvalidateRect(Handle, NULL, TRUE);
}
void __fastcall TColorButton::WMLButtonDblClk(TMessage& Msg)
{
SNDMSG(Handle, WM_LBUTTONDOWN,Msg.WParam, Msg.LParam);
}
void __fastcall TColorButton::CMmouseover(TMessage & Msg)
{
inButton = true;
Repaint();
}
void __fastcall TColorButton::CMmouseleave(TMessage & Msg)
{
inButton = false;
Repaint();
}
void __fastcall TColorButton::DrawImag(AnsiString path)
{
::Graphics::TBitmap *bmp= new ::Graphics::TBitmap;
bmp->Transparent = true;//是否透明
bmp->LoadFromFile(path);
Canvas_->Draw(0,0,bmp);
delete bmp;
}
//---------------------------------------------------------------------------
#endif
调用方法如下:先准备3张图片,分别代码按钮正常、高亮、点击时的状态。即normal.bmp,over.bmp,down.bmp,
在当前运行目录中,建一个文件夹,名为UI,将这三张图片复制到文件夹中。
.h头文件如下:
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Buttons.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
void __fastcall myButton(TObject *Sender);//自绘按钮的事件
protected:
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
.cpp文件如下:
#include <vcl.h>
#pragma hdrstop
#include "ColorButton.h"
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
TColorButton *gButton;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
__fastcall TColorButton::TColorButton(TComponent* Owner)
: TButton(Owner), ColorLo_(clBtnShadow), ColorHi_(clBtnHighlight),
Canvas_(new TCanvas()),draw_as_default_(false)
{
}
void __fastcall TForm1::myButton(TObject *Sender)
{
ShowMessage("按钮被点击");
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
gButton = new TColorButton(Form1);
gButton->Parent = Form1;
gButton->Top=70;
gButton->Left=50;
gButton->Width = 345;
gButton->Height = 42;
gButton->Color=clGreen;
gButton->Font->Name="宋体";
gButton->Font->Size =9;
gButton->Font->Color=clRed;
gButton->Caption="按钮";
gButton->OnClick = myButton;//自定义事件
}
扩展一下,可以改成CheckBox按钮,增加一个是否选中的属性,然后再准备3张,选中时显示的图片即可。
效果图如下: