Zum Inhalt springen

[C#] Panel flimmert bei Resize


Empfohlene Beiträge

Geschrieben (bearbeitet)

Hi,

ich wollte mir schnell mal eine Art Toolbox wie in Visual Studio schreiben, da ich diese für Suchfilter benötige und das Panel sowenig Platz wie möglich auf dem Form einnehmen soll.

Jetzt zeigt sich beim aufklappen respektive zuklappen des Panels dieser "flimmer" Effekt, welcher äußerst unschön ist.

Ich habe bereits versucht das Panel auf DoubleBuffered zu setzten. Jedoch sieht dann das aufklappen unschön aus. Ist ziemlich schwer zu erklären :beagolisc.

Bevor ich hier jetzt den Code poste werde ich das Projekt mal als zip anhängen um diesen Beitrag nicht unnötigerweise in die Länge zu ziehen.

In der aktuellen Konfiguration ist das Flimmern sichtbar.

Wenn ihr es also debuggt und rechts auf einen der Reiter klickt wird es expandiert und das flimmern ist erkennbar.

Bevor ich daran weiterarbeite würde ich das unschöne Problem gerne beseitigen, allerdings fällt mir gerade keine Möglichkeit mehr ein.

Wenn jemand einen Tipp hätte wäre das klasse :).

lg

Gateway

TestApp.zip

Bearbeitet von Gateway_man
Geschrieben (bearbeitet)

Nein leider nicht. Der Effekt ist immernoch present.

Ich habe mich nicht alzulange damit aufhalten wollen (da es im nachhinein immernoch bearbeitbar wäre).

Nun hab ich es so erweitert das es an allen Seiten andockbar ist und das man zwischen zwei modi unterscheidet. Entweder werden die Panel durch klicken aufgeklappt oder durch das bewegen der Maus über den entsprechenden Reiter.

Beim Docking ist mir aufgefallen das das Flimmern nur sichtbar ist wenn ich das HostControl rechts oder unten andocken lasse.

Ich vermute daher das es daran liegt das ich rechts und unten die location und die größe in der while schleife verändere. Links und oben muss ich jeweils nur die Witdh und die Height vergrößern/verkleinern.

Sollte also noch jemand einen geistesblitz haben wäre ich natürlich hoch erfreut :).

lg

Gateway

Bearbeitet von Gateway_man
Geschrieben (bearbeitet)

hi,

danke Gooose. Leider ist das ne wpf Library und das ist für mich nicht brauchbar da ich mich nur bedingt mit wpf und xaml auskenne.

Leider ist da auch nur ein Beispiel dabei wie man es in einer wpf Application einbindet und nicht wie man es in einer Windows Form Application einbindet.

Zudem bin ich eher an einer eigenen Lösung interessiert da ich da lizenztechnisch auf der sicheren Seite bin. Ich hab jetzt sowieso schon so viel Zeit reinivestiert und es gefällt mir schon außerordentlich gut (vor allem da recht simpel in der Benutzung).

Es scheint auch so als wäre mein Problem bereits gelöst da das flimmern (zumindest auf meiner Kiste) nichtmehr auftritt. Fragt mich nicht wie, denn ich weiß es nicht :D. Nachdem ich den größten Teil des codes umgeschrieben und erweitert hatte, diesen dann testete, viel mir auf das es nicht mehr present war.

Muss es nurnoch auf anderen Rechner testen um sicher sein zu können.... (habs gerade bei nem Kollegen getestet und das flimmern tritt nicht auf. Hat sich also erledigt)

Trotzdem danke an alle

lg

Gateway

Bearbeitet von Gateway_man
Geschrieben

Guten Abend,

leider muss ich nochmals stören :old.

Ich habe in dem Projekt noch ein Problem.

Wie bereits gesagt habe ich es um eine Mouse_Hover Funktionalität erweitert. Das heißt, wenn man den Cursor der Maus über einer der Registerkarten schiebt wird das entsprechende Panel automatisch aufgeklappt.

Es sollte natürlich auch aufgeklappt bleiben solange der Cursor sich entweder über der entsprechenden Registerkarte aufhält oder innerhalb des entsprechenden Panels.

