首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

ListBox透明有关问题

2013-08-11 
ListBox透明问题interfaceusesWindows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialog

ListBox透明问题



interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
  StdCtrls; 

type 
  TTransparentListBox = class(TListBox)
  private 
    { Private declarations } 
  protected 
    { Protected declarations } 
    procedure CreateParams(var Params: TCreateParams); override; 
    procedure WMEraseBkgnd(var Msg: TWMEraseBkgnd); message WM_ERASEBKGND; 
    procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); 
      override; 
  public 
    { Public declarations } 
    constructor Create(AOwner: TComponent); override; 
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; 
  published 
    { Published declarations }
    property Style default lbOwnerDrawFixed; 
    property Ctl3D default False; 
    property BorderStyle default bsNone; 
  end; 



implementation 

constructor TTransparentListBox.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Ctl3D       := False;
  BorderStyle := bsNone;
  Style       := lbOwnerDrawFixed;  // changing it to lbStandard results
  // in loss of transparency
end;

procedure TTransparentListBox.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle or WS_EX_TRANSPARENT;
end;

procedure TTransparentListBox.WMEraseBkgnd(var Msg: TWMEraseBkgnd);
begin
  Msg.Result := 1;           // Prevent background from getting erased
end;

procedure TTransparentListBox.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
var
  tlbVisible: Boolean;
begin
  tlbVisible := (Parent <> nil) and IsWindowVisible(Handle);  // Check for   visibility


  if tlbVisible then ShowWindow(Handle, SW_HIDE);             // Hide-Move-Show    strategy
  inherited SetBounds(ALeft, ATop, AWidth, AHeight);          //  to prevent   background
  if tlbVisible then ShowWindow(Handle, SW_SHOW);             //  from   getting copied
end;

procedure TTransparentListBox.DrawItem(Index: Integer; Rect: TRect;
  State: TOwnerDrawState);
var
  FoundStyle: TBrushStyle;
  R: TRect;
begin
  FoundStyle := Canvas.Brush.Style;       // Remember the brush style

  R := Rect;                                     // Adapt coordinates of drawing   rect
  MapWindowPoints(Handle, Parent.Handle, R, 2);  //  to parent's coordinate   system
  InvalidateRect(Parent.Handle, @R, True);   // Tell parent to redraw the    item Position
  Parent.Update;                             // Trigger instant redraw   (required)

  if not (odSelected in State) then
  begin  // If an unselected line is being      handled
    Canvas.Brush.Style := bsClear;  //   use a transparent background
  end
  else
  begin                          // otherwise, if the line needs to be     highlighted,
    Canvas.Brush.Style := bsSolid;  //   some colour to the brush is       essential
  end;

  inherited DrawItem(Index, Rect, State); // Do the regular drawing and give   component users


  //  a chance to provide an    OnDrawItem handler

  Canvas.Brush.Style := FoundStyle;  // Boy-scout rule No. 1: leave site as   you found it
end;


end.


参照网上的一段ListBox透明的代码,发现一个问题,在ListBox有数据时,的确可以整个ListBox透明,但是如果没数据不执行DrawItem则不会透明,有没有什么办法让ListBox在没数据的时候也可以透明
[解决办法]
不一定非得朝一个方向走,或都可以初始化时有一个默认项,都可以!
[解决办法]
可以参考下 伴水大牛的 《屏幕画板》 里面有关透明的

应该是截屏然后画到窗体上给人假象是透明的。

http://topic.csdn.net/u/20110331/02/D6330B1C-B4B3-4DF1-836F-CB08B48EDFE9.html#r_73340803

[解决办法]
从源码看,在WMPaint中对没数据的情况作了特殊处理,具体代码如下:

procedure TCustomListBox.WMPaint(var Message: TWMPaint);

  procedure PaintListBox;
  var
    DrawItemMsg: TWMDrawItem;
    MeasureItemMsg: TWMMeasureItem;
    DrawItemStruct: TDrawItemStruct;
    MeasureItemStruct: TMeasureItemStruct;
    R: TRect;
    Y, I, H, W: Integer;
{$IF DEFINED(CLR)}
    LMessage: TMessage;
    LMeasureItemBuf: IntPtr;
    LDrawItemBuf: IntPtr;
{$IFEND}
  begin
    if Items.Count = 0 then
    begin
      { Just fill it in with the color }
      with TBrush.Create do
      try
        Color := Self.Color;
        FillRect(Message.DC, ClientRect, Handle); //当没有数据时,这段代码往界面上填了东西
      finally
        Free;
      end;
      Exit;
    end;


//...........................


所以,解决办法是重写消息事件

procedure WMPaint(var Message: TWMPaint); message WM_PAINT;

在里面判断如果Items.Count=0,则触发父窗体的重绘,否则,调用继承的方法。

热点排行