源代码吐血大放送(分太少啦):(实现该功能的组件源代码,完全有本人攥写,还可以继续扩展)unit Unit_ESTipsImageBtn;interfaceuses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;type  //图片按钮
  TesTipsImageBtn=class(TGraphicControl)
  private
    { Private declarations }
    //按钮被选择
    FDown:Boolean;
    //缺省按钮图片
    FImage:TBitMap;
    //指示当前使用的是第几幅图片
    //所加载图片将被缺省的分成四幅
    //0:Up           正常
    //1:Disabled     禁止
    //2:Clicked      移动或焦点
    //3:Down         选中
    FImageIndex:0..3;
    //鼠标进入控件的事件
    FOnMouseEnter:TNotifyEvent;
    //鼠标离开控件的事件
    FOnMouseLeave:TNotifyEvent;
  protected
    { Protected declarations }
    //文本变化消息处理
    procedure CMTextChanged(var Message:TMessage);Message CM_TEXTCHANGED;
    //鼠标进入控件消息处理
    procedure WMMouseEnter(var Message:TMessage);Message CM_MOUSEENTER;
    //鼠标在控件中移动消息处理
    procedure WMMouseMove(var Message:TMessage);Message WM_MOUSEMOVE;
    //鼠标离开控件消息处理
    procedure WMMouseLeave(var Message:TMessage);Message CM_MOUSELEAVE;
    //装载按钮图片
    procedure SetImage(const Value:TBitMap);
    //设置按纽按下
    procedure SetDown(const Value:Boolean);
    //
    procedure paint;override;
  public
    { Public declarations }
    constructor Create(AOwner:TComponent);override;
    destructor Destroy;override;
  published
    { Published declarations }
    //当鼠标进入控件时发生
    property OnMouseEnter:TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
    //当鼠标离开控件时发生
    property OnMouseLeave:TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
    //按钮图片
    property Image:TBitMap read FImage write SetImage;
    //表示按纽被按下
    property Down:Boolean read FDown write SetDown;
    //
    property Visible;
    //
    property Enabled;
    //鼠标单击事件
    property OnClick;
    //鼠标双击事件
    property OnDblClick;
    //鼠标按纽按下事件
    property OnMouseDown;
    //鼠标按纽提起事件
    property OnMouseUp;
    //鼠标移动事件
    property OnMouseMove;  end;
  
  procedure Register;implementation
procedure Register;
begin
  RegisterComponents('ESTips', [TesTipsImageBtn]);
end;
{ TesTipsImageBtn }constructor TesTipsImageBtn.Create(AOWner:TComponent);
begin
  inherited Create(AOwner);
  Width:=32;
  Height:=32;
  FImage:=TBitMap.Create;
  FDown:=False;
  FImageIndex:=0;
  FImage.Transparent := True;
  FImage.TransParentColor := FImage.Canvas.Pixels[0,Height];
  FImage.TransparentMode := tmAuto;end;//文本变化消息处理
procedure TesTipsImageBtn.CMTextChanged(var Message:TMessage);
begin
  inherited;
  invalidate;
end;//鼠标进入事件处理
procedure TesTipsImageBtn.WMMouseEnter(var Message:TMessage);
begin
  inherited;
  //若鼠标进入前为图标0,则换成2
  if ((not FDown)and(FImageIndex<>2))then
  begin
    FImageIndex:=2;
    Invalidate;
  end;
end;//鼠标在控件中移动消息处理
procedure TesTipsImageBtn.WMMouseMove(var Message:TMessage);
begin
  if ((not FDown)and(FImageIndex<>2))then
  begin
    FImageIndex:=2;
    Invalidate;
  end;
end;//鼠标离开事件处理
procedure TesTipsImageBtn.WMMouseLeave(var Message:TMessage);
begin
  inherited;
  //若鼠标进入前为图标0,则换成3
  if FDown then FImageIndex:=3 else FImageIndex:=0;
  Invalidate;
end;procedure TesTipsImageBtn.SetImage(const Value:TBitMap);
begin
  //if Assigned(Value) then FImage.Assign(Value);
  FImage.Assign(Value);
  Invalidate;
end;//设置按纽按下
procedure TesTipsImageBtn.SetDown(const Value:Boolean);
begin
   FDown:=Value;
   if Value then FImageIndex:=3 else FImageIndex:=0;
  Invalidate;