Das klappt an sich wunderbar, solange ich das ToolBoxHost Control (welches für die Steuerung zuständig ist) entweder Links oder Oben ans ParentControl gedockt habe.

Docke ich es Rechts oder Unten ans ParentControl gibt es massive Probleme.

Damit meine ich egal wie schnell ich versuche auf das Panel zu kommen es klappt wieder zu.

Nun kurz die entsprechenden CodeSnippets.

Wenn ein Item dem ToolboxHostControl hinzugefügt wird, wird folgendes Event ausgelöst:


        private void ContainerAdded(object sender, ToolBoxContainerAdded e)

        {

            if (base.Parent != null)

            {

                if (e.Item.Container != null)

                {

                    e.Item.Container.Visible = false;

                    Parent.Controls.Add(e.Item.Container);

                    //e.Item.Container ist das Panel. Hier werden zwei Events registriert

                    e.Item.Container.MouseLeave += new EventHandler(Pnl_MouseLeave);

                    e.Item.Container.MouseEnter += new EventHandler(Pnl_MouseEnter);

                }

            }

        }

Um erkennen zu können ob die Maus innerhalb des Panel ist oder nicht werden diese zwei Events benötigt. Der Inhalt der Events sieht wie folgt aus:

        private void Pnl_MouseEnter(object sender, EventArgs e){

            //id ist ein globaler integer wert der zur identifikation benötigt wird. (Jeder ToolBoxContainer hat eine UniqueID)

            if (mode == ElapseMode.OnHover && id != 0) {

                ToolBoxPanel p = (ToolBoxPanel)sender;

                List<ToolBoxContainer> elements = (from current in items where current.ID == id && current.ViewState == ContainerState.Elapsed && current.Container == p select current).ToList();

                if (elements.Count > 0)

                {

                   //panel_enter wird ein gloaber boolean der im Mouse_Move Event abgefragt wird (Das poste ich nach den beiden Events)

                    panel_enter = true;

                }

            }

        }


        private void Pnl_MouseLeave(object sender, EventArgs e) {

            if (mode == ElapseMode.OnHover && id != 0) {

                ToolBoxPanel p = (ToolBoxPanel)sender;

                Rectangle rect = p.RectangleToScreen(p.ClientRectangle);

                if (MousePosition.X >= rect.X && MousePosition.X <= (rect.X + rect.Width) && MousePosition.Y >= rect.Y && MousePosition.Y <= (rect.Y + rect.Height)) {

                    return;

                }

                List<ToolBoxContainer> elements = (from current in items where current.ID == id && current.ViewState == ContainerState.Elapsed && current.Container == p select current).ToList();

                if (elements.Count > 0){

                 Collapse(elements[0].Container);

                 elements[0].Container.Visible = false;

                 elements[0].ViewState = ContainerState.Collapsed;

                 panel_enter = false;

                 id = 0;

                }

            }

        }

