Laden...

Button mit Backgroundimage wird in unterschiedlichen Forms verzerrt dargestellt

Erstellt von Bananajoe123 vor 3 Jahren Letzter Beitrag vor 3 Jahren 2.577 Views
B
Bananajoe123 Themenstarter:in
16 Beiträge seit 2020
vor 3 Jahren
Button mit Backgroundimage wird in unterschiedlichen Forms verzerrt dargestellt

Hallo Zusammen,

ich würde gerne eine Benutzeroberfläche mit Buttons als Polygonen gestalten. Dazu habe ich mir eine Klasse erstellt:

class Button_Polygon : Button
    {
        protected override void OnPaint(PaintEventArgs pevent)
        {
            // Create an array of points.
            Point[] myArray = new Point[]
                {
                 new Point(37, 0),
                 new Point(112, 0),
                 new Point(150, 65),
                 new Point(112, 130),
                 new Point(37, 130),
                 new Point(0, 65)
                };

            GraphicsPath grPath = new GraphicsPath();
            grPath.AddPolygon(myArray);
            this.Region = new System.Drawing.Region(grPath);
            base.OnPaint(pevent);
        }
    }

Das funktioniert im Prinzip auch wunderbar. In diese buttons habe ich dann Hintergrundbilder eingefügt und das Layout "gestretched".
Mein Programm besteht aus einer Haupt-Form und mehreren Child-Formen, die in einem Panel der Hauptform angezeigt werden.

In der Hauptform sind die Buttons einwandfrei dargestellt. Aber in den Childformen wird das Hintergrundbild nicht mehr richtig ein das Polygon eingepasst, sondern verzerrt (zu groß) dargestellt.
Prinzipiell glaube ich schon, dass das bild auf irgendeine Weise gestretched wird, denn es ist nicht viel zu groß. Aber es passt eben am Ende doch nicht wirklich.

Vielleicht hatte ja jemand diese problem schon einmal und weiß eine Lösung.

Vielen Dank für die Rückmeldung und beste Grüße!
Alle Childforms und das Panel haben die gleiche Pixelanzahl.

B
Bananajoe123 Themenstarter:in
16 Beiträge seit 2020
vor 3 Jahren

Mir ist gerade noch etwas aufgefallen, womit es zusammenhängen könnte:

Mein Button ist über das Feld statisch in seiner Größe. Ich kann ihn also nicht größer oder kleiner ziehen. Vielleicht müsste man das dynamisch gestalten.

Wobei ich in meinem Fall die Größe der buttons nicht verändert habe. Ich habe sie sogar kopiert. D. h. alle Eigenschaften sind bis auf den Namen und das Hintergrundbild identisch.

B
Bananajoe123 Themenstarter:in
16 Beiträge seit 2020
vor 3 Jahren

Ein Weg, der zumindest eine vorübergehende Lösung liefert ist natürlich, meine Hintergrundbilder auf die auf die Pixelzahl der Buttons anzupassen, sodass ich auf die Stretch-Funktion verzichten kann.

Das liefert auch das gewünschte Ergebnis, ist aber blöd, wenn ich die Buttons doch umskalieren muss.

16.834 Beiträge seit 2008
vor 3 Jahren

In Forms wirst Du bei Bildern und dynamischen Größen immer ein Stretch-Problem haben. Das ist halt bei fixen Pixeln so; skalieren ist da nicht so wirklich möglich.
Wirklich lösen (ohne Workaround) geht nur über SVG-Grafiken, die Du direkt in WPF verwenden kannst; jedoch nicht in Forms.

B
Bananajoe123 Themenstarter:in
16 Beiträge seit 2020
vor 3 Jahren

OK Danke, dann werde ich die Lösung mit passenden Bildern wählen.

B
Bananajoe123 Themenstarter:in
16 Beiträge seit 2020
vor 3 Jahren
Form in Panel verzerrt dargestellt

Hallo Zusammen,

ich habe mittlerweile Stunden darin investiert, mein Problem zu lösen, aber ich komme nicht auf eine Lösung oder ich weiß einfach nicht, welche Wörter ich zum googlen brauche.

