Laden...

[gelöst] Borderless Window Resize - ruckelig, sehr unschön

Erstellt von 7.e.Q vor 14 Jahren Letzter Beitrag vor 14 Jahren 5.312 Views
7.e.Q Themenstarter:in
925 Beiträge seit 2004
vor 14 Jahren
[gelöst] Borderless Window Resize - ruckelig, sehr unschön

Hi Leute,

mal wieder Project-Hopping; mein liebstes Hobby... 😄

Ich bin am basteln mit einem rahmenlosen Fenster, dem ich einen eigenen Resize-Rahmen verpassen möchte (acht Rectangles als Resize-Grips entsprechend angeordnet). Die acht Rectangles haben alle ihrer Position um das Fenster herum entsprechend ein Tag N, NE, E, SE, ..., NW.

Im Grunde funktioniert das auch soweit, es ist aber optisch sehr unschön. Es ruckelt wie die Sau (schulligung). Am saubersten funktionieren die Resize-Grips E und S, da diese nur Width und Height verändern. SE führt bei schnellen Bewegungen zu einer treppenartigen Veränderung der Größe (wohl, weil erst Height und dann Width gesetzt wird).

Ich vermute, dass dieses Ruckeln damit zusammenhängt, dass zwischen den einzelnen Anweisungen zum Setzen von Top, Left, Width und Height Verzögerungen auftreten. Diese muss ich irgendwie wegbekommen, also dafür sorgen, dass WPF das Form erst wieder rendert, nachdem alle vier Eigenschaften auf ihre neuen Werte gesetzt sind.

Gibt's da 'ne Möglichkeit? Oder hat jemand 'ne andere Idee?

Danke!

Grüße,
Hendrik

Hier mal die zugehörigen Code-Schanipsel


        #region Window Resize

        string sResizeTag = "";
        double dInitWidth = 0.0D, dMouseStartX = 0.0D;
        double dInitHeight = 0.0D, dMouseStartY = 0.0D;

// MouseMove Event aller acht Rectangles

        private void Resize_Window(object sender, MouseEventArgs e)
        {
            Rectangle rect = sender as Rectangle;
            if (sResizeTag == "" || rect == null) return;

            double width = e.GetPosition(this).X - dMouseStartX;
            double height = e.GetPosition(this).Y - dMouseStartY;

            double tTop = this.Top, tLeft = this.Left, tWidth = this.Width, tHeight = this.Height;

            if (sResizeTag.Contains('N'))
            {
                //Console.WriteLine("Resize north {0}", height);
                tTop += height;
                tHeight -= height;
            }

            if (sResizeTag.Contains('S'))
            {
                //Console.WriteLine("Resize south {0}", height);
                tHeight = dInitHeight + height;
            }

            if (sResizeTag.Contains('W'))
            {
                //Console.WriteLine("Resize east {0}", width);
                tLeft += width;
                tWidth -= width;
            }

            if (sResizeTag.Contains('E'))
            {
                //Console.WriteLine("Resize west {0}", width);
                tWidth = dInitWidth + width;
            }

            this.Height = tHeight; this.Width = tWidth; this.Top = tTop; this.Left = tLeft;
        }

// LeftMouseButtonUp Event aller acht Rectangles

        private void Resize_End(object sender, MouseButtonEventArgs e)
        {
            Rectangle rect = sender as Rectangle;

            dMouseStartX = dMouseStartY = 0;

            if (rect != null)
            {
                sResizeTag = "";
                rect.ReleaseMouseCapture();
            }
        }

// LeftMouseButtonDown Event aller acht Rectangles

        private void Resize_Init(object sender, MouseButtonEventArgs e)
        {
            Rectangle rect = sender as Rectangle;

            dMouseStartX = e.GetPosition(this).X;
            dMouseStartY = e.GetPosition(this).Y;

            dInitWidth = this.Width;
            dInitHeight = this.Height;

            if (rect != null)
            {
                sResizeTag = rect.Tag.ToString();
                rect.CaptureMouse();
            }
        }

        #endregion


L
95 Beiträge seit 2009
vor 14 Jahren

Setzte folgenden Code mal in den Konstruktor:

// Geschwindigkeiten optimieren
            SetStyle(ControlStyles.DoubleBuffer, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.CacheText, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.UserPaint, true);

Lg Marc

7.e.Q Themenstarter:in
925 Beiträge seit 2004
vor 14 Jahren

