2017-02-09 3 views
3

Ich habe ein Multiple TableLayoutPanels auf MDI-Formulare. Jedes Tabellenlayout verfügt über mehrere Steuerelemente (einschließlich ObjectListView) und nur die oberste Einstellung ist auf sichtbar gesetzt.Schwarzer Hintergrund und Artefakte auf ObjectListView, wenn Formular Fokus erhält

Ich implementierte die Lösung wie in dieser SO answer angegeben und es funktioniert hervorragend, wenn Sie ein Formular zum ersten Mal öffnen, da kein Flimmern auf den untergeordneten Steuerelementen des Layouts während der Größenänderung ist.

Ich habe auch:

protected override void OnShown(EventArgs e) 
    { 
     base.OnShown(e); 

     foreach (CoTableLayoutPanel tlp in this.Controls) 
     { 
      if (tlp != null) 
      { 
       tlp.BeginUpdate(); 
       tlp.Size = firstLayout.Size; 
       tlp.EndUpdate(); 
      } 
     } 
    } 

ich die oben tun, so dass, wenn ich Layouts innerhalb des Formulars wechseln alle sind sie schon die richtige Größe und vermeide ich flackernde weiter, während die Größenänderung. Das funktioniert auch gut.

Wenn ich jedoch ein ObjectListView Steuerelement auf diesem abgeleiteten Tabellenlayout habe, und ich zwischen den Formen wechseln, wird das Steuerelement teilweise gezeichnet (vor allem der Rahmen), ein schwarzer Hintergrund wird schnell angezeigt und auch die letzte Spalte wird jedes Mal neu skaliert (Spalte FillsFreeSpace Eigentum).

Wenn ich den Standard TableLayoutPanel verwende, verhält sich das Listensteuerelement wie erwartet, dh. keine Artefakte, kein schwarzer Hintergrund, keine Spaltengröße. Allerdings bekomme ich das flackern zurück, wenn ich das Formular öffne.

Die ObjectListView hat Eigenschaften wie Invalidate und Refresh, und ich habe versucht, diese auf der OnGotFocus Methode des Formulars aufzurufen. Das Problem besteht immer noch.

Ist dies ein Problem der ObjectListView oder kann ich das Problem aus dem abgeleiteten Tabellenlayout beheben?

EDIT

Das Problem mit dieser Methode verursacht wird:

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

diese Methode kommentiert geführte Maßnahmen werden die ObjectListView Arbeit wie erwartet, aber die flackernden kehrt machen.

Eine Umgehung der oben genannten Methode?

Antwort

0

Was als schwarz erscheint, ist nur der unbemalte Teil des Fensters. Wenn Sie viele Steuerelemente in einem Formular haben, dauert es bei der Neuüberstreichung genügend Zeit, um erkennbare Artefakte zu erzeugen. Wenn Sie ein mehrschichtiges Fenster verwenden, wird es schwarz, wenn Sie die Opacity- oder TransparencyKey-Eigenschaft verwenden. Wenn Sie das nicht tun, dann neigt das Artefakt dazu, viel weniger zu beanstanden, weil die unbemalten Teile dazu neigen, weiß zu sein.

Die meisten Programmierer nehmen an, dass es ein Flicker-Problem ist, aber es ist nicht und die DoubleBuffered-Eigenschaft kann es nicht lösen. Unterdrückend würde es Doppelpufferung alle der Kontrollen erfordern, die den gleichen Puffer verwenden. Etwa der Ansatz von WPF.

Doppel-Pufferung alles ist, was das WS_EX_COMPOSITED-Stil-Flag tut. Rein vom Betriebssystem gemacht, .NET ist nicht beteiligt. Es ist eine frühe Version von Aero, zuerst auf XP verfügbar. Das Betriebssystem erstellt eine Bitmap für das Toplevel-Fenster und weist seine Steuerelemente an, in diese Bitmap statt direkt in den Video-Framebuffer zu zeichnen. Wenn das Gemälde fertig ist, blitzt es die Bitmap in einem Schlag zum Framebuffer. Macht das Bild nicht schneller, aber der Benutzer empfindet es als sehr glatt.Wenn Sie jetzt die DoubleBuffered-Eigenschaft verwenden, möchten Sie diese deaktivieren.

Ich entdeckte die Technik für Winforms BTW, veröffentlichte es zuerst in einem Forum Post in den MSDN-Foren, vor 10 Jahren bereits. Es wurde viele, viele Male seitdem kopiert, wie ein Lauffeuer verbreitet. Ich habe nicht viel negatives Feedback bekommen, es löst das Problem für die überwiegende Mehrheit der Programmierer. Der einzige Unruhestifter, den ich kenne, ist TabControl, speziell wenn es zu viele Registerkarten hat und die linken/rechten Navigationszeichen anzeigt. Sein Visual Styles Renderer war nie ein Problem, wenn diese Glyphen auftauchen, beginnt er sich immer wieder neu zu streichen. Sieht aus wie ein sehr schnelles Flackern, du kannst es nicht verpassen. Einfach zu arbeiten.

Also nein, vorantreiben und meine Lösung verwenden. Es ist eine gute Sache und es wäre sehr untrivial. Sie müssten WPF neu erfinden, um es komplett zu eliminieren, indem Sie fensterlose Steuerelemente verwenden, die sich auf der Oberfläche des übergeordneten Fensters zeichnen. VB6 hat das getan, ein Grund, warum VB6 UI so alt aussieht. Ersetzen von Steuerelementen mit Code können Sie auch dort (Label und PictureBox sind besonders verschwenderisch), aber das neigt dazu, eine Menge Code zu nehmen und Sie können unmöglich die 3 Zeilen Code-Lösung zu schlagen :)

+0

Vielen Dank für die Erklärung. –

Verwandte Themen