Folgendes Problem:
Ich habe nach folgender "Anleitung" eine Anwendung erstellt (https://rjcodeadvance.com/formulario-modernoiconos-font-awesome-winform-c/). Dabei wird eine Haupt-Form erstellt, in der sich ein Panel befindet. Wird ein Button in der Hauptform gedrückt, wird eine "Childform" in das Panel geladen und angezeigt.

Die Code-Abschnitte dazu sind:

//Methode zum öffnen einer Childform im Main-Programmteil

private void OpenChildForm(Form childForm)
        {
            //open only one form
            if (currentChildForm != null)
            {
                currentChildForm.Close();
            }
            currentChildForm = childForm;
            //End

            childForm.TopLevel = false;
            childForm.FormBorderStyle = FormBorderStyle.None;
            childForm.Dock = DockStyle.Fill;
            panelTabs.Controls.Add(childForm);
            panelTabs.Tag = childForm;
            childForm.BringToFront();
            childForm.Show();
        }

//Clicken eines Buttons zum Laden der neuen Form in das Panel

private void button_Movement_Click(object sender, EventArgs e)
        {   
            OpenChildForm(new Forms.FormMovement());
        }

Laut Angabe des Erstellers wird die Childform dann unverzerrt dargestellt, wenn die Panle-Größe und die Childformgröße übereinstimmen. In meinem Fall habe ich beide auf 1604 x 871 festgelegt.

Anders als im Anleitungsvideo wird meine Childform Verzerrt. Meine Childform wird zwar schon geladen, aber viel zu groß. So wie ich das sehe funktioniert das "Fill" schon, aber es geht von einem viel zu großen Fenster aus oder so. So ist zumindest meine Wahrnehmung.

Ich habe zur veranschaulichung mal ein Bildeingefügt:
Die Childform hat 1604 x 871 Pixel. Der Hintergrund ist auf Rot festgelegt und sollte bei korrekter Darstellung eigentlich gar nicht sichtbar sein.
Der blaue Bereich ist der eingentlich darzustellende Bereich, der in das Panel eingepasst werden sollte. Die Pfeilbuttons, die im Bild rechts sind, sollten eigentlich mittig und ohne Abstand nebeneinander angeordnet sein (so habe ich sie zumindest positioniert. Ich habe dazu auch schon sämltiche Anchor-Eigenschaften durchprobiert. Die ändern leider nichts)
Die grauen Buttons ganz links habe ich in meiner Form am Rand auf die 0-Position geschoben. Nach meinem Verständniss müssten die eigentlich an der Blauen Kante erscheinen, sie erscheinen aber an der roten Kante.
Ich kann mir leider nicht erklären, woher diese Verschiebung bzw. Verzrerrung kommt und wie ich sie beheben kann. Dazu reicht mein aktuelles C# Niveau nicht aus.

Beste Grüße und danke für jede Antwort!

B
Bananajoe123 Themenstarter:in
16 Beiträge seit 2020
vor 3 Jahren

Hier noch zur Veranschaulichung: So sollten meine Buttons eigentlich positioniert sein.

5.658 Beiträge seit 2006
vor 3 Jahren

Leider zeigst du nicht, wie du die Buttons positionierst.

Aber wenn ich es richtig verstehe, haben die Buttons eine unveränderliche Größe, und werden dynamisch innerhalb des Controls positioniert. Ist doch klar, daß dabei irgendwelche Zwischenräume enststehen, wenn das Control größer ist als die Buttons.

Entweder sollte man das Control mit den Buttons immer in der gleichen Größe darstellen.
Oder man sollte beides, also das Control UND die Buttons, dynamisch in der Größe anpassen.

Weeks of programming can save you hours of planning

16.834 Beiträge seit 2008
vor 3 Jahren

Mit WPF würdest Du es Dir beim Layout um Welten einfacher machen; auch wenn erstmal eine Lernhürde existiert, die nur mit Lernen zu meistern ist; aber das weißt Du ja schon 😃

B
Bananajoe123 Themenstarter:in
16 Beiträge seit 2020
vor 3 Jahren

Also Danke erst mal für die Antworten.
Zunächst: WPF werde ich mir schon noch zu Gemüte führen, das ist aber für meine aktuelle Situation nicht weiterführend.

Dass ein in der Größe verzerrtes Bild auch zu anderen Abständen der buttons führt ist mir klar.
Die Größe der Childform soll aber eigentlich auf die Größe des Panels beschränkt werden. Bei gleich groß definiertem Panel und Childform sollte sich also eigentlich nichts verschieben.
Was aber passiert ist, dass die einzupassende Childform viel zu groß wird.
Wenn ich in jede Ecke meiner Childform einen Button oder irgendwas anderes positioniere, wird das alles abgeschnitten, weil die Form anscheinend zu groß ist. Ich sehe nur was im linken oberen Ausschnitt ist. Diese Verzerrung erklärt auch, warum die Buttons zu große Abstände haben.

16.834 Beiträge seit 2008
vor 3 Jahren

das ist aber für meine aktuelle Situation nicht weiterführend.

Naja, aber Windows Forms für Dein Vorhaben halt auch nicht (wirklich).

Forms ist nun mal keine wirkliche Basis für moderne, frei-skalierenden Fertigcontent.
Dafür war Forms nicht gedacht und ist mit Forms auch viel aufwändiger (nicht unmöglich) umzusetzen.

Aber gut; musst Du wissen.

5.658 Beiträge seit 2006
vor 3 Jahren

Ich glaube nicht, daß das ein Problem ist, das sich durch eine andere Technologie von allein löst. Man kann die Anforderungen auch alle mit WinForms umsetzen. Man muß nur wissen, was man macht. Einen Umstieg empfehle ich natürlich auch, aber nicht, um ein paar Buttons zu zeichnen.

Du zeichnest die Buttons alle mit fester Größe (im ersten Codeausschnitt), und dann willst du, daß sie sich dynamisch an die Größe der Form anpassen. Wie soll das denn funktionieren? Wenn du eine automatische Größenanpassung willst, mußt du die Buttons auch relativ zu ihrer Größe zeichnen.

Ich kann auch nicht sehen, daß da irgendetwas "verzerrt" dargestellt wird. Ich sehe nur größere Abstände ziwschen den Buttons. Und die kommen offensichtlich daher, daß du Buttons mit statischer Größe dynamisch positionierst.

Und was genau meinst du mit "Childform". Ist das das Steuerelement mit den Buttons? Oder eine Form?

Weeks of programming can save you hours of planning

16.834 Beiträge seit 2008
vor 3 Jahren

Ich glaube nicht, daß das ein Problem ist, das sich durch eine andere Technologie von allein löst. Man kann die Anforderungen auch alle mit WinForms umsetzen. Man muß nur wissen, was man macht. Einen Umstieg empfehle ich natürlich auch, aber nicht, um ein paar Buttons zu zeichnen.

Nicht wegen ein paar Buttons; es geht um den Aspekt "moderne, dynamisch skalierende GUI; und das in Summe ist halt mit WPF deutlich einfacher und stabiler umzusetzen als das mit Forms zu tun.

B
Bananajoe123 Themenstarter:in
16 Beiträge seit 2020
vor 3 Jahren

Mit Childform meine ich die Form, die in das Panel geladen wird. Die Bezeichnung stammt aus der Methode, in der eine Form in das Panel geladen wird (siehe Codeabschnitt von oben). Letztlich habe ich aber zu meiner Haupt-Form eine "Windows Form" zu dem Projekt hinzugefügt.

Ich habe mir noch einmal das Anleitungs-Video angeschaut und letztlich ist dort doch der gleiche Effekt zu sehen. Scheinbar kann ich das doch nicht so ohne weiters lösen.

Das ganze soll ja eh nur auf einem bestimmten Bildschirm laufen. Dann werde ich das alles auf diesen Anpassen und naja WPF halt dann demnächst.

4.939 Beiträge seit 2008
vor 3 Jahren

Hast du schon mal überprüft, welche Skalierung du bei deinen Forms eingestellt hast (Stichwort: AutoScaleMode) oder verwendest du einen Monitor mit hoher Auflösung, s.a. GUI Design (Schriften, Bilder, etc.) sind plötzlich anders bei Target Framework 4.6 ?

Und warum verwendest du überhaupt Forms als Child-Elemente (anstatt UserControls oder Panels)? Nur bei MDI-Anwendungen oder Einbetten von externen Forms machen Child-Forms Sinn, s.a. [FAQ] Assistenten/Wizards: Mit Windows Forms eine Art Frameset einer Website nachbauen

463 Beiträge seit 2009
vor 3 Jahren

Hier noch zur Veranschaulichung: So sollten meine Buttons eigentlich positioniert sein.

Warum machst du daraus nicht 1 Usercontrol und zeichnest alles selbst?

B
Bananajoe123 Themenstarter:in
16 Beiträge seit 2020
vor 3 Jahren

Hallo Th69,

die Verwendung von Benutzersteuerelementen war ein prima Tipp. Das funktioniert einwandfrei.

Ich habe sie folgendermaßen angelegt:

Im User Control selbst:

private static ucMovement _instance;

        
        public static ucMovement Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new ucMovement();
                return _instance;
            }
        }