Danke, würde ich gerne tun, wäre ich im Windows Forms Kontext. In WPF funktioniert das nicht. Window hat keine Methode SetStyle.

L
95 Beiträge seit 2009
vor 14 Jahren

Oh, sorry 😦

Habe überlesen, das das ganze in WPF gemacht wird 😦 (Besser gesagt nicht gelesen, in welchem Unterforum ich mich befinde) schäm

In WPF sollte das eigentlich gar nicht flackern... Oo

Jedenfalls DENKE ich, dass du es in WPF nicht besser machen können wirst, da WPF schon alles (diesbezüglich) per DirectX macht... So viel zu Optimierungen hust

Lg Marc

U
1.578 Beiträge seit 2009
vor 14 Jahren

man koennte nur versuchen den windows style (resize ohne vorschau) nach zu ahmen

also bei mousedown ein virtuellen grauen rahmen einblenden - diesen resizen und dann bei mouseup das fenster auf die groesse des rahmens bringen

in wiefern das ueberhaupt funktioniert kann ich allerdings nicht sagen

7.e.Q Themenstarter:in
925 Beiträge seit 2004
vor 14 Jahren

Das müsste eventuell mit 'nem Popup funktionieren... aber schön ist das trotzdem nicht.

Irgendwas muss da ja auch dafür sorgen, dass es ruckelt. An meinem PC (Core2Quad Q6700, GeForce 8800GTS/512, 8GB RAM) dürfte es eigentlich nicht liegen. Der sollte schnell genug sein.

Ich muss mir nochmal genau anschauen, welche Methoden da während des Resize aufgerufen werden, welche davon so viel Performance schlucken.

Möglicherweise ist es PostSharp 1.5, das ich einsetze, um in einer meiner Daten-Klassen ein automatisches OnPropertyChanged zu haben; aus purer Faulheit, weil ich nicht in jeder Setter-Methode den Aufruf der OnPropertyChanged Methode drin haben will. Eventuell zieht das Ding so enorm Performance... dürfte aber eigentlich nicht, wenn ich das auf der Entwickler-Homepage richtig verstanden habe. Ich schau mir das nochmal an... in der Zwischenzeit werd ich damit wohl leben müssen.

//edit 1:

An PostSharp liegt's wohl nicht. Die Methoden werden während des Resize gar nicht aufgerufen. Auch tritt keine Änderung des Verhaltens ein, wenn ich PostSharp weglasse.

Stelle ich WindowStyle auf SingleBorder, AllowTransparency auf False und verändere die Größe des Fensters mit dem Windows-eigenen Border, dann tritt dieses Verhalten nicht auf. Dann verändert das Fenster sehr viel fließender seine Größe.

Benutze ich in diesem Zustand den von mir selbst eingezogenen Rahmen, ruckelt es trotzdem. An AllowTransparency oder WindowStyle kann's also auch nicht liegen.

Gibt es nicht irgendwie einen Weg, wie ich das Resize-Verhalten des normalen Fensterrahmens auf einen eigenen Rahmen abbilden kann?

373 Beiträge seit 2006
vor 14 Jahren

Vielleicht hilft dir das weiter.

MfG
Tonka

7.e.Q Themenstarter:in
925 Beiträge seit 2004
vor 14 Jahren

Vielleicht hilft dir
>
weiter.

MfG
Tonka

Japp! Volltreffer! Ein riesen Schritt auf jeden Fall.

Einzig beim Vergrößern und Verkleinern an Top und Left (wie im Artikel erwähnt) ruckelt's noch etwas. Aber das scheint ein WPF spezifisches Problem zu sein. Right und Bottom sind nun wesentlich sauberer.

Danke dafür!

373 Beiträge seit 2006
vor 14 Jahren

Bei Left und Top ruckelt es in Windows grundsätzlich immer, egal ob Xp, Vista, Win7. Das ist ein Windows-Problem 😉

7.e.Q Themenstarter:in
925 Beiträge seit 2004
vor 14 Jahren

Bei Left und Top ruckelt es in Windows grundsätzlich immer, egal ob Xp, Vista, Win7. Das ist ein Windows-Problem 😉

Haha, stimmt! Das ist mir noch nie vorher aufgefallen... Da arbeitet man seit Windows 95 mit Fenstern, deren Inhalt beim Ziehen dargestellt wird und nie fällt einem sowas auf... tztztz... 👅

Okay, alles klar, danke nochmal für die großartige Hilfe! 🙂 👍 👍 👍