ToggleButton Zeichnet komisch Oo

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 39 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    ToggleButton Zeichnet komisch Oo

    Hallo,
    ich versuche gerade einen ToggleButton zu zeichnen, nur das problem ist es Zeichnet den Off-Status falsch (Bilder sagen mehr als 1000 Worte)
    So wie es aussehen soll

    Das Falsche

    Das ist meine zeichen Methode
    Meine Frage ist, wo ist der Fehler? Oo
    ------- Full end Code
    Spoiler anzeigen

    C#-Quellcode

    1. public class ToggleButton : Control {
    2. #region Events
    3. #region PublicEvents
    4. public event Action<ToggleButton> Toggled;
    5. public event Action PropertiesChangeEvent;
    6. #endregion
    7. #region PrivateEvents
    8. #endregion
    9. #endregion
    10. #region Settings
    11. private GraphicsPath BackGraphicPath;
    12. private GraphicsPath ForeGraphicsPath;
    13. #endregion
    14. #region Properties
    15. private bool togglestate ;
    16. [Category("States"), DisplayName("State")]
    17. public bool ToggleState {
    18. get => togglestate;
    19. set {
    20. PropertyChange<bool, EventArgs>(ref togglestate, value, OnResize, null);
    21. Toggled?.Invoke(this);
    22. }
    23. }
    24. private Color oncolor;
    25. [Category("Toggle"), DisplayName("On")]
    26. public Color OnColor {
    27. get => oncolor;
    28. set => PropertyChange(ref oncolor, value);
    29. }
    30. private Color offcolor;
    31. [Category("Toggle"), DisplayName("Off")]
    32. public Color OffColor {
    33. get => offcolor;
    34. set => PropertyChange(ref offcolor, value);
    35. }
    36. private Color togglecolor;
    37. [Category("Toggle"), DisplayName("Color")]
    38. public Color ToggleColor {
    39. get => togglecolor;
    40. set => PropertyChange(ref togglecolor, value);
    41. }
    42. #endregion
    43. #region HiddenProperties
    44. [EditorBrowsable(EditorBrowsableState.Never)]
    45. [Browsable(false)]
    46. public new Color BackColor { get; set; }
    47. [EditorBrowsable(EditorBrowsableState.Never)]
    48. [Browsable(false)]
    49. public new Color ForeColor { get; set; }
    50. [EditorBrowsable(EditorBrowsableState.Never)]
    51. [Browsable(false)]
    52. public new Color Font { get; set; }
    53. [EditorBrowsable(EditorBrowsableState.Never)]
    54. [Browsable(false)]
    55. public new string Text { get; set; }
    56. [EditorBrowsable(EditorBrowsableState.Never)]
    57. [Browsable(false)]
    58. public new Image BackgroundImage { get; set; }
    59. [EditorBrowsable(EditorBrowsableState.Never)]
    60. [Browsable(false)]
    61. public new ImageLayout BackgroundImageLayout { get; set; }
    62. #endregion
    63. public ToggleButton() {
    64. InitializeStyle();
    65. InitializeValues();
    66. InitializeEvents();
    67. }
    68. private void InitializeStyle() {
    69. ControlStyles styles = ControlStyles.OptimizedDoubleBuffer
    70. | ControlStyles.SupportsTransparentBackColor
    71. | ControlStyles.UserPaint
    72. | ControlStyles.ResizeRedraw;
    73. SetStyle(styles, true);
    74. }
    75. private void InitializeValues() {
    76. BackColor = Color.Transparent;
    77. ToggleState = true;
    78. OnColor = Color.DodgerBlue;
    79. OffColor = Color.Red;
    80. ToggleColor = Color.White;
    81. BackColor = Color.Transparent;
    82. ForeColor = Color.Transparent;
    83. }
    84. private void InitializeEvents() {
    85. Resize += ToggleButton_Resize;
    86. Paint += ToggleButton_Paint;
    87. Click += ToggleButton_Click;
    88. DoubleClick += ToggleButton_Click;
    89. void ToggleButton_Resize(object sender, EventArgs e) {
    90. ///Setting
    91. ///
    92. int x = ToggleScanner(4, Width - Height + 4);
    93. ///Back
    94. ///
    95. GraphicsPath backgraphicsPath = new GraphicsPath();
    96. backgraphicsPath.AddArc(0, 0, Height, Height, 90, 180);
    97. backgraphicsPath.AddArc(Width - Height, 0, Height, Height, 270, 180);
    98. backgraphicsPath.CloseFigure();
    99. BackGraphicPath = backgraphicsPath;
    100. ///Fore
    101. ///
    102. GraphicsPath foregraphicsPath = new GraphicsPath();
    103. foregraphicsPath.StartFigure();
    104. foregraphicsPath.AddArc(x, 4, Height - 8, Height - 8, 0, 360);
    105. foregraphicsPath.CloseFigure();
    106. ForeGraphicsPath = foregraphicsPath;
    107. }
    108. void ToggleButton_Paint(object sender, PaintEventArgs e) {
    109. ///Setting
    110. ///
    111. Graphics graphics = e.Graphics;
    112. graphics.SmoothingMode = SmoothingMode.AntiAlias;
    113. graphics.CompositingQuality = CompositingQuality.HighQuality;
    114. graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
    115. graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
    116. ///back
    117. ///
    118. if (BackGraphicPath != null)
    119. graphics.FillPath(new SolidBrush(ToggleScanner(OnColor, OffColor)), BackGraphicPath);
    120. ///Fore
    121. ///
    122. if (ForeGraphicsPath != null)
    123. graphics.FillPath(new SolidBrush(ToggleColor), ForeGraphicsPath);
    124. }
    125. void ToggleButton_Click(object sender, EventArgs e) {
    126. ToggleState = ToggleScanner(false, true);
    127. }
    128. #region EventHelper
    129. T ToggleScanner<T>(T argtrue, T argfalse) => ToggleState ? argtrue : argfalse;
    130. #endregion
    131. }
    132. public void PropertyChange<T>(ref T field, T value) {
    133. field = value;
    134. PropertiesChangeEvent?.Invoke();
    135. Invalidate();
    136. }
    137. public void PropertyChange<T,T1>(ref T field, T value, Action<T1> action, T1 arg) {
    138. PropertiesChangeEvent?.Invoke();
    139. field = value;
    140. action(arg);
    141. Invalidate();
    142. }
    143. }

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Facebamm“ ()

    Hi
    du hast immer noch Option Strict auf Off. Stelle das unbedingt auf On. Du machst dir und insbesondere uns definitiv das Leben einfacher, wenn du es aktivierst.

    Clear ist überflüssig, das übernimmt das Steuerelement selbst (Control.OnPaintBackground). Wenn back transparent ist, funktioniert dein Code nicht. Nimm besser GraphicsPath und dort AddArc, um das zu machen (Es genügt, zwei Arcs zu haben und dann CloseFigure oder wie das heißt aufzurufen, du brauchst AddRectangle nicht, da eine Verbindung zwischen dem letzten Punkt des letzten Elements und dem ersten Punkt der nächsten hergestellt wird).

    Ansonsten probier mal mit Width - Height - 3.

    Viele Grüße
    ~blaze~
    a) c# hat kein Option Strict, weiß zwar nicht wo du da was gesehen hast aber okay :D - erledigt :D
    b) ist win-form. ok .. hätte ich schreiben sollen
    c) Also muss ich an allen ecken ein AddArc machen und dann Close figure, und dann erstelle ich meinen Kreis ...
    GraphicsPath, hab damit noch nie gearbeitet -.-, ich glaub ich mach es schon wieder zu kompliziert -.-
    Okay
    Das wäre mein Code, nur das Control Flackert ohne ende Oo - erledigt
    @~blaze~, thx, muss jetzt nur noch der qualli schauen

    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.ComponentModel;
    3. using System.Drawing;
    4. using System.Drawing.Drawing2D;
    5. using System.Windows.Forms;
    6. public class ToggleButton: Control, IState {
    7. private ToggleState togglestate = ToggleState.On;
    8. [Category("States")]
    9. public ToggleState ToggleState { get => togglestate; set {
    10. togglestate = PropertyChange(value);
    11. Toggled?.Invoke(this, null);
    12. }
    13. }
    14. private Color oncolor = Color.DodgerBlue;
    15. [Category("States")]
    16. public Color OnColor { get => oncolor; set => oncolor = PropertyChange(value);}
    17. private Color offcolor = Color.Red;
    18. [Category("States")]
    19. public Color OffColor { get => offcolor; set => offcolor = PropertyChange(value); }
    20. private Color tooglecolor = Color.White;
    21. [Category("States")]
    22. public Color ToggleColor { get => tooglecolor; set => tooglecolor = PropertyChange(value); }
    23. public event EventHandler Toggled;
    24. public event PropertiesChangeHandle PropertiesChangeEvent;
    25. public ToggleButton() {
    26. DoubleBuffered = true;
    27. ResizeRedraw = true;
    28. BackColor = OnColor;
    29. Paint += ToggleButton_Paint;
    30. Click += (sender, e) => ToggleState = ToggleState == ToggleState.On ? ToggleState.Off : ToggleState.On;
    31. Toggled += (sender, e) => BackColor = ToggleState == ToggleState.On ? OnColor : OffColor;
    32. }
    33. private void SetRoundPath() {
    34. //float r2 = radius / 2f;
    35. GraphicsPath graphicsPath = new GraphicsPath();
    36. graphicsPath.StartFigure();
    37. graphicsPath.AddArc(0, 0, Height, Height, 90, 180);
    38. graphicsPath.AddArc(Width - Height, 0, Height, Height, 270, 180);
    39. graphicsPath.CloseFigure();
    40. this.Region = new Region(graphicsPath);
    41. }
    42. private void ToggleButton_Paint(object sender, PaintEventArgs e) {
    43. ///Setting
    44. ///
    45. Graphics graphics = e.Graphics;
    46. graphics.SmoothingMode = SmoothingMode.HighQuality;
    47. GraphicsPath graphicsPath = new GraphicsPath();
    48. int x = ToggleState == ToggleState.On ? 4 : Width - Height + 4;
    49. ///back
    50. ///
    51. SetRoundPath();
    52. ///Fore
    53. ///
    54. graphicsPath.StartFigure();
    55. graphicsPath.AddArc(x, 4, Height - 8, Height - 8, 0, 360);
    56. graphicsPath.CloseFigure();
    57. graphics.FillPath(new SolidBrush(ToggleColor), graphicsPath);
    58. }
    59. public T PropertyChange<T>(T value, ref T field) {
    60. field = value;
    61. PropertiesChangeEvent?.Invoke();
    62. Invalidate();
    63. return value;
    64. }
    65. public T PropertyChange<T>(T value) {
    66. PropertiesChangeEvent?.Invoke();
    67. Invalidate();
    68. return value;
    69. }
    70. }

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Facebamm“ ()

    Da hab' ich eine Reihe von Anmerkungen:
    - das erste StartFigure sollte überflüssig sein
    - this.Region benötigst du ebenfalls nicht, außer du möchtest den Hintergrund ausblenden
    - Es wäre evtl. eine Idee von CheckBox zu erben, da es sich um eine CheckBox handelt (die hat allerdings 3 States)
    - immer using oder zumindest Dispose für GraphicsPath verwenden, ebenso für SolidBrush und alle anderen IDisposable implementierenden Klassen
    - Du rufst ständig SetRoundPath auf, wenn du es in ToggleButton_Paint aufrufst. Entweder bei OnSizeChanged oder gar nicht

    Hat das mit der - 3 geklappt?

    Viele Grüße
    ~blaze~
    Also so?
    @~blaze~ Das ist irgendwie ganz komisch damit, ich hab als erstes Width - Height - 4, da war es ja zuweit links, mach ich aber Width - Height + 4 passt es ...

    was aber noch fehlt ist die Quallität
    Bilder

    Code
    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.ComponentModel;
    3. using System.Drawing;
    4. using System.Drawing.Drawing2D;
    5. using System.Windows.Forms;
    6. public class ToggleButton: Control, IState, IDisposable {
    7. private ToggleState togglestate = ToggleState.On;
    8. [Category("States")]
    9. public ToggleState ToggleState { get => togglestate; set {
    10. togglestate = PropertyChange(value);
    11. Toggled?.Invoke(this, null);
    12. }
    13. }
    14. private Color oncolor = Color.DodgerBlue;
    15. [Category("States")]
    16. public Color OnColor { get => oncolor; set => oncolor = PropertyChange(value);}
    17. private Color offcolor = Color.Red;
    18. [Category("States")]
    19. public Color OffColor { get => offcolor; set => offcolor = PropertyChange(value); }
    20. private Color tooglecolor = Color.White;
    21. [Category("States")]
    22. public Color ToggleColor { get => tooglecolor; set => tooglecolor = PropertyChange(value); }
    23. public event EventHandler Toggled;
    24. public event PropertiesChangeHandle PropertiesChangeEvent;
    25. public ToggleButton() {
    26. DoubleBuffered = true;
    27. ResizeRedraw = true;
    28. BackColor = OnColor;
    29. Paint += ToggleButton_Paint;
    30. Click += (sender, e) => ToggleState = ToggleScanner(ToggleState.Off, ToggleState.On);
    31. Toggled += (sender, e) => BackColor = ToggleScanner(OnColor, OffColor);
    32. SizeChanged += (sender, e) => SetRoundPath();
    33. }
    34. private T ToggleScanner<T>(T argtrue, T argfalse) => ToggleState == ToggleState.On ? argtrue : argfalse;
    35. private void SetRoundPath() {
    36. using(GraphicsPath graphicsPath = new GraphicsPath()) {
    37. graphicsPath.AddArc(0, 0, Height, Height, 90, 180);
    38. graphicsPath.AddArc(Width - Height, 0, Height, Height, 270, 180);
    39. this.Region = new Region(graphicsPath);
    40. }
    41. }
    42. private void ToggleButton_Paint(object sender, PaintEventArgs e) {
    43. ///Setting
    44. ///
    45. Graphics graphics = e.Graphics;
    46. graphics.SmoothingMode = SmoothingMode.AntiAlias;
    47. graphics.CompositingQuality = CompositingQuality.HighQuality;
    48. graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
    49. graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
    50. int x = ToggleScanner(4, Width - Height + 4);
    51. ///Fore
    52. ///
    53. using(GraphicsPath graphicsPath = new GraphicsPath()) {
    54. graphicsPath.StartFigure();
    55. graphicsPath.AddArc(x, 4, Height - 8, Height - 8, 0, 360);
    56. graphics.FillPath(new SolidBrush(ToggleColor), graphicsPath);
    57. }
    58. }
    59. public T PropertyChange<T>(T value, ref T field) {
    60. field = value;
    61. PropertiesChangeEvent?.Invoke();
    62. Invalidate();
    63. return value;
    64. }
    65. public T PropertyChange<T>(T value) {
    66. PropertiesChangeEvent?.Invoke();
    67. Invalidate();
    68. return value;
    69. }
    70. }

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Facebamm“ ()

    Achso, sorry, du hast ja - 8 gerechnet, da muss es dann ja + 4 sein.

    StartFigure ist überflüssig, nicht CloseFigure, zumindest wenn du nicht nur das Volumen zeichnen willst.

    Control selbst implementiert übrigens bereits IDisposable. Das solltest du oben nicht mehr hinschreiben.

    Du sollst übrigens den GraphicsPath zum Zeichnen des Hintergrunds benutzen, nicht zum Zeichnen der Ellipse. Heute ist irgendwie nicht mein Tag.

    Viele Grüße
    ~blaze~
    Wenn du die Farbe auf Transparent setzt, schon. Schau' dir mal die Flags bei SetStyle an, da kannst du einstellen, dass transparenter Hintergrund unterstützt wird.

    CloseFigure wird nur dann nicht überflüssig sein, wenn du keinen Rand zeichnen willst. Sonst ist der Rahmen nicht geschlossen. StartFigure benötigst du wohl auf jeden Fall nicht.

    Und wie gesagt, es wäre meine Empfehlung von CheckBox zu erben und bei SetStyle UserPaint zu übergeben. Dadurch hast du die Funktionalität der CheckBox bereits vorgefertigt und auch sämtliche Dinge, wie Tastendrücke, Fokus, usw. ohne es selbst implementieren zu müssen.

    Viele Grüße
    ~blaze~
    SetStyle so hab ich
    SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);​

    jetzt zu entscheidenen Frage, soll ich das was jeweils Blau und grau zu sehen ist mit Graphics oder CraphicsPath zeichnen?
    Der GraphicsPath dient dir lediglich dazu, komplexere Geometrien auf einmal zu zeichnen, so wie z.B. die Hintergrundfigur. Der GraphicsPath ist sozusagen eine Art Liste, die alle zu zeichnenden Punkte enthält. Somit zeichnest du nur dein Rechteck mit den zwei Halbkreisen in den Hintergrund und in den Vordergrund den zu verschiebenden Knopf.

    Viele Grüße
    ~blaze~
    aber mit GraphicsPath ist die Qualli nicht so toll -.- -erledigt

    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.ComponentModel;
    3. using System.Drawing;
    4. using System.Drawing.Drawing2D;
    5. using System.Windows.Forms;
    6. public class ToggleButton: Control, IState{
    7. private ToggleState togglestate = ToggleState.On;
    8. [Category("States")]
    9. public ToggleState ToggleState { get => togglestate; set {
    10. togglestate = PropertyChange(value);
    11. Toggled?.Invoke(this, null);
    12. }
    13. }
    14. private Color oncolor = Color.DodgerBlue;
    15. [Category("States")]
    16. public Color OnColor { get => oncolor; set => oncolor = PropertyChange(value);}
    17. private Color offcolor = Color.Red;
    18. [Category("States")]
    19. public Color OffColor { get => offcolor; set => offcolor = PropertyChange(value); }
    20. private Color tooglecolor = Color.White;
    21. [Category("States")]
    22. public Color ToggleColor { get => tooglecolor; set => tooglecolor = PropertyChange(value); }
    23. public event EventHandler Toggled;
    24. public event PropertiesChangeHandle PropertiesChangeEvent;
    25. public ToggleButton() {
    26. SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
    27. DoubleBuffered = true;
    28. ResizeRedraw = true;
    29. BackColor = Color.Transparent;
    30. Paint += ToggleButton_Paint;
    31. Click += (sender, e) => ToggleState = ToggleScanner(ToggleState.Off, ToggleState.On);
    32. //SizeChanged += (sender, e) => SetRoundPath();
    33. }
    34. private T ToggleScanner<T>(T argtrue, T argfalse) => ToggleState == ToggleState.On ? argtrue : argfalse;
    35. private void SetRoundPath() {
    36. using(GraphicsPath graphicsPath = new GraphicsPath()) {
    37. graphicsPath.AddArc(0, 0, Height, Height, 90, 180);
    38. graphicsPath.AddArc(Width - Height, 0, Height, Height, 270, 180);
    39. graphicsPath.CloseFigure();
    40. this.Region = new Region(graphicsPath);
    41. }
    42. }
    43. private void ToggleButton_Paint(object sender, PaintEventArgs e) {
    44. ///Setting
    45. ///
    46. Graphics graphics = e.Graphics;
    47. graphics.SmoothingMode = SmoothingMode.AntiAlias;
    48. graphics.CompositingQuality = CompositingQuality.HighQuality;
    49. graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
    50. graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
    51. int x = ToggleScanner(4, Width - Height + 4);
    52. ///back
    53. ///
    54. using(GraphicsPath graphicsPath = new GraphicsPath()) {
    55. //graphics.FillEllipse(new SolidBrush(ToggleScanner(OnColor, OffColor)), 0, 0, Width, Height);
    56. graphicsPath.AddArc(0, 0, Height, Height, 90, 180);
    57. graphicsPath.AddArc(Width - Height, 0, Height, Height, 270, 180);
    58. graphicsPath.CloseFigure();
    59. graphics.FillPath(new SolidBrush(ToggleScanner(OnColor, OffColor)), graphicsPath);
    60. }
    61. ///Fore
    62. ///
    63. using(GraphicsPath graphicsPath = new GraphicsPath()) {
    64. graphicsPath.StartFigure();
    65. graphicsPath.AddArc(x, 4, Height - 8, Height - 8, 0, 360);
    66. graphicsPath.CloseFigure();
    67. graphics.FillPath(new SolidBrush(ToggleColor), graphicsPath);
    68. }
    69. }
    70. public T PropertyChange<T>(T value, ref T field) {
    71. field = value;
    72. PropertiesChangeEvent?.Invoke();
    73. Invalidate();
    74. return value;
    75. }
    76. public T PropertyChange<T>(T value) {
    77. PropertiesChangeEvent?.Invoke();
    78. Invalidate();
    79. return value;
    80. }
    81. }

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Facebamm“ ()

    @Facebamm Warum malst Du die Button? Mach zwei Bitmaps und ne CheckBox und feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Habe ich bis jetzt immer so gemacht, hat den Vorteil, daß man den Button dann easy skinnen kann, bzw. das dem Anwender anbieten kann.
    Nen gezeichneten finde ich aber auch ganz chick, einfach weil er gezeichnet ist und es auch flexibler ist, da kann mann dann zur Laufzeit viele lustige Dinge mit anstellen.
    @RodFromGermany, weil ich dann die Farben für evtl. andere Projekte nicht anpassen kann :D

    Update ToggleButton
    - DoubleClick event hinzugefügt
    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.ComponentModel;
    3. using System.Drawing;
    4. using System.Drawing.Drawing2D;
    5. using System.Windows.Forms;
    6. namespace FaceMaterial
    7. {
    8. public delegate void PropertiesChangeHandle();
    9. public class ToggleButton : Control
    10. {
    11. private bool togglestate = true;
    12. [Category("States")]
    13. public bool State
    14. {
    15. get => togglestate; set {
    16. togglestate = PropertyChange(value);
    17. Toggled?.Invoke(this, null);
    18. }
    19. }
    20. private Color oncolor = Color.DodgerBlue;
    21. [Category("States")]
    22. public Color OnColor { get => oncolor; set => oncolor = PropertyChange(value); }
    23. private Color offcolor = Color.Red;
    24. [Category("States")]
    25. public Color OffColor { get => offcolor; set => offcolor = PropertyChange(value); }
    26. private Color tooglecolor = Color.White;
    27. [Category("States")]
    28. public Color ToggleColor { get => tooglecolor; set => tooglecolor = PropertyChange(value); }
    29. public event EventHandler Toggled;
    30. public event PropertiesChangeHandle PropertiesChangeEvent;
    31. public ToggleButton()
    32. {
    33. SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
    34. DoubleBuffered = true;
    35. ResizeRedraw = true;
    36. BackColor = Color.Transparent;
    37. Paint += ToggleButton_Paint;
    38. Click += (sender, e) => State = ToggleScanner(false, true);
    39. DoubleClick += (sender, e) => State = ToggleScanner(false, true);
    40. }
    41. private T ToggleScanner<T>(T argtrue, T argfalse) => State ? argtrue : argfalse;
    42. private void SetRoundPath()
    43. {
    44. using (GraphicsPath graphicsPath = new GraphicsPath())
    45. {
    46. graphicsPath.AddArc(0, 0, Height, Height, 90, 180);
    47. graphicsPath.AddArc(Width - Height, 0, Height, Height, 270, 180);
    48. graphicsPath.CloseFigure();
    49. this.Region = new Region(graphicsPath);
    50. }
    51. }
    52. private void ToggleButton_Paint(object sender, PaintEventArgs e)
    53. {
    54. ///Setting
    55. ///
    56. Graphics graphics = e.Graphics;
    57. graphics.SmoothingMode = SmoothingMode.AntiAlias;
    58. graphics.CompositingQuality = CompositingQuality.HighQuality;
    59. graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
    60. graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
    61. int x = ToggleScanner(4, Width - Height + 4);
    62. ///back
    63. ///
    64. using (GraphicsPath graphicsPath = new GraphicsPath())
    65. {
    66. graphicsPath.AddArc(0, 0, Height, Height, 90, 180);
    67. graphicsPath.AddArc(Width - Height, 0, Height, Height, 270, 180);
    68. graphicsPath.CloseFigure();
    69. graphics.FillPath(new SolidBrush(ToggleScanner(OnColor, OffColor)), graphicsPath);
    70. }
    71. ///Fore
    72. ///
    73. using (GraphicsPath graphicsPath = new GraphicsPath())
    74. {
    75. graphicsPath.StartFigure();
    76. graphicsPath.AddArc(x, 4, Height - 8, Height - 8, 0, 360);
    77. graphicsPath.CloseFigure();
    78. graphics.FillPath(new SolidBrush(ToggleColor), graphicsPath);
    79. }
    80. }
    81. public T PropertyChange<T>(T value, ref T field)
    82. {
    83. field = value;
    84. PropertiesChangeEvent?.Invoke();
    85. Invalidate();
    86. return value;
    87. }
    88. public T PropertyChange<T>(T value)
    89. {
    90. PropertiesChangeEvent?.Invoke();
    91. Invalidate();
    92. return value;
    93. }
    94. }
    95. }



    Ich hab mal noch ein Fenster (Form) Programmier :D
    Spoiler anzeigen

    C#-Quellcode

    1. using System.Drawing;
    2. using System.Windows.Forms;
    3. using System.Drawing.Drawing2D;
    4. using System.ComponentModel;
    5. namespace FaceMaterial
    6. {
    7. public class Window : Form
    8. {
    9. #region Toolbar
    10. private int _Toolbarheight;
    11. [Category("Toolbar")]
    12. public int Toolbarheight { get => _Toolbarheight; set => Property(value, ref _Toolbarheight); }
    13. private Color _ToolbarColor;
    14. [Category("Toolbar")]
    15. public Color ToolbarColor { get => _ToolbarColor; set => Property(value, ref _ToolbarColor); }
    16. private ToolbarLoc _ToolbarPosition;
    17. [Category("Toolbar")]
    18. public ToolbarLoc ToolbarPosition { get => _ToolbarPosition; set => Property(value, ref _ToolbarPosition); }
    19. #endregion
    20. #region CloseButton
    21. private Color _CloseButtonColor;
    22. [Category("Close Button")]
    23. public Color CloseButtonColor { get => _CloseButtonColor; set => Property(value, ref _CloseButtonColor); }
    24. private Color _CloseButtonHoverBack;
    25. [Category("Close Button")]
    26. public Color CloseButtonHoverBack { get => _CloseButtonHoverBack; set => Property(value, ref _CloseButtonHoverBack); }
    27. private int _CloseButtonWidth;
    28. [Category("Close Button")]
    29. public int CloseButtonWidth { get => _CloseButtonWidth; set => Property(value, ref _CloseButtonWidth); }
    30. #endregion
    31. private Rectangle ToolbarRectangle;
    32. private Rectangle CloseRectangle;
    33. private bool LeftClick;
    34. private bool _HoverCloseRecangle;
    35. private bool HoverCloseRecangle { get => _HoverCloseRecangle; set => Property(value, ref _HoverCloseRecangle); }
    36. private Point PreviousMousePosition;
    37. private const int WM_NCLBUTTONDOWN = 0xA1;
    38. private const int HT_CAPTION = 0x2;
    39. public Window()
    40. {
    41. SetStyle(ControlStyles.ResizeRedraw | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
    42. DoubleBuffered = true;
    43. ResizeRedraw = true;
    44. Toolbarheight = 32;
    45. ToolbarColor = Color.DodgerBlue;
    46. ToolbarPosition = ToolbarLoc.Top;
    47. CloseButtonHoverBack = Color.Red;
    48. CloseButtonColor = Color.White;
    49. CloseButtonWidth = Toolbarheight + 14;
    50. LeftClick = false;
    51. HoverCloseRecangle = false;
    52. Paint += Window_Paint;
    53. MouseDown += Window_MouseDown;
    54. MouseUp += Window_MouseUp;
    55. MouseClick += Window_MouseClick;
    56. MouseMove += Window_MouseMove;
    57. MouseLeave += Window_MouseLeave;
    58. }
    59. private void Window_MouseLeave(object sender, System.EventArgs e)
    60. {
    61. HoverCloseRecangle = false;
    62. }
    63. private void Window_MouseClick(object sender, MouseEventArgs e) {
    64. if (e.Button == MouseButtons.Left && CloseRectangle.Contains(e.Location))
    65. Application.Exit();
    66. }
    67. private void Window_MouseDown(object sender, MouseEventArgs e)
    68. {
    69. if (e.Button == MouseButtons.Left)
    70. LeftClick = true;
    71. }
    72. private void Window_MouseUp(object sender, MouseEventArgs e)
    73. {
    74. if (e.Button == MouseButtons.Left)
    75. LeftClick = false;
    76. }
    77. private void Window_MouseMove(object sender, MouseEventArgs e)
    78. {
    79. Point mouseloc = e.Location;
    80. bool ishoverclose = CloseRectangle.Contains(mouseloc);
    81. if (HoverCloseRecangle != ishoverclose)
    82. HoverCloseRecangle = ishoverclose;
    83. if ((LeftClick && ToolbarRectangle.Contains(mouseloc)) && !CloseRectangle.Contains(mouseloc))
    84. {
    85. ReleaseCapture();
    86. SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
    87. }
    88. PreviousMousePosition = mouseloc;
    89. }
    90. private void Window_Paint(object sender, PaintEventArgs e)
    91. {
    92. ///Setting
    93. ///
    94. Graphics graphics = e.Graphics;
    95. graphics.SmoothingMode = SmoothingMode.AntiAlias;
    96. int y = (Location)ToolbarPosition == FaceMaterial.Location.Bottom ? Height - Toolbarheight : 0;
    97. ///Head
    98. ///
    99. ToolbarRectangle = new Rectangle(new Point(0, y), new Size(Width, Toolbarheight));
    100. using (SolidBrush headercolor = new SolidBrush(ToolbarColor))
    101. graphics.FillRectangle(headercolor, ToolbarRectangle);
    102. ///CloseButton
    103. ///
    104. ///-Setting
    105. Point closeloc = new Point(ToolbarRectangle.Right - CloseButtonWidth, ToolbarRectangle.Y);
    106. Size closesize = new Size(CloseButtonWidth, Toolbarheight);
    107. CloseRectangle = new Rectangle(closeloc, closesize);
    108. ///-BackGround
    109. if (HoverCloseRecangle)
    110. {
    111. using (SolidBrush brush = new SolidBrush(CloseButtonHoverBack))
    112. graphics.FillRectangle(brush, CloseRectangle);
    113. }
    114. ///-Icon
    115. int padding = 8;
    116. int iconsize = CloseRectangle.Height - padding;
    117. using (Pen pen = new Pen(CloseButtonColor, 3))
    118. {
    119. int margin = (CloseRectangle.Width - iconsize) / 2 ;
    120. int xl = CloseRectangle.Left + margin + (padding / 2);
    121. int xr = CloseRectangle.Right - margin - (padding / 2);
    122. int yt = CloseRectangle.Top + padding;
    123. int yb = CloseRectangle.Bottom - padding;
    124. graphics.DrawLine(pen, xl, yt, xr, yb);
    125. graphics.DrawLine(pen, xl, yb, xr, yt);
    126. }
    127. ///Title
    128. ///
    129. Size titlesize = TextRenderer.MeasureText(Text, Font);
    130. y = (Toolbarheight - titlesize.Height) / 2;
    131. TextRenderer.DrawText(graphics, Text, Font, new Point(4, y), ForeColor);
    132. }
    133. private void Property<T>(T value, ref T field)
    134. {
    135. field = value;
    136. Invalidate();
    137. }
    138. [System.Runtime.InteropServices.DllImport("user32.dll")]
    139. public static extern int SendMessage(System.IntPtr hWnd, int Msg, int wParam, int lParam);
    140. [System.Runtime.InteropServices.DllImport("user32.dll")]
    141. public static extern bool ReleaseCapture();
    142. }
    143. }