Ein Button in der Main-Form:

if (!panelTabs.Controls.Contains(UserControls.ucMovement.Instance))
            {
                panelTabs.Controls.Add(UserControls.ucMovement.Instance);
                UserControls.ucMovement.Instance.Dock = DockStyle.Fill;
                UserControls.ucMovement.Instance.BringToFront();
            }
            else
                UserControls.ucMovement.Instance.BringToFront();
2.079 Beiträge seit 2012
vor 3 Jahren

Warum ein Singleton?

Ich behaupte, ein Singleton ist in irgendwas von 95 bis 99% der Fälle eine blöde Idee oder lässt sich besser lösen.

Instanziiere das Ding, wie jedes andere Control auch, im Designer oder sobald Du es der Controls-Liste hinzufügen kannst.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

T
2.224 Beiträge seit 2008
vor 3 Jahren

Hier hat Palladin007 absolut recht, Singleton ist hier der falsche Ansatz.
Hier reicht es, das Control per Designer in dein Form zu ziehen und dann hast du deine Instanz.
Mehr als eine Menü Instanz wirst du im Code auch nicht anlegen wollen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

B
Bananajoe123 Themenstarter:in
16 Beiträge seit 2020
vor 3 Jahren

Ok, ich will das gerne so machen, wie ihr sagt, aber dafür bräuchte ich noch einmal eine genauere Beschreibung.
Wie soll ich die UserControls genau anlegen? Wie stelle ich sicher, dass immer nur genau eines offen ist und alle anderen im Hintergund nicht laufen?

