53

DoubleBufferedちらつきが発生しているフォームのコントロールの保護されたプロパティを設定するにはどうすればよいですか?

4

13 に答える 13

90

これは、ダミーのソリューションのより一般的なバージョンです。

リフレクションを使用して保護されたDoubleBufferedプロパティを取得し、それをtrueに設定できます。

:ユーザーがターミナル サービス セッション (リモート デスクトップなど) で実行している場合は、開発者税を支払い、ダブル バッファリングを使用しないでください。ユーザーがリモート デスクトップで実行している場合、このヘルパー メソッドはダブル バッファリングをオンにしません。

public static void SetDoubleBuffered(System.Windows.Forms.Control c)
{
   //Taxes: Remote Desktop Connection and painting
   //http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
   if (System.Windows.Forms.SystemInformation.TerminalServerSession)
      return;

   System.Reflection.PropertyInfo aProp = 
         typeof(System.Windows.Forms.Control).GetProperty(
               "DoubleBuffered", 
               System.Reflection.BindingFlags.NonPublic | 
               System.Reflection.BindingFlags.Instance);

   aProp.SetValue(c, true, null); 
}
于 2008-09-16T21:17:28.110 に答える
69

このスレッドをチェック

その答えの中核を繰り返すと、ウィンドウで WS_EX_COMPOSITED スタイル フラグをオンにして、フォームとそのすべてのコントロールの両方をダブル バッファリングすることができます。スタイル フラグは XP 以降で使用できます。ペイントは速くなりませんが、ウィンドウ全体がオフスクリーン バッファに描画され、一度に画面にブリットされます。目に見える塗装アーティファクトなしで、ユーザーの目に即座に見えるようにします。完全に問題がないわけではありません。一部のビジュアル スタイル レンダラー、特にタブが多すぎる場合の TabControl でグリッチが発生する可能性があります。YMMV。

このコードをフォーム クラスに貼り付けます。

protected override CreateParams CreateParams {
    get {
        var cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;    // Turn on WS_EX_COMPOSITED
        return cp;
    } 
}

この手法と Winform のダブル バッファリング サポートの大きな違いは、Winform のバージョンは一度に 1 つのコントロールでしか機能しないことです。個々のコントロール ペイント自体は引き続き表示されます。これはちらつき効果のように見えることもあります。特に、ペイントされていないコントロールの四角形がウィンドウの背景と著しく対照的である場合です。

于 2008-09-18T01:13:37.427 に答える
18
System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control)
    .GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic |
    System.Reflection.BindingFlags.Instance);
aProp.SetValue(ListView1, true, null);

Ianは、ターミナルサーバーでこれを使用する方法についてさらに情報を持っています。

于 2008-09-16T21:02:02.373 に答える
12
public void EnableDoubleBuffering()
{
   this.SetStyle(ControlStyles.DoubleBuffer | 
      ControlStyles.UserPaint | 
      ControlStyles.AllPaintingInWmPaint,
      true);
   this.UpdateStyles();
}
于 2008-09-16T21:00:19.197 に答える
9

1 つの方法は、ダブル バッファする特定のコントロールを拡張し、コントロールの ctor 内に DoubleBuffered プロパティを設定することです。

例えば:

class Foo : Panel
{
    public Foo() { DoubleBuffered = true; }
}
于 2008-09-16T21:03:48.377 に答える
5

nobugzは、彼のリンクでメソッドのクレジットを取得しています。私は再投稿しています。このオーバーライドをフォームに追加します。

protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;
        return cp;
    }
}

Windows 7 では、コントロールの重いフォームのサイズを変更すると、大きな黒いブロックが表示されていました。コントロールが代わりにバウンスするようになりました! しかし、それはより良いです。

于 2009-10-29T11:25:12.470 に答える
5

コントロールのダブルバッファリングをオンまたはオフにする拡張メソッド

public static class ControlExtentions
{
    /// <summary>
    /// Turn on or off control double buffering (Dirty hack!)
    /// </summary>
    /// <param name="control">Control to operate</param>
    /// <param name="setting">true to turn on double buffering</param>
    public static void MakeDoubleBuffered(this Control control, bool setting)
    {
        Type controlType = control.GetType();
        PropertyInfo pi = controlType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
        pi.SetValue(control, setting, null);
    }
}

使用法 (たとえば、DataGridView を DoubleBuffered にする方法):

DataGridView _grid = new DataGridView();
//  ...
_grid.MakeDoubleBuffered(true);
于 2013-01-11T16:20:17.233 に答える
4

ダブルバッファリングを試す前に、SuspendLayout()/ ResumeLayout()で問題が解決するかどうかを確認してください。

