gpt4 book ai didi

delphi - 使用自定义绘图时Delphi ListView 控件是否存在错误?

转载 作者:行者123 更新时间:2023-12-03 14:37:07 35 4
gpt4 key购买 nike

QC#101189

我正在尝试按照 NGLN's answer to another SO question 的建议在 Delphi TListView 中自定义绘制进度条。除了使用 Vista 中引入的新资源管理器主题绘制时与热跟踪的交互之外,这工作得很好。

热跟踪绘图和 Delphi 自定义绘图事件似乎相互干扰。例如,我看到的输出类型如下所示:

enter image description here

第 1 列中的文本应为第 3 项,但已被删除。它看起来像是 ListView 控件的 Delphi 包装器中的一个错误,但同样可能是我做错了什么!

尽管我一直在 XE2 中开发此功能,但在 2010 年以及可能的 XE 中也会出现相同的行为。

以下是重现此行为的代码:

Pascal 文件

unit Unit1;

interface

uses
Windows, Classes, Controls, Forms, CommCtrl, ComCtrls;

type
TForm1 = class(TForm)
ListView: TListView;
procedure FormCreate(Sender: TObject);
procedure ListViewCustomDrawSubItem(Sender: TCustomListView;
Item: TListItem; SubItem: Integer; State: TCustomDrawState;
var DefaultDraw: Boolean);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
ListView.RowSelect := True;
ListView.Items.Add.Caption := 'Item 1';
ListView.Items.Add.Caption := 'Item 2';
ListView.Items.Add.Caption := 'Item 3';
end;

procedure TForm1.ListViewCustomDrawSubItem(Sender: TCustomListView;
Item: TListItem; SubItem: Integer; State: TCustomDrawState;
var DefaultDraw: Boolean);
var
R: TRect;
begin
DefaultDraw := False;
ListView_GetSubItemRect(Sender.Handle, Item.Index, SubItem, LVIR_BOUNDS, @R);
Sender.Canvas.MoveTo(R.Left, R.Top);
Sender.Canvas.LineTo(R.Right-1, R.Bottom-1);
end;

end.

表单文件

object Form1: TForm1
Caption = 'Custom Draw List View Bug'
ClientHeight = 290
ClientWidth = 554
OnCreate = FormCreate
object ListView: TListView
Align = alClient
Columns = <
item
Caption = 'Column 1'
Width = 250
end
item
Caption = 'Column 2'
Width = 250
end>
ViewStyle = vsReport
OnCustomDrawSubItem = ListViewCustomDrawSubItem
end
end

最佳答案

这是针对有缺陷的行为的解决方法,而不是对 VCL 中是否存在错误的问题的答案,以及一些想法。

解决方法是在进行自定义绘制后,将项目绘制周期公共(public)控件分配的设备上下文的背景模式设置为透明:

procedure TForm1.ListViewCustomDrawSubItem(Sender: TCustomListView;
Item: TListItem; SubItem: Integer; State: TCustomDrawState;
var DefaultDraw: Boolean);
var
R: TRect;
begin
if not [CustomDrawing] then // <- If we're not gonna do anything do not
Exit; // fiddle with the DC in any way

DefaultDraw := False;
ListView_GetSubItemRect(Sender.Handle, Item.Index, SubItem, LVIR_BOUNDS, @R);
Sender.Canvas.MoveTo(R.Left, R.Top);
Sender.Canvas.LineTo(R.Right-1, R.Bottom-1);

SetBkMode(Sender.Canvas.Handle, TRANSPARENT); // <- will effect the next [sub]item
end;



在[子]项目绘制周期中,绘制始终以自上而下的方式完成,索引较低的项目会在之前发送NM_CUSTOMDRAW通知指标较高的。当鼠标从一行移动到另一行时,需要重新绘制两行 - 一行失去“热”状态,另一行获得热状态。看起来,当自定义绘图生效时,绘制失去热状态的行会使 DC 处于不希望的状态。向上移动鼠标时这不是问题,因为该项目是最后绘制的。

自定义绘制 ListView 和 TreeView 控件与自定义绘制其他控件不同,并且有些复杂(请参阅: Custom Draw With List-View and Tree-View Controls )。但您可以完全控制整个过程。 VCL 'comctrls.pas' 中 TCustomListView.CNNotifyNM_CUSTOMDRAW 情况中的代码同样复杂。但是,尽管提供了一堆自定义绘图处理程序(其中一半是高级的),您仍然无法控制 VCL 的功能。例如,您无法返回您想要的 CDRF_xxx,或者您无法设置您想要的 clrTextBk。我的偏见是,Delphi ListView 控件中存在错误/设计问题,但我没有什么比寻找解决方法的直觉更具体的了。

关于delphi - 使用自定义绘图时Delphi ListView 控件是否存在错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8192961/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com