现在我自己写了一个控件。
 
Tmycontrol=class(TCustomControl)
    private
      FMemoryBitmap: array [0..1] of TBitmap;
      FTopImg:array [0..1] of TBitmap;
      FBottomImg:array [0..1] of TBitmap;
      FMiddleImg:array [0..1] of TBitmap;
      FOwnerForm:TForm;
      FSpetPos:Integer;
    protected
      procedure  Paint; override;
      procedure  MouseDown(Button: TMouseButton; Shift: TShiftState;X, Y: Integer); override;
   public
      constructor Create(AOwner: TComponent); override;
      destructor  Destroy; override;
      property    OwnerForm:TForm read FOwnerForm write FOwnerForm;
      property    SpetPos:Integer read FSpetPos write FSpetPos;
    end;
然后Create和paint时间重写如下constructor Tmycontrol.Create(AOwner: TComponent);
var
  I:Integer;
begin
  inherited;
  FOwnerForm:=nil; //
  FSpetPos:=75;  FMemoryBitmap[0]:=TBitmap.Create;
  FMemoryBitmap[1]:=TBitmap.Create;  FTopImg[0]:=TBitmap.Create;
  FTopImg[1]:=TBitmap.Create;
  FTopImg[0].Handle:=LoadBitmap(hInstance,'LeftBarTop0'); //LeftBarTop0          BITMAP "image\leftbar_top0.bmp" 黑色
  FTopImg[1].Handle:=LoadBitmap(hInstance,'LeftBarTop1');//灰色  FBottomImg[0]:=TBitmap.Create;
  FBottomImg[1]:=TBitmap.Create;
  FBottomImg[0].Handle:=LoadBitmap(hInstance,'LeftBarBottom0');
  FBottomImg[1].Handle:=LoadBitmap(hInstance,'LeftBarBottom1');  FMiddleImg[0]:=TBitmap.Create;
  FMiddleImg[1]:=TBitmap.Create;
  FMiddleImg[0].Handle:=LoadBitmap(hInstance,'LeftBarMiddle0');
  FMiddleImg[1].Handle:=LoadBitmap(hInstance,'LeftBarMiddle1');
  FMemoryBitmap[0].Width:=FTopImg[0].Width;
  FMemoryBitmap[0].Height:=1;  for I:=0 to  FTopImg[0].Width-1 do
      FMemoryBitmap[0].Canvas.Pixels[I,0]:=
         FTopImg[0].Canvas.Pixels[I,FTopImg[0].Height-1];  FMemoryBitmap[1].Width:=FTopImg[1].Width;
  FMemoryBitmap[1].Height:=1;
  for I:=0 to  FTopImg[1].Width-1 do
      FMemoryBitmap[1].Canvas.Pixels[I,0]:=
         FTopImg[1].Canvas.Pixels[I,FTopImg[1].Height-1];
  //change Cursor
  Cursor:=crSizeWE;
//  Self.Width
  Width:= FTopImg[0].Width;
  if FOwnerForm<>nil then
    FOwnerForm:=nil;
end;paintprocedure Tmycontrol.Paint;
var
   Idx:Integer;
begin
   if (FOwnerForm<>nil) then
       begin
       Idx:=ord(FOwnerForm.Active);// Idx:=1
       Canvas.StretchDraw(ClientRect,FMemoryBitmap[Idx]);
       Canvas.Draw(0,0,FTopImg[Idx]);
       Canvas.Draw(0,Height-FBottomImg[Idx].Height,FBottomImg[Idx]);
       Canvas.Draw(0,FSpetPos,FMiddleImg[Idx]);
       end;
end;现在就出现一个问题,也就是我用到这个控件的窗体在失焦和获得焦点切换的时候,说白了就是2个窗体一个点一下的情况,控件的某些地方就会出现白色的条,未被填充,瞬间,因为上面的LoadBitmap的图片都是灰黑色的,所以瞬间的白条很刺眼。
我感觉应该是paint语句中
Idx:=ord(FOwnerForm.Active);// Idx:=1
       Canvas.StretchDraw(ClientRect,FMemoryBitmap[Idx]);
       Canvas.Draw(0,0,FTopImg[Idx]);
       Canvas.Draw(0,Height-FBottomImg[Idx].Height,FBottomImg[Idx]);
       Canvas.Draw(0,FSpetPos,FMiddleImg[Idx]);
这里的问题,可是要怎么写才能不闪出白条呢?有没有高手来解决?

