ListBox透明问题

飞牛 2011-06-17 03:39:55


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在没数据的时候也可以透明
...全文
385 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
oushengfen 2013-08-10
  • 打赏
  • 举报
回复
问题解决,为什么一直不结题呢?
飞牛 2011-06-18
  • 打赏
  • 举报
回复
谢谢xinghun61,问题解决了
在Items.Count=0时直接贴图到整个区域不同样也是透明效果么,以前一直都没转过弯来
xinghun61 2011-06-18
  • 打赏
  • 举报
回复
从源码看,在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,则触发父窗体的重绘,否则,调用继承的方法。
浩南_哥 2011-06-17
  • 打赏
  • 举报
回复
可以参考下 伴水大牛的 《屏幕画板》 里面有关透明的

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

http://topic.csdn.net/u/20110331/02/D6330B1C-B4B3-4DF1-836F-CB08B48EDFE9.html#r_73340803
浩南_哥 2011-06-17
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 hongqi162 的回复:]

没有数据的时候让它不可见
[/Quote]
确实牛。。。。。。
山东蓝鸟贵薪 2011-06-17
  • 打赏
  • 举报
回复
试试再说.............
飞牛 2011-06-17
  • 打赏
  • 举报
回复
一直都用一个比较邪恶的做法,就是在Clear的时候加上一个 Item.add(‘’)而后面添加数据的时候自动把这条删掉,但是治标不治本,想找个治本的办法
babydog01 2011-06-17
  • 打赏
  • 举报
回复
不一定非得朝一个方向走,或都可以初始化时有一个默认项,都可以!
dinoalex 2011-06-17
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 hongqi162 的回复:]
没有数据的时候让它不可见
[/Quote]

牛....
hongqi162 2011-06-17
  • 打赏
  • 举报
回复
没有数据的时候让它不可见

5,392

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