In dem MouseLeave soll das aufgeklappte Panel wieder geschlossen werden, da die Mouse ja effektiv außerhalb des Panels bewegt wurde. So nun zu dem Mouse_Move Event des ToolBoxHost Controls. Ist etwas größer und unter umständen etwas schwer nachzuvollziehen. Ich werd mal versuchen das notwendigste zu Kommentieren.

 private void ToolBoxHost_MouseMove(object sender, MouseEventArgs e)

        {

           //Der Obere Teil ist nicht relevant hier wird nur der entsprechenden Border für die Registerkarten neugezeichnet

            if (mode == ElapseMode.OnClick)

            {

                foreach (ToolBoxContainer item in items)

                {

                    if (e.X >= item.Location.X && e.X <= (item.Location.X + item.Size.Width) && e.Y >= item.Location.Y && e.Y <= (item.Location.Y + item.Size.Height))

                    {

                        item.LableState = HeaderState.Hover;

                        this.Update() ;

                    }

                    else

                    {

                        item.LableState = HeaderState.None;

                        this.Update();

                    }

                }

            }

            else {



                foreach (ToolBoxContainer item in items)

                {

                    if (e.X >= item.Location.X && e.X <= (item.Location.X + item.Size.Width) && e.Y >= item.Location.Y && e.Y <= (item.Location.Y + item.Size.Height))

                    {

                        item.LableState = HeaderState.Hover;

                        //this.Update();

                        this.Refresh();

                    }

                    else

                    {

                        item.LableState = HeaderState.None;

                        this.Refresh();

                        //this.Update();

                    }

                }

                //Hier gehts los. Wenn die id ungleich null ist, sprich wenn eine Registerkarte

                //Elapsed (ausgefahren) ist und panel_enter false ist gibts nochmal 100

                //Millisekunden Zeit um ins Panel zu wechseln (klappt soweit wenn das Docking

                //left oder top ist).

                if (id != 0 && !panel_enter)

                    System.Threading.Thread.Sleep(100);

                //Es wird nocheinmal geprüft ob panel_enter nun true ist und id ungleich 0.

                //Wenn ja dann gehts raus aus der Funktion.

                if (id != 0 && panel_enter)

                    return;

                //Der Rest ist eigentlich wieder irrelevant da hier wieder nur die Locations und

                //die Sizes der Panels anhand des Docking gesetzt werden. 

                //Nebenbei werden noch

                //die überflüssigen Panels geschlossen (also die die offen sind aber nicht         

                //fokusiert.

                if (id > 0)

                {

                    List<ToolBoxContainer> currentitem = items.Where(Target => Target.ID == id).ToList();

                    ToolBoxContainer cont = currentitem[0];

                    if (e.X >= cont.Location.X && e.X <= (cont.Location.X + cont.Size.Width) && e.Y >= cont.Location.Y && e.Y <= (cont.Location.Y + cont.Size.Height))

                    {

                        return;

                    }

                    else

                    {

                        Collapse(cont.Container);

                        cont.Container.Visible = false;

                        cont.ViewState = ContainerState.Collapsed;

                        id = 0;

                        panel_enter = false;

                        ToolBoxContainer ncont = null;

                        foreach (ToolBoxContainer item in items)

                        {

                            if (e.X >= item.Location.X && e.X <= (item.Location.X + item.Size.Width) && e.Y >= item.Location.Y && e.Y <= (item.Location.Y + item.Size.Height) && item.ViewState != ContainerState.Elapsed)

                            {

                                ncont = item;

                                break;

                            }

                        }

                        if (ncont != null)

                        {

                            switch (base.Dock)

                            {

                                case DockStyle.Top:

                                    if (Parent != null)

                                    {


                                        ncont.Container.Height = 0;

                                        ncont.Container.Width = Parent.ClientRectangle.Width;

                                        ncont.Container.Location = new Point(this.Location.X, this.Location.Y + this.Height);

                                        ncont.Container.Visible = true;

                                        Elapse(ncont.Container);

                                    }

                                    break;

                                case DockStyle.Right:

                                    if (Parent != null)

                                    {


                                        ncont.Container.Height = Parent.ClientRectangle.Height;

                                        ncont.Container.Width = 0;

                                        ncont.Container.Location = new Point(this.Location.X, this.Location.Y);

                                        ncont.Container.Visible = true;

                                        Elapse(ncont.Container);

                                    }

                                    break;

                                case DockStyle.Left:

                                    if (Parent != null)

                                    {


                                        ncont.Container.Height = Parent.ClientRectangle.Height;

                                        ncont.Container.Width = 0;

                                        ncont.Container.Location = new Point(this.Location.X + this.Width, this.Location.Y);

                                        ncont.Container.Visible = true;

                                        Elapse(ncont.Container);

                                    }

                                    break;

                                case DockStyle.Bottom:

                                    if (Parent != null)

                                    {


                                        ncont.Container.Height = 0;

                                        ncont.Container.Width = Parent.ClientRectangle.Width;

                                        ncont.Container.Location = new Point(this.Location.X, this.Location.Y);

                                        ncont.Container.Visible = true;

                                        Elapse(ncont.Container);

                                    }

                                    break;

                            }



                            id = ncont.ID;

                            ncont.ViewState = ContainerState.Elapsed;

                        }


                    }

                }

                else {

                    ToolBoxContainer ncont = null;

                    foreach (ToolBoxContainer item in items)

                    {

                        if (e.X >= item.Location.X && e.X <= (item.Location.X + item.Size.Width) && e.Y >= item.Location.Y && e.Y <= (item.Location.Y + item.Size.Height) && item.ViewState != ContainerState.Elapsed )

                        {

                            ncont = item;

                            break;

                        }

                    }

                    if (ncont != null)

                    {

                        switch (base.Dock)

                        {

                            case DockStyle.Top:

                                if (Parent != null)

                                {


                                    ncont.Container.Height = 0;

                                    ncont.Container.Width = Parent.ClientRectangle.Width;

                                    ncont.Container.Location = new Point(this.Location.X, this.Location.Y + this.Height);

                                    ncont.Container.Visible = true;

                                    Elapse(ncont.Container);

                                }

                                break;

                            case DockStyle.Right:

                                if (Parent != null)

                                {


                                    ncont.Container.Height = Parent.ClientRectangle.Height;

                                    ncont.Container.Width = 0;

                                    ncont.Container.Location = new Point(this.Location.X, this.Location.Y);

                                    ncont.Container.Visible = true;

                                    Elapse(ncont.Container);

                                }

                                break;

                            case DockStyle.Left:

                                if (Parent != null)

                                {


                                    ncont.Container.Height = Parent.ClientRectangle.Height;

                                    ncont.Container.Width = 0;

                                    ncont.Container.Location = new Point(this.Location.X + this.Width, this.Location.Y);

                                    ncont.Container.Visible = true;

                                    Elapse(ncont.Container);

                                }

                                break;

                            case DockStyle.Bottom:

                                if (Parent != null)

                                {


                                    ncont.Container.Height = 0;

                                    ncont.Container.Width = Parent.ClientRectangle.Width;

                                    ncont.Container.Location = new Point(this.Location.X, this.Location.Y);

                                    ncont.Container.Visible = true;

                                    Elapse(ncont.Container);

                                }

                                break;

                        }



                        id = ncont.ID;

                        ncont.ViewState = ContainerState.Elapsed;

                    }


                }


            }

        }

