22

TreeView.BeginUpdateを追加すると、ツリービューのちらつきが防止されることがわかりましたが、プロジェクトに追加すると、ツリービューのすべてのノードが消えます。なぜそれが発生するのかを誰かに教えてもらえますか。これが、TreeViewを使用したコードスニペットです。 .BeginUpdateおよびTreeView.EndUpdate

  TreeNode treeNode = new TreeNode("Windows");
        treeView1.Nodes.Add(treeNode);
        //
        // Another node following the first node.
        //
        treeNode = new TreeNode("Linux");
        treeView1.Nodes.Add(treeNode);
        //
        // Create two child nodes and put them in an array.
        // ... Add the third node, and specify these as its children.
        //
        TreeNode node2 = new TreeNode("C#");
        TreeNode node3 = new TreeNode("VB.NET");
        TreeNode[] array = new TreeNode[] { node2, node3 };
        //
        // Final node.
        //
        treeNode = new TreeNode("Dot Net Perls", array);
        treeView1.Nodes.Add(treeNode);
4

2 に答える 2

88

Begin / EndUpdate()メソッドは、ちらつきをなくすようには設計されていません。EndUpdate()でちらつきが発生するのは避けられず、コントロールが再描画されます。これらは、ノードの大部分の追加を高速化するように設計されています。これは、すべてのアイテムが再描画を引き起こすため、デフォルトでは遅くなります。それらをforループの内側に配置し、すぐに改善するために外側に移動することで、状況をさらに悪化させました。

それはおそらくあなたの問題を解決するのに十分でしょう。しかし、それを改善することはできます。ちらつきを抑えるには、ダブルバッファリングが必要です。.NET TreeViewクラスは、DoubleBufferedプロパティをオーバーライドし、非表示にします。これは歴史的な事故ですが、ネイティブのWindowsコントロールは、WindowsXP以降ではダブルバッファリングのみをサポートしています。.NETはかつてWindows2000とWindows98をサポートしていました。

最近では、それはもはや正確には関係ありません。TreeViewから独自のクラスを派生させることで元に戻すことができます。プロジェクトに新しいクラスを追加し、以下に示すコードを貼り付けます。コンパイル。ツールボックスの上部からフォームに新しいコントロールをドロップし、既存のTreeViewを置き換えます。特にスクロールすると、その影響は非常に顕著になります。

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

class BufferedTreeView : TreeView {
    protected override void OnHandleCreated(EventArgs e) {
       SendMessage(this.Handle, TVM_SETEXTENDEDSTYLE, (IntPtr)TVS_EX_DOUBLEBUFFER, (IntPtr)TVS_EX_DOUBLEBUFFER);
        base.OnHandleCreated(e);
    }
    // Pinvoke:
    private const int TVM_SETEXTENDEDSTYLE = 0x1100 + 44;
    private const int TVM_GETEXTENDEDSTYLE = 0x1100 + 45;
    private const int TVS_EX_DOUBLEBUFFER = 0x0004;
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
}
于 2012-04-28T14:11:59.880 に答える
2

あなたが私のように新しく、vb.netでそれを必要とするなら、ここに@HansPassantの答えがあります。使ってみましたが、その変化は目覚ましいです

Protected Overrides Sub OnHandleCreated(ByVal e As EventArgs)
    SendMessage(Me.Handle, TVM_SETEXTENDEDSTYLE, CType(TVS_EX_DOUBLEBUFFER, IntPtr), CType(TVS_EX_DOUBLEBUFFER, IntPtr))
    MyBase.OnHandleCreated(e)
End Sub

Private Const TVM_SETEXTENDEDSTYLE As Integer = &H1100 + 44
Private Const TVM_GETEXTENDEDSTYLE As Integer = &H1100 + 45
Private Const TVS_EX_DOUBLEBUFFER As Integer = &H4
<DllImport("user32.dll")>
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wp As IntPtr, ByVal lp As IntPtr) As IntPtr
End Function
于 2020-05-27T10:49:02.240 に答える