我写了个圆角的panel组件,重绘的时候会一直闪烁,设计期和运行期都是如此,请大家看看!
这是Paint事件
procedure TRoundPanel.Paint;
var
  rect:TRect;
  i:integer;
  tmpPS:PAINTSTRUCT;
  myHDC:HDC;
begin
  if FRoundPanel then
    begin
    rect:=self.ClientRect;
    myHDC:=BeginPaint(Handle,tmpPS);
    for i:=5 downto 1 do
    begin
      canvas.Pen.Color:= BaseColor+FStepColor;
      canvas.RoundRect(rect.Left+i,rect.Top+i,rect.Right-i,rect.Bottom-i,FRoundWidth,FRoundHeight);
    end;
    RoundClientArea;
    EndPaint(Handle,tmpPS);
  end;
  inherited Paint;
end;
//是下面这个事件导致闪烁
procedure TRoundPanel.RoundClientArea;
var
  rect:Trect;
  rgn:Hrgn;
begin
  rect:=self.ClientRect;
  Rgn:=CreateRoundRectRgn(rect.Left,rect.Top,rect.Right,rect.Bottom,FRoundWidth,FRoundHeight);
  setWindowRgn(self.Handle,rgn,true);(是这个语句导致的)
end;

解决方案 »

  1.   

    你的Paint方法调用了RoundClientArea;
    而RoundClientArea调用了setWindowRgn(self.Handle,rgn,true);
    而setWindowRgn的第三个参数为True,所以它立刻重绘,于是Paint方法又被调用.....这样就处于不停的重绘状态了
      

  2.   

    {曲线化控件}procedure MakeRound(mControl: TWinControl; Width, height: integer; style: byte);
    var
      Rgn: HRGN;
      left, top, right, bottom: integer;
    begin
      top := -height;
      left := -width;
      right := mControl.BoundsRect.Right + width;
      bottom := mControl.BoundsRect.bottom + height;
      if (style and 1) > 0 then
      begin
        top := top + height;
        left := left + width;
      end;
      if (style and 2) > 0 then
      begin
        if (style and 1) = 0 then
          left := left + width;
        bottom := bottom - height;
      end;
      if (style and 4) > 0 then
      begin
        if (style and 2) = 0 then
          bottom := bottom - height;
        right := right - width;
      end;
      if (style and 8) > 0 then
      begin
        if (style and 4) = 0 then
          right := right - width;
        if (style and 1) = 0 then
          top := top + height;
      end;
      Rgn := CreateRoundRectRgn(left, top, right, bottom, Width, height);
      SetWindowRgn(mControl.Handle, rgn, true);
    end;
      

  3.   

    setWindowRgn(self.Handle,rgn,true)这句话的第3个参数即使改为false也不行,同样的问题。
    我把源代码贴出来大家共同探讨一下。其实我觉得写过控件的应该觉得很简单。unit RoundPanel;interfaceuses
      SysUtils, Classes, Controls, ExtCtrls,graphics,windows,messages,Themes;type
      TRoundPanel = class(TPanel)
      private
        FStepColor:int64;
        FBaseColor:TColor;
        FRoundPanel:boolean;
        FRoundWidth:integer;
        FRoundHeight:integer;
        procedure SetStepColor(StepColor:int64);
        procedure SetBaseColor(BaseColor:TColor);
        procedure SetRoundPanel(RoundPanel:boolean);
        procedure SetRoundWidth(RoundWidth:integer);
        procedure SetRoundHeight(RoundHeight:integer);
        procedure RoundClientArea;
      protected
        procedure WMEraseBkgnd(var Message: TWMEraseBkgnd);
            message WM_ERASEBKGND;
        procedure Paint;override;
      public
        procedure PaintRound;
        constructor Create(AOwner: TComponent);override;
      published
        property StepColor:int64 read FStepColor Write SetStepColor  default 1000000;
        property BaseColor:TColor read FBaseColor write SetBaseColor default clBtnFace;
        property RoundPanel:boolean read FRoundPanel Write SetRoundPanel default false;
        property RoundWidth:integer read FRoundWidth write SetRoundWidth default 0;
        property RoundHeight:integer read FRoundHeight write SetRoundHeight default 0;
      end;procedure Register;implementationprocedure Register;
    begin
      RegisterComponents('Samples', [TRoundPanel]);
    end;constructor TRoundPanel.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);end;procedure TRoundPanel.Paint;
    var
      rect:TRect;
      i:integer;
      tmpPS:PAINTSTRUCT;
      myHDC:HDC;
    begin
      inherited Paint;
      if FRoundPanel then
        begin
        rect:=self.ClientRect;
        myHDC:=BeginPaint(Handle,tmpPS);
        for i:=5 downto 1 do
        begin
          canvas.Pen.Color:= BaseColor+FStepColor;
          canvas.RoundRect(rect.Left+i,rect.Top+i,rect.Right-i,rect.Bottom-i,FRoundWidth,FRoundHeight);
        end;
        //RoundClientArea;
        EndPaint(Handle,tmpPS);
      end;end;procedure TRoundPanel.SetStepColor(StepColor:int64);
    begin
      FStepColor:=StepColor;
    end;procedure TRoundPanel.SetBaseColor(BaseColor:TColor);
    begin
      FBaseColor:=BaseColor;
    end;procedure TRoundPanel.SetRoundPanel(RoundPanel:boolean);
    begin
      FRoundPanel:=RoundPanel;
    end;procedure TRoundPanel.SetRoundWidth(RoundWidth:integer);
    begin
      FRoundWidth:=RoundWidth;
    end;procedure TRoundPanel.SetRoundHeight(RoundHeight:integer);
    begin
      FRoundHeight:=RoundHeight;
    end;procedure TRoundPanel.WMEraseBkgnd(var Message: TWMEraseBkgnd);
    begin
        Message.Result := 0;
    end;procedure TRoundPanel.RoundClientArea;
    var
      rect:Trect;
      rgn:Hrgn;
    begin
      rect:=self.ClientRect;
         Rgn:=CreateRoundRectRgnrect.Left,rect.Top,rect.Right,rect.Bottom,FRoundWidth,FRoundHeight);
      setWindowRgn(self.Handle,rgn,false);
    end;procedure TRoundPanel.PaintRound;
    begin
      RoundClientArea;
      paint;
    end;end.
    希望高手们给出具体点的建议来!
      

  4.   

    这样开发出来的也不是圆角 Panel 啊,其实只要用
    var
    HT: THandle;HT := CreateRoundRectRgn(0, 0, Width, Height, RX, RY);//RX,RY就是圆角控制,integer;SetWindowRgn(Handle, HT, True);然后用 Pen 的大小来描一下边框就很好了。不用那么复杂;以上纯属个人之见!!
      

  5.   

    应该在Panel的OnResize事件中SetWindowRgn
      

  6.   

    这东西做成控件没有多大的意义,还不如像 ahjoe(强哥) 所说的那样做