-3

我有一些动态创建的列表视图组件,其中包含数十个项目和超过 24 列。

onCustomdrawXXX当我在事件或列表视图的事件中设置一些画布属性(例如,brush.color)时onAdvancedCustomDrawXXX,应用程序变得不稳定并崩溃。

首先,开始出现一些视觉故障(标题未绘制,列表视图中的伪影),然后应用程序无响应并崩溃。

我也能够通过设计时创建的列表视图重现该问题。

我已阅读内容,但我不想拥有控件。

有人可以帮我解决这个问题吗?

更新:代码

procedure TMainForm.listview1AdvancedCustomDrawItem(
  Sender: TCustomListView; Item: TListItem; State: TCustomDrawState;
  Stage: TCustomDrawStage; var DefaultDraw: Boolean);
begin

  FDefaultCanvasColor := clWindow;

  if Item.SubItems[1] = 'Test' then begin
     FDefaultCanvasColor := $66CCFFFF;
  end;

  // if i remove this line, everything is OK
  (Sender As TCustomListView).Canvas.Brush.Color := FDefaultCanvasColor;

end;

上面显示了视觉效果(控件变得无响应,控件上的伪影),然后崩溃(YourApp.exe 停止工作标准 Windows 错误消息)。

第二次更新

我还不能重现这个问题,但我正在努力。


我最终拥有了控件(尽管我不情愿),它可以正常工作。

我仍然会研究这个问题,如果我想出解决方案会让你知道。

4

2 回答 2

3

我在更改 Canvas.Font 时遇到了类似的问题。与其说是崩溃,不如说是一些绘图伪影和不当行为。事实证明,在绘图事件处理程序退出后,TListView 没有正确清理所有内容,也没有正确报告给 Windows。这是因为当绘图事件处理程序正在运行时,TListView 实际上禁用了一些内部 TCanvas 事件处理程序(TBrush.OnChange、TFont.OnChange 等),这些处理程序通常会在进行更改时被调用。这些事件处理程序设置了 TListView 寻找的标志。很明显,没有事件处理程序意味着没有设置标志。我最终做的是在我的绘图事件处理程序结束时手动调用 TCanvas 事件处理程序,问题就消失了。

我现在不在我的代码附近,但我稍后会发布一个示例。

于 2013-06-13T14:50:47.167 回答
2

我建议复制您的表格,然后将其撕掉,直到它起作用为止。然后继续前进,找出是什么破坏了它。

因为当我有代码时:

procedure TForm1.FormCreate(Sender: TObject);

    procedure Add(Caption: string; SubItems: array of string);
    var
        item: TListItem;
        i: Integer;
    begin
        item := ListView1.Items.Add;
        item.Caption := Caption;
        for i := Low(SubItems) to High(SubItems) do
            item.SubItems.Add(SubItems[i]);
    end;
begin
    Add('I''ve', ['got',  'soul'            ]);
    Add('but',   ['i''m', 'not', 'a solider']);

    Add('I''ve', ['got',  'Test'            ]);
    Add('but',   ['i''m', 'not', 'a tester' ]);
end;

与绘图代码:

procedure TForm1.ListView1AdvancedCustomDrawSubItem(
  Sender: TCustomListView; Item: TListItem; SubItem: Integer;
  State: TCustomDrawState; Stage: TCustomDrawStage;
  var DefaultDraw: Boolean);
begin
    FDefaultCanvasColor := clWindow;

    if Item.SubItems[1] = 'Test' then
     FDefaultCanvasColor := $66CCFFFF;

    // if i remove this line, everything is OK
    (Sender As TCustomListView).Canvas.Brush.Color := FDefaultCanvasColor;
end;

它呈现得很好:

在此处输入图像描述

虽然,这Delphi 5。Delphi 中最帅的。


编辑:来自 Peter below的旧建议,它仍然在我的一些绘图代码中:

您犯了一个常见错误:您假设更改控件Font属性将对control.Canvas.Font. 它没有,这两个是完全不同的实体。
您只能依靠Canvas.Fontcontrol.Font内部绘制事件相同。对于绘画事件之外的任何用途,您必须执行以下操作:

control.Canvas.Font := Control.Font;  

在使用画布进行测量等之前。

——
彼得下(B队)

于 2013-06-13T14:51:47.090 回答