解决方案 »

  1.   

    经我 老板,带我那个师傅说,叫我看看 boublebuffer 的确 该考虑双缓冲,问问论坛人有什么好资料没有?
      

  2.   

    TForm 的 DoubleBuffered 主要是为了解决时闪烁问题
      

  3.   

    所谓双缓冲,就是对于复杂的图形绘制,为了减少闪烁的效果,先将图形在内存中绘制,并最终将结果返回。因为复杂的图形绘制动作没有呈现到界面上,最终看到的,只是缓冲返回的结果,对于使用者来说,图形的展示是比较平缓的。一般情况下,使用双缓冲可以这样:this.SetStyle(ControlStyles.OptimizedDoubleBuffer,true),this.DoubleBuffered = true,但是,也经常要手动地绘制并使用双缓冲。下面就介绍手动设置双缓冲。两个重要的类
    BufferedGraphicsContext  _bufferedGraphicsContext
    BufferedGraphicsContext是类,提供创建图形缓冲区的方法,该缓冲区可用于双缓冲。而后者是它的实例的名称。
    BufferedGraphics  _bufferedGraphics
    BufferedGraphics是类,为双缓冲提供图形缓冲区。而后者是它的实例的名称,是否明白中文解释的意思不重要,重要的是找到例子或使用方法。
    获取当前的BufferedGraphicsContext
    _bufferedGraphicsContext  = BufferedGraphicsManager.Current
    BufferedGraphicsManager提供对应用程序域的主缓冲图形上下文对象的访问。而Current就是获取当前应用程序域的BufferedGraphicsContext,这个对象实例交给
    _bufferedGraphicsContext设置,可以在构造函数时设置
    _bufferedGraphicsContext.MaximumBuffer = new Size(this.Width + 1, this.Height + 1);
    _bufferedGraphics = _bufferedGraphicsContext.Allocate(this.CreateGraphics(), ClientRectangle);
    MaximumBuffer是用来设置要使用的缓冲区的最大大小,如果缓冲区过小,而要画的内容过大,就不能完全展示内容了
    Allocate使用指定的 System.Drawing.Graphics 的像素格式,创建指定大小的图形缓冲区。注意大小的变化时应该及时同步缓冲区大小,在OnSizeChanged事件上面设置
    _bufferedGraphicsContext.MaximumBuffer = new Size(this.Width + 1, this.Height + 1);
    if (_bufferedGraphicsContext != null)
    _bufferedGraphicsContext.Dispose();
    _bufferedGraphics = _bufferedGraphicsContext.Allocate(this.CreateGraphics(), 
    ClientRectangle);
    因为源控件的大小发生变化后,而缓冲区不同了,所画的内容也将会不用的。OnPaint方法的调用
    protected override void OnPaint(PaintEventArgs e)
    {
    DoSomePaintAction(_bufferedGraphics.Graphics);                
    _bufferedGraphics.Render(e. Graphics);
    }
    Render将图形缓冲区的内容写入指定的 System.Drawing.Graphics 对象。
    而_bufferedGraphics.Graphics是一个Graphics的实例,DoSomePaintAction所做的动作就像平常的Paint一样,最后_bufferedGraphics.Render可以由缓冲区做的处理都反映到当前的Graphics实例上面。重要链接资源
    下面的链接地址,介绍了一个DoubleBuffer的应用例子,说明得很深刻,有很好的借鉴作用。
    http://www.codeproject.com/KB/graphics/DoubleBuffering.aspx
      

  4.   

    TForm 的 DoubleBuffered 主要是为了解决时闪烁问题
      

  5.   

    给form1.DoubleBuffered := true;
      

  6.   

    我把只要继承TCustomControl的组件都加上了 self.doubleBuffered:=true;
    解决了一部分问题,新问题又发现了,
    在窗体resize,也就是我拖动窗体大小的时候,因为我这个控件有点儿类似于scrollbar,所以一拖动窗体大小,就出现大白块,汗,哈哈,郁闷
      

  7.   

    我现在只有好好的看看businessSkinForm的pas了,哇,好长呀。
      

  8.   

    什么持久化,详细说一下,我网上搜索 都是java orm hibernate  前段时间搞了个java ssh项目的
    这里的持久化是什么东西?
      

  9.   

        绘制的时候,再创建一个临时的TBitmap对象(或者一个私有的对象),先将所有的图片绘制到这个对象上,然后在Draw到控件的Canvas上。大概是这样的:  Tmycontrol=class(TCustomControl)
      private
        m_bmpBuffer: TBitmap;
      //....  end;procedure OnPaint;
    begin
      if not Assigned(m_bmpBuffer) then
      begin
        m_bmpBuffer = TBitmap.Create;
        m_bmpBuffer.Width := Self.Width;
        m_bmpBuffer.Height:= Self.Height;    // Draw image on buffer(如果图像不经常变的话,可以这么做,如果变换,就把end这个放到下面或者在需要变的时候自己画)
        with m_bmpBuffer.Canvas do
        begin
          Draw(0,0,FTopImg[Idx]);
          Draw(0,Height-FBottomImg[Idx].Height,FBottomImg[Idx]);
          Draw(0,FSpetPos,FMiddleImg[Idx]);
          //....
        end;
      end;  // Transfer to screen DC
      Bitblt(Self.Canvas.Handle, 0, 0, Self.Width, Self.Height,
             m_bmpBuffer.Canvas.Handle, 0, 0, SRCCOPY);
    end;
      

  10.   

    这里的持久化是什么东西?------------------------
    就是具有将自己保存起来,以后有能恢复。简单的说,就是具有将自己的信息写到文件中,以后能读出来再恢复成原来状态。所有从TPersist继承下来的类,都具有持久化。