请教:有一个form,里面有个pagecontrol(有两个tabsheet),他们的重绘顺序是什么?是什么消息让他们重绘的?百分感谢!

解决方案 »

  1.   

    procedure TForm1.PageControl1DrawTab(Control: TCustomTabControl;
      TabIndex: Integer; const Rect: TRect; Active: Boolean);
    beginend;
      

  2.   

    没,要的不是这个答案的啊!要的是消息流程,以及在vcl中的函数处理流程!谁来帮我,如果正解的话,再开100分。百分感谢!
      

  3.   

    请见delphi的源码:
    procedure TWinControl.PaintHandler(var Message: TWMPaint);
    var
      I, Clip, SaveIndex: Integer;
      DC: HDC;
      PS: TPaintStruct;
    begin
      DC := Message.DC;
      if DC = 0 then DC := BeginPaint(Handle, PS);
      try
        if FControls = nil then PaintWindow(DC) else
        begin
          SaveIndex := SaveDC(DC);
          Clip := SimpleRegion;
          for I := 0 to FControls.Count - 1 do
            with TControl(FControls[I]) do
              if (Visible or (csDesigning in ComponentState) and
                not (csNoDesignVisible in ControlStyle)) and
                (csOpaque in ControlStyle) then
              begin
                Clip := ExcludeClipRect(DC, Left, Top, Left + Width, Top + Height);
                if Clip = NullRegion then Break;
              end;
          if Clip <> NullRegion then PaintWindow(DC);  //先画窗口
          RestoreDC(DC, SaveIndex);
        end;
        PaintControls(DC, nil);  //很显然是先画窗口再画控件。
      finally
        if Message.DC = 0 then EndPaint(Handle, PS);
      end;
    end;
    至于控件的重画顺序,如下源码:
    procedure TWinControl.PaintControls(DC: HDC; First: TControl);
    var
      I, Count, SaveIndex: Integer;
      FrameBrush: HBRUSH;
    begin
      if DockSite and UseDockManager and (DockManager <> nil) then
        DockManager.PaintSite(DC);
      if FControls <> nil then
      begin
        I := 0;
        if First <> nil then
        begin
          I := FControls.IndexOf(First);
          if I < 0 then I := 0;
        end;
        Count := FControls.Count;
        while I < Count do //是根据form的controls[i]属性的顺序重画的。
        begin
          ...
        end;
        ...
      end;
      ...
    end;
    而form的control是个控件数组,其顺序就是在设计时VCL控件放置在窗口上的顺序,而非其TabOrder。
      

  4.   

    至于pagecontrol,当然是哪个tabsheet为active就先画哪个tabsheet。
      

  5.   

    Windows是消息驱动的,哪个先收到WM_PAINT就先重绘哪个
      

  6.   

    那怎么截取发送给pagecontrol的paint消息呢?
      

  7.   

    自己写这个消息的处理过程
    procedure x.onpaint..
    {
    dosomething...
    }
      

  8.   

    那我再问的直接点吧!
    我有这样的代码!procedure TForm1.RefreshPgControl(APageControl: TPageControl);
    var
      iActiveIndex: Integer;
      rRect: TRect;
      sCaption : String;
    begin
      iActiveIndex := APageControl.ActivePageIndex;
      rRect := APageControl.TabRect(iActiveIndex);
      sCaption := APageControl.Pages[iActiveIndex].Caption;
      APageControl.Canvas.Font:= APageControl.Font;
      APageControl.Canvas.Font.Color := clBlue;
      APageControl.Canvas.Brush.Color := clBtnFace;
      APageControl.Canvas.TextOut(rRect.Left + 6, rRect.Top + 2, sCaption);
    end;
    这个代码只是把参数的pagecontrol的活动页的caption字体画为蓝色!通过按钮调用是没问题的!
      

  9.   

    但是这样调用就出问题了,这是为什么?
    procedure TForm1.WndProc(var Message: TMessage);
    begin
      inherited;
      if Message.Msg = WM_PAINT then
        RefreshPgControl(PageControl1);
    end;
    本意是想在窗体重绘的时候,重新刷新pagecontrol的caption字体颜色,可就是不行!
    望高手指点!
      

  10.   

    把RefreshPgControl(PageControl1);写在form的onpaint事件中都没用啊???
      

  11.   

    如果只是把参数的pagecontrol的活动页的caption字体画为蓝色那太简单了,设置其HotTrack为true
      

  12.   

    这只是一个例子而已,具体要求是有4个tabsheet,要把前3个的一个或两个或3个的caption都变为红色。
      

  13.   

    procedure TForm1.WndProc(var Message: TMessage);
    begin
    inherited;
    if Message.Msg = WM_PAINT then
    RefreshPgControl(PageControl1);
    end;procedure TForm1.RefreshPgControl(APageControl: TPageControl);
    var
    iActiveIndex: Integer;
    rRect: TRect;
    sCaption : String;
    begin
    iActiveIndex := APageControl.ActivePageIndex;
    rRect := APageControl.TabRect(iActiveIndex);
    sCaption := APageControl.Pages[iActiveIndex].Caption;
    APageControl.Canvas.Font:= APageControl.Font;
    APageControl.Canvas.Font.Color := clBlue;
    APageControl.Canvas.Brush.Color := clBtnFace;
    APageControl.Canvas.TextOut(rRect.Left + 6, rRect.Top + 2, sCaption);
    end;感觉有几个问题:1. 代码未判断WM_PAINT消息的接收对象
    2. PageControl的WM_PAINT消息不一定要经过其属主窗口
    3. 如果WM_PAINT消息是POST的,可以在消息队列中检索到,Application是入口
    4. 如果自己画,必须在画完后通知操作系统,并终止后续事件,但未看到对应的代码
      

  14.   

    to:budi
    多谢你的回答,我会往这个方向寻找答案!
    如果可以,希望你能指条捷径!
      

  15.   

    刚从外地回来,不好意思直接响应PageControl的OnDrawTab事件自己画标签不就可以了吗?如果你是想子类化PageControl,那就是另外一个概念了!
      

  16.   

    可现在的问题是不能自己做控件继承。
    而用ondrawtab事件的话,那必须把ownerdraw置为true才行啊!但这样的话,看起来效果不好,tab标签和下面的tssheet衔接不协调。还有想请教:子类化pagecontrol如何实现?谢谢!
      

  17.   

    win32下的PageControl确实有点土,建议你下载并安装Jedi的JCL和JVCL,里面
    有多种组件可以取代PageControl,而且界面非常美观。Jedi是由Delphi开发者建立的一个套件集,用于强化VCL:
    http://delphi-jedi.org/子类化PageControl并不复杂,但是是没必要
      

  18.   

    Jedi的代码是公开的,你可以根据需求对其进行修改和定制