大家好:
同事寫了一個 button 的元件
但在 98 和 ME 執行後,動態換圖片幾次後會出錯(原因還找不到)
想請大家幫忙看看以下的程式是否有缺失,謝謝 GoodButton.h
//---------------------------------------------------------------------------
#ifndef GoodButtonH
#define GoodButtonH
//---------------------------------------------------------------------------
#include
#include
#include
//---------------------------------------------------------------------------
class TPictureIndex : public TPersistent
{
private:
TNotifyEvent FOnChange;
int FUp, FOver, FDown, FDisable;
int FPictureCount; protected:
virtual void __fastcall SetDisable(int value);
virtual void __fastcall SetDown(int value);
virtual void __fastcall SetPictureCount(int value);
virtual void __fastcall SetOver(int value);
virtual void __fastcall SetUp(int value); public: __fastcall TPictureIndex();
__fastcall ~TPictureIndex();
//virtual void __fastcall Assign(TPersistent *value); __published:
__property int PictureCount = {read = FPictureCount, write = SetPictureCount, default = 2};
__property int Disable = {read = FDisable, write = SetDisable, default = 0};
__property int Down = {read = FDown, write = SetDown, default = 0};
__property int Over = {read = FOver, write = SetOver, default = 0};
__property int Up = {read = FUp, write = SetUp, default = 0};
__property TNotifyEvent OnChange = {read = FOnChange, write = FOnChange};
}; enum TTransparentState {tsNone, tsLook, tsFull}; class PACKAGE TGoodButton : public TGraphicControl
{
private:
AnsiString FCaption;
TFont *FFont;
TPicture *FPicture;
TPictureIndex *FPictureIndex;
TColor FTransparentColor;
TTransparentState FTransparentState;
bool FChecked;
bool FShowCaption;
bool isDown, isOver;
int pictureIndex; protected:
virtual void __fastcall SetCaption(AnsiString value);
virtual void __fastcall SetChecked(bool value);
void __fastcall SetEnabled(bool value);
virtual void __fastcall SetFont(TFont *value);
virtual void __fastcall SetShowCaption(bool value);
virtual void __fastcall SetPicture(TPicture *value);
virtual void __fastcall SetPictureIndex(TPictureIndex *value);
virtual void __fastcall SetTransparentColor(TColor value);
virtual void __fastcall SetTransparentState(TTransparentState value);
void __fastcall FontChanged(TObject *Sender);
virtual void __fastcall PictureChanged(TObject *);
virtual void __fastcall PictureIndexChanged(TObject *Sender);
virtual void __fastcall Modified(bool force);
bool __fastcall IsTransparentColor(int X, int Y);
virtual void __fastcall WndProc(TMessage &Message);
void __fastcall Paint(void);
TNotifyEvent FOnMouseEnter, FOnMouseLeave; public:
__fastcall TGoodButton(TComponent* Owner);
virtual __fastcall ~TGoodButton();
__published:
__property Anchors;
__property Cursor;
__property Enabled;
__property ShowHint;
__property Visible;
__property OnClick;
__property AnsiString Caption = {read = FCaption, write = SetCaption};
__property bool Checked = {read = FChecked, write = SetChecked};
__property TFont *Font = {read = FFont, write = SetFont};
__property TPicture *Picture = {read = FPicture, write = SetPicture};
__property TPictureIndex *PictureIndex = {read = FPictureIndex, write = SetPictureIndex};
__property bool ShowCaption = {read = FShowCaption, write = SetShowCaption};
__property TColor TransparentColor = {read = FTransparentColor, write = SetTransparentColor};
__property TTransparentState TransparentState = {read = FTransparentState, write = SetTransparentState};
__property OnMouseDown;
__property OnMouseMove;
__property OnMouseUp;
__property TNotifyEvent OnMouseEnter = {read = FOnMouseEnter, write = FOnMouseEnter};
__property TNotifyEvent OnMouseLeave = {read = FOnMouseLeave, write = FOnMouseLeave};
};
//---------------------------------------------------------------------------
#endif GoodButton.cpp /*===========================================================================
說明:繼承TGraphicControl而設計的按鈕,可以針對滑鼠的移入、移出、按下、
放開而顯示不同的圖案,並且增加了OnMouseEnter和OnMouseLeave的事件。
如果將Transparent設為true,則滑鼠的動作只會在非透明的地方有作用。
===========================================================================*/
//---------------------------------------------------------------------------
#include
#pragma hdrstop #include "GoodButton.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
// static inline void ValidCtrCheck(TGoodButton *)
{
new TGoodButton(NULL);
}
//--------------------------------------------------------------------------- __fastcall TPictureIndex::TPictureIndex() : TPersistent()
{
FDisable = FDown = FOver = FDisable = 0;
FPictureCount = 2;
}
//--------------------------------------------------------------------------- __fastcall TPictureIndex::~TPictureIndex()
{
}
//--------------------------------------------------------------------------- /*void __fastcall TPictureIndex::Assign(TPersistent *value)
{
TPictureIndex *Source; Source = (TPictureIndex *)value; FDisable = Source->FDisable;
FDown = Source->FDown;
FOver = Source->FOver;
FUp = Source->FUp;
FPictureCount = Source->FPictureCount;
if (FOnChange)
FOnChange(this);
}*/
//--------------------------------------------------------------------------- void __fastcall TPictureIndex::SetDisable(int value)
{
if (value == FDisable || value < 0 || value >= FPictureCount)
return; FDisable = value;
if (FOnChange)
FOnChange(this);
}
//--------------------------------------------------------------------------- void __fastcall TPictureIndex::SetDown(int value)
{
if (value == FDown || value < 0 || value >= FPictureCount)
return; FDown = value;
if (FOnChange)
FOnChange(this);
}
//--------------------------------------------------------------------------- void __fastcall TPictureIndex::SetOver(int value)
{
if (value == FOver || value < 0 || value >= FPictureCount)
return; FOver = value;
if (FOnChange)
FOnChange(this);
}
//--------------------------------------------------------------------------- void __fastcall TPictureIndex::SetUp(int value)
{
if (value == FUp || value < 0 || value >= FPictureCount)
return; FUp = value;
if (FOnChange)
FOnChange(this);
}
//--------------------------------------------------------------------------- void __fastcall TPictureIndex::SetPictureCount(int value)
{
if (value == FPictureCount || value <= 0)
return; if (FDisable >= value)
FDisable = value - 1;
if (FDown >= value)
FDown = value - 1;
if (FOver >= value)
FOver = value - 1;
if (FUp >= value)
FUp = value - 1;
FPictureCount = value;
if (FOnChange)
FOnChange(this);
}
//---------------------------------------------------------------------------
__fastcall TGoodButton::TGoodButton(TComponent* Owner)
: TGraphicControl(Owner)
{
FCaption = "";
FChecked = false;
FFont = new TFont();//Canvas->Font;
FPicture = new TPicture();
FPictureIndex = new TPictureIndex();
FTransparentColor = clWhite;
FTransparentState = tsNone;
FFont->OnChange = FontChanged;
FPicture->OnChange = PictureChanged;
FPictureIndex->OnChange = PictureIndexChanged;
FOnMouseEnter = FOnMouseLeave = NULL;
Width = 100;
Height = 100;
pictureIndex = 0;
isDown = isOver = false;
}
//---------------------------------------------------------------------------
__fastcall TGoodButton::~TGoodButton()
{
delete FFont;
delete FPicture;
delete FPictureIndex;
}
//---------------------------------------------------------------------------
//--------------------------------------------------------------------------- void __fastcall TGoodButton::SetCaption(AnsiString value)
{
FCaption = value;
Invalidate();
}
//--------------------------------------------------------------------------- void __fastcall TGoodButton::SetChecked(bool value)
{
FChecked = value;
Modified(false);
}
//--------------------------------------------------------------------------- void __fastcall TGoodButton::SetEnabled(bool value)
{
TGraphicControl::SetEnabled(value);
Modified(false);
}
//---------------------------------------------------------------------------
void __fastcall TGoodButton::SetFont(TFont *value)
{
FFont->Assign(value);
}
//--------------------------------------------------------------------------- void __fastcall TGoodButton::SetShowCaption(bool value)
{
FShowCaption = value;
Invalidate();
}
//--------------------------------------------------------------------------- void __fastcall TGoodButton::SetPicture(TPicture *value)
{
/*if (FPicture == NULL)
FPicture = new TPicture();*/
FPicture->Assign(value);
Invalidate();
}
//--------------------------------------------------------------------------- void __fastcall TGoodButton::SetPictureIndex(TPictureIndex *value)
{
FPictureIndex->Assign(value);
Invalidate();
}
//--------------------------------------------------------------------------- void __fastcall TGoodButton::SetTransparentColor(TColor value)
{
FTransparentColor = value;
Invalidate();
}
//--------------------------------------------------------------------------- void __fastcall TGoodButton::SetTransparentState(TTransparentState value)
{
FTransparentState = value;
Invalidate();
}
//--------------------------------------------------------------------------- void __fastcall TGoodButton::FontChanged(TObject *Sender)
{
Invalidate();
}
//--------------------------------------------------------------------------- void __fastcall TGoodButton::PictureChanged(TObject *Sender)
{
if (FPicture->Width > 0 && FPicture->Height > 0)
{
Width = FPicture->Width / FPictureIndex->PictureCount;
Height = FPicture->Height;
}
Modified(true);
}
//--------------------------------------------------------------------------- void __fastcall TGoodButton::PictureIndexChanged(TObject *Sender)
{
PictureChanged(Sender);
}
//--------------------------------------------------------------------------- void __fastcall TGoodButton::Modified(bool update)
{
int index; index = pictureIndex;
if (!Enabled)
pictureIndex = FPictureIndex->Disable;
else if ((isOver && isDown) || FChecked)
pictureIndex = FPictureIndex->Down;
else if (isOver)
pictureIndex = FPictureIndex->Over;
else
pictureIndex = FPictureIndex->Up;
if (pictureIndex != index || update)
Invalidate();
}
//--------------------------------------------------------------------------- void __fastcall TGoodButton::Paint(void)
{
bool designing;
TRect RcSrc, RcDst;
Canvas->Font = Font;
designing = ComponentState.Contains(csDesigning);
if (FPicture->Graphic) //有圖案
{
if (Visible || designing)
{
RcSrc = TRect(pictureIndex * Width, 0, (pictureIndex 1) * Width, Height);
RcDst = TRect(0, 0, Width, Height);
if (FTransparentState == tsNone)
Canvas->CopyRect(RcDst, FPicture->Bitmap->Canvas, RcSrc);
else
{
Canvas->Brush->Style = bsClear;
Canvas->BrushCopy(RcDst, FPicture->Bitmap, RcSrc, FTransparentColor);
}
}
} if (FShowCaption || designing) //顯示標題
{
Canvas->Brush->Style = bsClear;
if (!Enabled) Canvas->Font->Color = clSilver;
if (!isDown)
Canvas->TextOut((Width - Canvas->TextWidth(FCaption)) / 2, Height - Canvas->TextHeight(FCaption) - 5, FCaption);
else
Canvas->TextOut((Width - Canvas->TextWidth(FCaption)) / 2 1, Height - Canvas->TextHeight(FCaption) - 5 1, FCaption);
} if (designing) //設計時期
{
Canvas->Pen->Style = psDash;
Canvas->Brush->Style = bsClear;
Canvas->Rectangle(0, 0, Width, Height); //畫虛線方框
}
}
//--------------------------------------------------------------------------- bool __fastcall TGoodButton::IsTransparentColor(int X, int Y)
{
return FTransparentState == tsFull && (FPicture->Bitmap->Canvas->Pixels[X][Y] == FTransparentColor || X >= FPicture->Width || Y >= FPicture->Height);
}
//---------------------------------------------------------------------------
void __fastcall TGoodButton::WndProc(TMessage &Message)
{
TGraphicControl::WndProc(Message); if (ComponentState.Contains(csDesigning)) //設計時期
return; switch (Message.Msg)
{
case CM_HITTEST:
Message.Result = !IsTransparentColor(Message.LParamLo, Message.LParamHi);
break;
case WM_LBUTTONDOWN: //按下左鍵
if (Enabled)
{
isDown = true;
Modified(false);
}
break;
case WM_LBUTTONUP: //放開左鍵
if (Enabled)
{
isDown = false;
Modified(false);
}
break;
case CM_MOUSEENTER: //滑鼠移入
if (Enabled)
{
isOver = true;
Modified(false);
if (FOnMouseEnter)
FOnMouseEnter(this);
}
break;
case CM_MOUSELEAVE: //滑鼠移出
if (Enabled)
{
isOver = false;
Modified(false);
if (FOnMouseLeave)
FOnMouseLeave(this);
}
break;
}
}
//---------------------------------------------------------------------------
namespace Goodbutton
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TGoodButton)};
RegisterComponents("Samples", classes, 0);
}
}
//---------------------------------------------------------------------------