Entwickler-Ecke

WinForms - Eigenen SplitButton erstellen


Csharp-programmierer - Fr 05.08.16 09:43
Titel: Eigenen SplitButton erstellen
Hallo,
ich versuche gerade meinen eigenen SplitButton zu erstellen. Dafür habe ich eine UserControl und 2 PictureBoxen. Eine mit dem Icon und die andere mit dem Pfeil. Ich habe mir auch eine Property geschrieben, die verschiedene Items in einen ContextMenuStrip schreibt. Das funktioniert alles erstmal.

Das Problem nun aber ist die Berechnung der Koordinaten, wo das ContextmenuStrip angezeigt werden soll. So erstmal der Prototype Code:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
public partial class MS_SplitButton : UserControl
    {
        private string[] _items;
        ContextMenuStrip strip = new ContextMenuStrip();

        public MS_SplitButton()
        {
            InitializeComponent();
        }

        private void pictureBox2_Click(object sender, EventArgs e)
        {
            foreach (string it in _items)
                strip.Items.Add(it);
            strip.Show(thisthis.Location.Y, this.Location.X);
            strip.Items.Clear();
        }

        [DisplayName("ContextMenu Items")]
        public string[] Items
        {
            get
            {
                return _items;
            }
            set
            {
                _items = value;
            }
        }
    }


Palladin007 - Fr 05.08.16 09:50


C#-Quelltext
1:
2:
3:
4:
5:
6:
Point splitButtonLocation = ...
Size splitButtonSize = ...

var verticalMargin = 5;
var menuLocation = splitButtonLocation + new Point(0, splitButtonSize.Height + verticalMargin);
var menuSize = new Size(splitButtonSize.Width, CalculateMenuHeight());


Csharp-programmierer - Fr 05.08.16 10:12

s

Irgendwie nimmt er die 4. Zeile nicht. Und CalculateSplitButtonHeight() ist doch nur die Höhe des SplitButtons, oder?


Ralf Jansen - Fr 05.08.16 10:16

Ich kaufe ein Semikolon?


Palladin007 - Fr 05.08.16 10:17

Verdammt, sollte CalculateMenuHeight sein :D
Bringt ja nichts, wenn das Menü so groß ist wie der Button

Und da fehlt ein Semikolon, deshalb meckert der
Das hättest Du aber auch selber heruas finden können :P


@Ralf:
Ich muss seit Wochen mit VB.NET arbeiten, ich denke, da kann man mir das verzeihen :D



PS:
Die Properties Location und Size sind bereits Point bzw. Size, da musst Du keinen neuen Wert erzeugen.
Die Variablen sind auch nur als Dummy gedacht, um eben diese Properties anzudeuten.


Ralf Jansen - Fr 05.08.16 10:22

Points kan man eigentlich auch nicht addieren :?: Points kann man mit Point.Offset(x,y) verschieben.


Palladin007 - Fr 05.08.16 10:24

Points kann man addieren ;)
Zumindest die Points aus dem System-Drawing-Namespace
Die haben entsprechende Operator-Überladungen und ich bin froh drüber, sonst würde mein Code hier noch unübersichtlicher werden :D
Und da er mit WinForms arbeitet, was auf System.Drawing aufbaut ..



PS:
Wobei, stimmt nicht ganz
Es hat Überladungen für Size

Aber da Size wiederum implizite Konvertierung von Point unterstützt, greift das trotzdem
Oder ist das nur wieder irgendeine implizite Konvertierung von VB.NET? :/

Dann natürlich so:

C#-Quelltext
1:
var menuLocation = new Point(splitButtonLocation.X, splitButtonLocation.Y + splitButtonSize.Height + verticalMargin);                    


Ralf Jansen - Fr 05.08.16 10:34

Vielleicht zu Sicherheit einfach nicht rechnen ;) Man kann den Strip relativ zu einem ~Parent~ Control anzeigen.


C#-Quelltext
1:
strip.Show(thisnew Point(0, Height), ToolStripDropDownDirection.BelowRight);                    

Dann ist der Links unten zum dem Control (this) ausgerichtet. Oder wenn man die rechte Kante des Controls will etwa

C#-Quelltext
1:
strip.Show(thisnew Point(Width, Height), ToolStripDropDownDirection.BelowLeft);                    


Zitat:
Oder ist das nur wieder irgendeine implizite Konvertierung von VB.NET? :/


Vermutlich. Klingt auf jedenfall nach etwas das ich nicht will ;)
Punkte addieren macht für mich wenig Sinn. Eine Strecke + ein Punkt ergibt einen neuen Punkt das macht Sinn.


Csharp-programmierer - Fr 05.08.16 13:11

Vielen vielen Dank. Nun funktioniert es :)


Palladin007 - Fr 05.08.16 13:42

Die Überladung kannte ich ja noch gar nicht :D
Danke dafür ^^


Zitat:
Vermutlich. Klingt auf jedenfall nach etwas das ich nicht will ;)


Joa, das Gefühl kenne ich :D
VB.NET macht so einiges, wie z.B. implizites Konvertieren und spätes Binden, was ich bisher nur von PHP und JavaScript kannte und nicht mochte.

Zitat:
Punkte addieren macht für mich wenig Sinn. Eine Strecke + ein Punkt ergibt einen neuen Punkt das macht Sinn.


Ist denke ich Auslegungssache. Man kann ja auch so argumentieren, dass die Addition zweier Punkte die Addition der Koordinaten ist und das finde ich dann wieder sinnvoll.
Wenn Du zig Punkte manuell positionieren und einen Haufen anderer Werte beachten musst, dann ist das einfacher:

C#-Quelltext
1:
var myNewPoint = Point1 + Point2 + Point3 - Point4;                    

als das:

C#-Quelltext
1:
var myNewPoint = new Point(Point1.X + Point2.X + Point3.X - Point4.X, Point1.Y + Point2.Y + Point3.Y - Point4.Y);                    

Vorallem ist es übersichtlicher, erst recht, wenn Point1 bis 4 von Controls und Properties mit längeren Namen kommen.


Viel merkwürdiger finde ich dagegen, warum es einen Operator gibt, der Point in Size konvertiert O.o


Ralf Jansen - Fr 05.08.16 13:56

Zitat:
Man kann ja auch so argumentieren, dass die Addition zweier Punkte die Addition der Koordinaten ist und das finde ich dann wieder sinnvoll.


Wenn das ein simpler x,y Tupel/Vektor wäre würde ich dir Recht geben aber .Net hat sich explizit dafür entschieden die Dinge zu unterscheiden und eben unterscheidbare Typen (Point,Size etc.) erfunden. Dann sollten die Dinge sich auch entsprechend ihrem Namen verhalten ;)