Größere Viewupdates



  • Ich hab folgendes problem in Winforms:

    Ich habe eine größere Maske welche wiederum aus mehreren Subcontrols besteht. Z.B. Groupboxen, Panels etc. In diesen befinden sich weitere Controls... Die verschachtelung kann also ziemlich tief gehen. Durch Bestimmte Nutzeraktionen können nun diese Masken umsortiert werden. Controls Verschwinden, Andere Tauchen auf. Controls werden verschoben etc. Das Problem daran ist, das die Reihenfolge in der dies geschieht sichtbar ist. D.H. wenn ich künstlich die Zeit erhöhe in der einzelne Controls relayoutet werden dann ist ist das gut Sichtbar wie dies geschieht. Das sorgt manchmal optisch für ein Flimmern.

    Nun hab ich schon mit sachen wie SuspendLayout und ResumeLayout gespielt. Das nützt gar nix. Da beim Relayouten die ControlPosition, Size etc neu gesetzt wird ist es egal ob SuspendLayout bzw ResumeLayout an oder aus ist, das Control wird sofort beim Setzen der Position/Größe etc neu gezeichnet.

    Der Zweite weg ging über die WinApi mit

    private const int WM_SETREDRAW = 0xB;
        [DllImport("User32")]
        private static extern bool SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
    
        public static void SetRepaint(IntPtr handle, bool enable)
        {
          if (enable)
            SendMessage(handle, WM_SETREDRAW, 1, 0);
          else
            SendMessage(handle, WM_SETREDRAW, 0, 0);
    
        }
    

    Das muss ich zwar auch auf alle Controls der Maske anwenden klappte aber im ersten moment super. Bis ich festgestellt habe das wenn ein Control gerade für WM_SETREDRAW abgemeldet ist und auf invisible gestellt wird. Dies beim neuzeichnen nicht beachtet wird. D.H. ich hab dann Elemente auf meiner Maske die eigentlich Invisible sind aber dennoch gezeichnet werden. Selbst ein Refresh nützt nix, erst wenn ich die Controls wieder explizit auf Visible und Invisble setze funktioniert es.

    Ich hab auch DoubleBuffer auf true etc. Nichts ist wirklich so zufriedenstellend wie ich es mir wünsche. Ich möchte einfach alle Updates ausschalten, dann meine Controls alle Layouten, die Updates wieder anschalten und auf mein oberstes Element ein Refresh aufrufen so das alles korrekt neu gezeichnet wird.

    Hab auch schon diverse Ansätze versucht die Maske auf ein Bitmap zu zeichnen und dieses einzublenden während im Hintergrund upgedated wird. Aber auch das hatte einen kurzen Flimmereffekt. Mir gehen echt langsam die Alternativen aus.



  • Hast du SuspendLayout nur für die Controls die bewegt werden soll verwendet oder auch für den übergeordneten Container?



  • Für alles..., vom obersten Control bis hin zum letzten Child hab ich Suspend Layout gemacht. Habe da auch schon ein Testprojekt erstellt, um zu schauen woran das liegt. Dort hab ich nur 2 Panels mit je einen Label, alles Suspended und dann die Location der Labels geändert. Die werden aber trotz dem sofort aktualisiert.


Log in to reply