-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 エラー メッセージの動作を停止しました)。

2回目の更新

まだ問題を再現できませんでしたが、取り組んでいます。


私は(気が進まないにもかかわらず)コントロールを描画することになりましたが、これは問題なく動作します。

私はまだこの問題を調査し、解決策を思いついたらお知らせします。

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 の中で最もハンサムです。


編集:ピーター・ビロウからの古いアドバイス、これはまだ私の描画コードの一部に含まれています:

あなたはよくある間違いを犯しています: コントロールのFontプロパティを変更すると、control.Canvas.Font. そうではありません。この 2 つはまったく別のエンティティです。がペイント イベントの内部と同一である
ことだけに頼ることができます。ペイントイベント以外で使用するには、次のことを行う必要があります。Canvas.Fontcontrol.Font

control.Canvas.Font := Control.Font;  

キャンバスを測定などに使用する前に。

--
ピーター・ビロウ (TeamB)

于 2013-06-13T14:51:47.090 に答える