end;
procedure TesTipsImageBtn.paint;
var
  MyBitMap:TBitMap;
  MyRect:TRect;
  MyImageIndex:integer;
begin
  inherited;  //若图象为空则退出
  if ((FImage.Width=0)or(FImage.Height=0))then Exit;
  if Enabled then MyImageIndex:=FImageIndex else MyImageIndex:=1;
  MyRect:=Rect(0+MyImageIndex*FImage.Width div 4,0,
               (MyImageIndex+1)*FImage.Width div 4,FImage.Height);
  //从图片中分解出指定索引号码的图片,并设置为透明色
  MyBitMap:=TBitMap.Create;
  MyBitMap.Width:=MyRect.Right-MyRect.Left;
  MyBitMap.Height:=MyRect.Bottom-MyRect.Top;
  MyBitMap.Canvas.CopyRect(Rect(0,0,MyBitMap.Width,MyBitMap.Height),FImage.Canvas,MyRect);
  MyBitMap.Transparent := True;
  MyBitMap.TransParentColor := FImage.Canvas.Pixels[0,Height];
  MyBitMap.TransparentMode := tmAuto;
  //写画布
  Canvas.Lock;
  Canvas.Draw(0,0,MyBitMap);
  Canvas.Unlock;
  //释放 
  MyBitMap.Free;
end;destructor TesTipsImageBtn.Destroy;
begin
  FImage.Free;
  inherited;
end;
end.
由菜单Component->Install Component...导入该新组件。

解决方案 »

  1.   

    没那么麻烦!
    在image的onmousemove里和form的onmousemove里分别处理就可以了。
    (iamge放在form上)
      

  2.   

    其实根本就没有mouseEnter和mouseLeave这两个消息。当鼠标进入一个客户区必然产生一个
    mousemove消息,当它离开时必然触发另一个mousemove消息(一般是这样)
      

  3.   

    To enlightenment(阿明--平均睡眠时间<6h/d的超人),谢谢你,不过我要的是我的问题的答案,也就是说,怎样用类来实现,主要我是想学类的定义和使用。
    TO lance,我开始就想用你说的办法,但是,只要鼠标在Form里一移动,就会调用form的onmouseMove事件,这样图片会闪烁得很厉害,所以我就想用OnMouseEnter和OnMouseLeave
    事件(ONMouseEnter和OnmouseLeave不是Windows的标准消息,是Borland自定义的,我在一本书上看到的)。
      

  4.   

    enlightenment(阿明--平均睡眠时间<6h/d的超人) 写的不错
    通里也可做成Tshape等的移动问题
      

  5.   

    哦,笑话不错嘛,不过好像在讽刺我哦:) 收下了!
    我的意思是能否在一个Unit里定义并且使用。因为我刚学,又不懂,所以我想用一个简单得例子学习类,还有继承等等。
      

  6.   


    哦!这样啊!  我以前发过一帖,不知道你能否“细细”看完?  如果“能”,我相信你必定会有收获的! :)http://www.csdn.net/expert/topic/129/129319.shtm  :)
      

  7.   

    -->enlightenment(阿明--平均睡眠时间<6h/d的超人) WMMouseEnter,WMMouseLeave为什么不是CMMouseEnter,CMMouseLeave?消息明明是CM_XXXX嘛。在WMMouseMove中重绘会不会造成闪烁?-->karron(晴空)
    看他人源代码也是学习啊,不一定要完全跟你的要求一样,否则,你就没有自己练习的机会了。
    enlightenment(阿明--平均睡眠时间<6h/d的超人)很不容易啊,贴了这么多,建议分全给他了。
      

  8.   

    用个flag就可以了.第一次触发mousemove时执行代码,以后就直接exit.
      

  9.   

    enlightenment(阿明--平均睡眠时间<6h/d的超人) 的是正解.
      

  10.   


    实际情况是:没有CMMouseMove,至少我没找到。CM(VCL control message)和WM(Window Messages)我一直混用,到目前还没有出过什么娄子。至于在画布重画时,在LOCK以后操作再UNLOCK,应该不会有问题。我还做过(用画布和定时器共同作用显示简单动画的)控件,倒也没什么闪烁!    当然,绘写画布时,绘写流程、算法该精简的还是要精简,特别是在同一次绘写当中(譬如Paint函数中如果发生前后绘写内容重叠,则产生闪烁的可能性很大)。