Ich habe das Problem schon einigermaßen eingrenzen können. Wenn das ToolBoxHost Control Rechts oder Unten gedockt wurde, wird das Event Pnl_MouseEnter nicht ausgeführt.

Warum das nicht so ist verstehe ich nicht, da ich effektiv bei jedem Docking den fast identischen Code ausführe (unterscheidet sich nur in den Location Points und der Size).

Wenn einer von euch weiß was ich falsch mache, dann bitte ich inständig um Hilfestellung :).

lg

Gateway

Geschrieben

Hi,

wollte nur bescheid sagen das es sich bereits erledigt hat. Ich hatte noch eine Funktion die bei Verlassen des Controls alle offenen Panels schließt. Scheinbar war dort ein Fehler, den ich leider nicht genauer nachvollziehen kann/konnte, da es ja bei Top Docking nicht eintratt.

lg

Gateway

Geschrieben

Okay, kommt etwas spät, aber vielleicht nützt es ja doch noch etwas... google mal nach DockPanel Suite. Ist ein Sourceforge Projekt, Du könntest also mal reinschauen, wie die das gemacht haben.

Geschrieben
Okay, kommt etwas spät, aber vielleicht nützt es ja doch noch etwas... google mal nach DockPanel Suite. Ist ein Sourceforge Projekt, Du könntest also mal reinschauen, wie die das gemacht haben.

Sieht sehr interessant aus (eben exakt wie die Toolbox von VS). Allerdings ist mir das schon wieder fast zu overdressed. Das mit dem verschieben der einzelnen Panel brauch ich gar nicht :). Es ging mir primär um das dynamische auf und zuklappen der Panels, da ich momentan was schreibe das für kleine Geräte ausgelegt ist. Das heißt sehr kleine Bildschirme :D.

Ich bin vollauf Zufrieden mit der aktuellen version.

Trotzdem danke.

lg

Gateway

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...