能详细点吗?还有brush在tButton类型的控件好像没作用

解决方案 »

  1.   

    这是TWinControl中的WM_EraseBkgnd消息,你可以改变FBrush的Color、Style等,也可以改变FillRect函数中的Rect等.
    procedure TWinControl.WMEraseBkgnd(var Message: TWMEraseBkgnd);
    begin
      { Only erase background if we're not doublebuffering or painting to memory. }
      if not FDoubleBuffered or
        (TMessage(Message).wParam = TMessage(Message).lParam) then
        FillRect(Message.DC, ClientRect, FBrush.Handle);
      Message.Result := 1;
    end;
      

  2.   

    呵呵,其实上面的回答根本就没讲清楚,下面补充一点:TControl下面有两个类:TWinControl和TGraphicControl,其中TWinControl有Handle没Canvas,而TGraphicControl有Canvas没Handle,从TGraphicControl继承的控件要画背景可以使用其Canvas的Brush,而从TWinControl继承的则需要根据其Handle取得DC,然后使用FillRect函数来画.但是从TWinControl继承的TCustomControl却具有Canvas属性,可以在其Canvas上画.
    所以对从TCustomControl或TGraphicControl继承的直接用Canvas属性就行啦,而对从TGraphicControl继承的,你需要创建一个新的类,在这个类中相应WM_PAINT或WM_ERASEBKGND消息来画窗体.
      

  3.   

    我的意思是怎样从外部截获消息,控制TControl的Brush,比如媒体播放器那样
      

  4.   

    to 风儿飞飞:你得用GetWindowLong取出它的消息处理函数,然后用SetWindowLong将之设置为自己的。然后在你自己的消息响应函数中处理WM_EraseBkgnd消息。
      

  5.   

    agui说得没错,你找本书找到子类化一章,自然有说明,小心细节!
      

  6.   

    问题所在:经过试验才知道,TButton根本就不需要WM_EraseBkgnd,它在WM_PAINT中把所有客户区都绘制了一遍,所以只有截WM_PAINT消息自绘才能定制其颜色了。
      

  7.   

    这是源码,在Form上放两个Button控件(Button1, Button2没用,只是用来移开焦点)。有一点还需要处理:WM_LBUTTONDOWN, WM_LBUTTONUP,Button在这两个消息中重绘了自己,你也需要重绘。unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, ComCtrls, DatetimeDialog, ExtCtrls, Db, Grids, DBGrids,
      DBTables;type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
        FDefWndProc: TFarProc;    procedure ButtonWndProc(var Message: TMessage);
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.DFM}procedure TForm1.ButtonWndProc(var Message: TMessage);
    var
      dc: HDC;
      rct: TRect;
      ps: TPaintStruct;
      font: HFONT;
    begin
      if Message.Msg=WM_ERASEBKGND then
      begin
        FillRect( TWMEraseBkgnd(Message).DC, Button1.ClientRect, Button1.Brush.Handle );
        Message.Result := 1;
      end
      else
      if Message.Msg=WM_PAINT then
      begin
        if( GetUpdateRect( Button1.Handle, rct, True ) )then
        begin
          BeginPaint( Button1.Handle, ps );
          try
            dc := ps.hdc;
            rct := Button1.ClientRect;
            DrawFrameControl( dc, rct, DFC_BUTTON, DFCS_BUTTONPUSH  or DFCS_ADJUSTRECT);
            FillRect( dc, rct, Button1.Brush.Handle );
            if Button1.Focused then
            begin
              InflateRect( rct, -2, -2 );
              DrawFocusRect( dc, rct );
            end;
            font := SelectObject( dc, Button1.Font.Handle );
            SetTextColor( dc, ColorToRGB(clWhite) );
            SetBkMode( dc, TRANSPARENT );
            DrawText( dc, Pchar(Button1.Caption), Length(Button1.Caption), rct, DT_CENTER or DT_VCENTER or DT_SINGLELINE );
            SelectObject( dc, font );
          finally
            EndPaint( Button1.Handle, ps );
          end;
        end;
      end
      else
        with Message do
          Result := CallWindowProc(FDefWndProc, Button1.Handle, Msg, wParam, lParam);
    end;procedure TForm1.FormCreate(Sender: TObject);
    var
      FButtonInstance: TFarProc;
    begin
      Button1.Brush.Style := bsSolid;
      Button1.Brush.Color := clBlue;
      FButtonInstance := MakeObjectInstance(ButtonWndProc);
      FDefWndProc := Pointer(GetWindowLong(Button1.Handle, GWL_WNDPROC));
      SetWindowLong(Button1.Handle, GWL_WNDPROC, Longint(FButtonInstance));
    end;end.