于 2008-09-16T21:05:18.997 に答える
4

この優れたソリューションの vb.net バージョン....:

Protected Overrides ReadOnly Property CreateParams() As CreateParams
    Get
        Dim cp As CreateParams = MyBase.CreateParams
        cp.ExStyle = cp.ExStyle Or &H2000000
        Return cp
    End Get
End Property
于 2016-09-06T07:34:40.760 に答える
4

これにより、追跡するまでの2日間、サードパーティのコントロールで多くの悲しみが生じました.

protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;
        return cp;
    }
}

最近、他のいくつかのコントロールを含むコントロールのサイズを変更/再描画すると、多くの穴 (ドロップ) が発生しました。

WS_EX_COMPOSITED と WM_SETREDRAW を試しましたが、これを使用するまで何も機能しませんでした:

private void myPanel_SizeChanged(object sender, EventArgs e)
{
     Application.DoEvents();
}

それを伝えたかっただけです。

于 2013-06-24T16:03:07.863 に答える
1

コントロールを独自のクラスに継承し、そこにプロパティを設定することもできます。この方法は、すべてのコントロールで同じ設定を頻繁に行う場合にも便利です。

于 2008-09-16T21:03:04.930 に答える
0

フォームに DoubleBuffered を設定するだけで、ここにリストされているすべてのプロパティが自動的に設定されることがわかりました。

于 2008-09-16T21:29:55.943 に答える
-1

FWIW

私の前に来た人々の仕事に基づいて構築:
Dummy's SolutionIan Boyd's SolutionAmo's Solution

SetStyleこれは、リフレクションを使用してPowerShellで経由してダブルバッファリングを設定するバージョンです

function Set-DoubleBuffered{
<#
.SYNOPSIS
Turns on double buffering for a [System.Windows.Forms.Control] object
.DESCRIPTION
Uses the Non-Public method 'SetStyle' on the control to set the three
style flags recomend for double buffering: 
   UserPaint
   AllPaintingInWmPaint
   DoubleBuffer
.INPUTS
[System.Windows.Forms.Control]
.OUTPUTS
None
.COMPONENT  
System.Windows.Forms.Control
.FUNCTIONALITY
Set Flag, DoubleBuffering, Graphics
.ROLE
WinForms Developer
.NOTES
Throws an exception when trying to double buffer a control on a terminal 
server session becuase doing so will cause lots of data to be sent across 
the line
.EXAMPLE
#A simple WinForm that uses double buffering to reduce flicker
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()

$Pen = [System.Drawing.Pen]::new([System.Drawing.Color]::FromArgb(0xff000000),3)

$Form = New-Object System.Windows.Forms.Form
Set-DoubleBuffered $Form
$Form.Add_Paint({
   param(
      [object]$sender,
      [System.Windows.Forms.PaintEventArgs]$e
   )
   [System.Windows.Forms.Form]$f = $sender
   $g = $e.Graphics
   $g.SmoothingMode = 'AntiAlias'
   $g.DrawLine($Pen,0,0,$f.Width/2,$f.Height/2)
})
$Form.ShowDialog()

.LINK
https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.setstyle?view=net-5.0
.LINK
https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.controlstyles?view=net-5.0
#>
   param(
      [parameter(mandatory=$true,ValueFromPipeline=$true)]
      [ValidateScript({$_ -is [System.Windows.Forms.Control]})]
      #The WinForms control to set to double buffered
      $Control,
      
      [switch]
      #Override double buffering on a terminal server session(not recomended)
      $Force
   )
   begin{try{
      if([System.Windows.Forms.SystemInformation]::TerminalServerSession -and !$Force){
         throw 'Double buffering not set on terminal server session.'
      }
      
      $SetStyle = ([System.Windows.Forms.Control]).GetMethod('SetStyle',
         [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance
      )
      $UpdateStyles = ([System.Windows.Forms.Control]).GetMethod('UpdateStyles',
         [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance
      )
   }catch {$PSCmdlet.ThrowTerminatingError($PSItem)}
   }process{try{
      $SetStyle.Invoke($Control,@(
         ([System.Windows.Forms.ControlStyles]::UserPaint -bor
           [System.Windows.Forms.ControlStyles]::AllPaintingInWmPaint -bor
           [System.Windows.Forms.ControlStyles]::DoubleBuffer
         ),
         $true
      ))
      $UpdateStyles.Invoke($Control,@())
   }catch {$PSCmdlet.ThrowTerminatingError($PSItem)}}
}
于 2021-04-26T20:11:23.273 に答える