Meine Version habe ich so als Codebeispiel im Internet gefunden. Warum genau ist sie schlecht oder ungünstig?

16.834 Beiträge seit 2008
vor 3 Jahren

Die einfachste Antwort: weil statische Verweise / Singletons sich nicht oder nur sehr umständlich überhaupt testen lassen.
[Artikel] Unit-Tests: Einführung in das Unit-Testing mit VisualStudio

Singletons sind immer eine große Gefahr für eine Software Architektur, wenn Du sie nicht so verwendest, wofür sie eigentlich gedacht sind - und das ist hier leider der Fall.
Sie sind immer eine Verletzung des Single-responsibility principle

What is so bad about singletons?

Meine Version habe ich so als Codebeispiel im Internet gefunden. Warum genau ist sie schlecht oder ungünstig?

Code aus dem Internet zu kopieren, den man selbst nicht versteht, ist halt selten eine gute Idee 😉

2.079 Beiträge seit 2012
vor 3 Jahren

Beispiel:

var myUserControl = new MyUserControl();
panelTabs.Controls.Add(myUserControl);

So schwer ist das nicht - da ist das Singleton weit komplexer 😄

Die einfachste Antwort: weil statische Verweise / Singletons sich nicht oder nur sehr umständlich überhaupt testen lassen.

Das stimmt natürlich, aber ich bezweifle, dass das in diesem Fall jemals von Bedeutung sein wird.

Viel problematischer finde ich, dass UserControl-Instanzen sich nicht uneingeschränkt wiederverwenden lassen.
Wie das bei WinForms genau abläuft, weiß ich nicht, aber bei WPF hatte ich mal einen lustigen Fehler, bei dem Controls verschwunden sind - weil irgendwer versucht hat, instanziierte Controls an mehreren Stellen zu nutzen...

Meine Version habe ich so als Codebeispiel im Internet gefunden. Warum genau ist sie schlecht oder ungünstig?

Wenn Du im Internet suchst, darfst Du nie vergessen: Das könnte auch ein Anfänger geschrieben haben.
Das heißt nicht, dass Du nicht online recherchieren darfst/sollst, ganz im Gegenteil, aber Du solltest nie irgendetwas einfach so nutzen, ohne zu verstehen, warum das so gemacht wurde.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

5.658 Beiträge seit 2006
vor 3 Jahren

Gerade bei UserControls ergibt Singleton überhaupt keinen Sinn. Ein UserControl soll ja gerade mehrfach, mit mehreren Instanzen, dargestellt werden können.

Ok, ich will das gerne so machen, wie ihr sagt, aber dafür bräuchte ich noch einmal eine genauere Beschreibung.
Wie soll ich die UserControls genau anlegen?

In der Doku gibt es ein Beispiel. Hast du dir das schon mal angeschaut?

Weeks of programming can save you hours of planning