我有TListView
一些修改。它包括每行的一些图标(几个,取决于项目),以及如果满足某些条件,则可能会出现一行背景。
它似乎可以正常渲染。但是当我将鼠标移到窗口上时会出现问题,似乎正在重新渲染行,这会产生不必要的延迟,更重要的是,它似乎会干扰可视化。如果我做某事(比如选择一行),它应该只重新绘制。
如何强制它停止(鼠标悬停时似乎刷新行)?目前我正在使用AdvancedCustomDrawItem
绘图。窗口也需要一秒钟才能对项目的选择做出反应,这似乎很乏味。
所以基本上,每一行都有DrawText()
并将图像绘制到Sender.Canvas
. 诚然,这是一个缓慢的进展,但它现在可以工作,如果当我将鼠标悬停在行上时它似乎没有重新绘制行!事实上,如果我使用 Aero 主题,当您将鼠标悬停在它们上方时,这些行会变为黑色。
这是我的事件代码AdvancedCustomDrawItem
:
procedure TfrmJobQueue.ListView1AdvancedCustomDrawItem(Sender: TCustomListView;
Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
var DefaultDraw: Boolean);
const
DT_ALIGN: array[TAlignment] of integer = (DT_LEFT, DT_RIGHT, DT_CENTER);
var
r: TRect;
SL: TStringList;
TypeName: string;
I: Integer;
TypeState: integer;
x1,x2: Integer;
S: string;
begin
if Stage = cdPostPaint then begin
// Ways I tried to avoid it; but failed.
if cdsHot in State then
exit;
if cdsNearHot in State then
exit;
if cdsOtherSideHot in State then
exit;
if cdsMarked in State then
exit;
if cdsIndeterminate in State then
exit;
Sender.Canvas.Brush.Style := bsSolid;
if FRepLines.Items[Item.Index].IsAutoReport then begin
Sender.Canvas.Font.Color := clBlack;
Sender.Canvas.Brush.Color := clSkyBlue;
end else begin
Sender.Canvas.Font.Color := clBlack;
Sender.Canvas.Brush.Color := clWhite;
end;
if cdsSelected in State then begin
Sender.Canvas.Font.Color := clWhite;
Sender.Canvas.Brush.Color := clNavy;
end;
R := Item.DisplayRect(drBounds);
Sender.Canvas.FillRect(R);
Sender.Canvas.Brush.Style := bsClear;
if cdsFocused in State then
DrawFocusRect(Sender.Canvas.Handle, R);
x1 := 0;
x2 := 0;
for i := 0 to TListView(Sender).Columns.Count - 1 do
begin
inc(x2, Sender.Column[i].Width);
r.Left := x1;
r.Right := x2;
if i = 0 then
S := Item.Caption
else
S := Item.SubItems[i-1];
if DT_ALIGN[Sender.Column[i].Alignment] = DT_LEFT then
S := ' ' + S;
DrawText(Sender.Canvas.Handle,
S, length(S), r,
DT_SINGLELINE or DT_ALIGN[Sender.Column[i].Alignment] or
DT_VCENTER or DT_END_ELLIPSIS);
x1 := x2;
end;
r := Item.DisplayRect(drIcon);
SL := TStringList.Create;
SL.CommaText := FRepLines.Value(Item.Index, 'TypeState');
r.Left := Sender.Column[0].Width + Sender.Column[1].Width + Sender.Column[2].Width + Sender.Column[3].Width
+ Sender.Column[4].Width;
for I := 0 to SL.Count - 1 do begin
if GetTypeImagesIndex(SL.Names[I]) = -1 then
continue;
// FRepLines is a collection of items containing more information about each row.
if FRepLines.Value(Item.Index, 'State') <> '1' then begin // no error
TypeName := SL.Names[I];
TypeState := StrToIntDef(SL.Values[TypeName], 0);
// State*Images are TImageList.
if TypeState = 0 then
StateWaitingImages.Draw(Sender.Canvas, r.Left + 17*I, r.Top,
GetTypeImagesIndex(TypeName))
else
StateDoneImages.Draw(Sender.Canvas, r.Left + 17*I, r.Top,
GetTypeImagesIndex(TypeName));
CreateIconToolTip(StrToIntDef(FRepLines.Value(Item.Index, 'RepJob'), -1),
TypeName, r.Left + 17*I, ListView1.ViewOrigin.Y + r.Top,
Format(TranslateString('RepQTypeState'),
[TranslateString(Format('RepQTypeStateN%s', [TypeName])),
TranslateString(Format('RepQTypeState-%d', [TypeState]))]));
end;
end;
end;
end;
代码的一些解释:
该列表是报告列表(报告队列)。我正在介绍“自动报告”(或 UI 中的预定报告)的概念,我想用浅蓝色背景 ( clSkyBlue
) 突出显示它。
除了这个背景之外,它还在状态列上绘制了一些图标,指示报告处于什么阶段,此外,报告的排序格式(PDF、Excel 和 HTML 等格式)以及它是否具有已打印和/或通过电子邮件发送。仅当已订购此类事件时才会出现图标,因此图标的数量是可变的。
等待状态图像是完成状态图像的灰色版本。我还尝试创建一些代码,因此当我将鼠标悬停在特定图标上时,它会显示工具提示消息。
因为代码速度相当慢,我怀疑我做错了什么。