Datetimepicker Backcolor

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

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von -Franky-.

    Datetimepicker Backcolor

    Guten Tag

    Ich bin auf der Suche nach einem Datetimepicker-Steuerelement, bei dem man optisch einiges anpassen kann auf Github auf folgenden Code gestossen:
    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.ComponentModel;
    3. using System.Drawing;
    4. using System.Runtime.InteropServices;
    5. using System.Windows.Forms;
    6. public class FlatDateTimePicker : DateTimePicker
    7. {
    8. private Image calendarImage;
    9. private Image calendarImageWhite;
    10. public FlatDateTimePicker()
    11. {
    12. SetStyle(ControlStyles.ResizeRedraw, true);
    13. DoubleBuffered = true;
    14. calendarImage = FlatDateTimePickerExample.Properties.Resources.Calendar;
    15. calendarImageWhite = FlatDateTimePickerExample.Properties.Resources.CalendarWhite;
    16. }
    17. private Color borderColor = Color.DeepSkyBlue;
    18. [DefaultValue(typeof(Color), "RoyalBlue")]
    19. public Color BorderColor
    20. {
    21. get { return borderColor; }
    22. set
    23. {
    24. if (borderColor != value)
    25. {
    26. borderColor = value;
    27. Invalidate();
    28. }
    29. }
    30. }
    31. UpDownRenderer updownRenderer;
    32. protected override void WndProc(ref Message m)
    33. {
    34. if (m.Msg == WM_PAINT)
    35. {
    36. var info = new DATETIMEPICKERINFO();
    37. info.cbSize = Marshal.SizeOf(info);
    38. SendMessage(Handle, DTM_GETDATETIMEPICKERINFO, IntPtr.Zero, ref info);
    39. var clientRect = new Rectangle(0, 0, Width, Height);
    40. var dropDownButtonRect = new Rectangle(info.rcButton.L, info.rcButton.T,
    41. info.rcButton.R - info.rcButton.L, clientRect.Height);
    42. var dropDownRect = dropDownButtonRect;
    43. var imageRect = Rectangle.Empty;
    44. if (info.rcButton.R - info.rcButton.L > SystemInformation.HorizontalScrollBarArrowWidth)
    45. {
    46. var w = dropDownButtonRect.Width / 2;
    47. imageRect = dropDownButtonRect;
    48. imageRect.Width = w;
    49. dropDownRect.X += w;
    50. dropDownRect.Width = w;
    51. }
    52. var checkBoxRect = new Rectangle(info.rcCheck.L, info.rcCheck.T,
    53. info.rcCheck.R - info.rcCheck.L, clientRect.Height);
    54. var innerRect = new Rectangle(checkBoxRect.Right + 1, 1,
    55. clientRect.Width - dropDownButtonRect.Width - checkBoxRect.Width - (ShowCheckBox ? 3 : 1),
    56. clientRect.Height - 2);
    57. if (RightToLeft == RightToLeft.Yes && RightToLeftLayout == true)
    58. {
    59. dropDownButtonRect.X = clientRect.Width - dropDownButtonRect.Right;
    60. dropDownButtonRect.Width += 1;
    61. innerRect.X -= clientRect.Width - innerRect.X;
    62. innerRect.Width += 1;
    63. imageRect.X = clientRect.Width - imageRect.Right;
    64. dropDownRect.X = clientRect.Width - dropDownRect.Right;
    65. dropDownRect.Width += 1;
    66. }
    67. var middle = new Point(dropDownRect.Left + dropDownRect.Width / 2,
    68. dropDownRect.Top + dropDownRect.Height / 2);
    69. var arrow = new Point[]
    70. {
    71. new Point(middle.X - 3, middle.Y - 2),
    72. new Point(middle.X + 4, middle.Y - 2),
    73. new Point(middle.X, middle.Y + 2)
    74. };
    75. var borderColor = Enabled ? BorderColor : Color.LightGray;
    76. var ps = new PAINTSTRUCT();
    77. bool shoulEndPaint = false;
    78. IntPtr dc;
    79. if (m.WParam == IntPtr.Zero)
    80. {
    81. dc = BeginPaint(Handle, ref ps);
    82. m.WParam = dc;
    83. shoulEndPaint = true;
    84. }
    85. else
    86. {
    87. dc = m.WParam;
    88. }
    89. var rgn = CreateRectRgn(innerRect.Left, innerRect.Top, innerRect.Right, innerRect.Bottom);
    90. SelectClipRgn(dc, rgn);
    91. DefWndProc(ref m);
    92. DeleteObject(rgn);
    93. rgn = CreateRectRgn(clientRect.Left, clientRect.Top, clientRect.Right, clientRect.Bottom);
    94. SelectClipRgn(dc, rgn);
    95. using (var g = Graphics.FromHdc(dc))
    96. {
    97. if (ShowCheckBox)
    98. {
    99. var r = Rectangle.FromLTRB(info.rcCheck.L, info.rcCheck.T,
    100. info.rcCheck.R, info.rcCheck.B);
    101. if (Checked)
    102. DrawFrameControl(dc, ref info.rcCheck, DFC_MENU, DFCS_MENUCHECK);
    103. else
    104. g.FillRectangle(SystemBrushes.Window, r);
    105. if (!Enabled)
    106. {
    107. using (var b = new SolidBrush(Color.FromArgb(200, SystemColors.Control)))
    108. g.FillRectangle(b, r);
    109. }
    110. var r2 = r;
    111. r2.Width -= 1; r2.Height -= 1;
    112. g.DrawRectangle(Enabled ? SystemPens.WindowText : SystemPens.GrayText, r2);
    113. r2.Inflate(1, 1);
    114. g.DrawRectangle(Pens.White, r2);
    115. }
    116. if (ShowUpDown)
    117. {
    118. if (updownRenderer == null && info.hwndUD != IntPtr.Zero)
    119. updownRenderer = new UpDownRenderer(info.hwndUD);
    120. updownRenderer.ButtonColor = this.BorderColor;
    121. updownRenderer.ArrowColor = Color.Black;
    122. }
    123. else
    124. {
    125. var buttonColor = Enabled ? BorderColor : Color.LightGray;
    126. var arrorColor = Color.Black;
    127. var imageToRender = calendarImage;
    128. if(dropDownButtonRect.Contains(PointToClient(Cursor.Position)))
    129. {
    130. arrorColor = Color.White;
    131. imageToRender = calendarImageWhite;
    132. }
    133. using (var brush = new SolidBrush(buttonColor))
    134. g.FillRectangle(brush, dropDownButtonRect);
    135. if (imageRect != Rectangle.Empty)
    136. g.DrawImage(imageToRender,
    137. imageRect.Left + ((imageRect.Width - imageToRender.Width) / 2),
    138. imageRect.Top + ((imageRect.Height - imageToRender.Height) / 2),
    139. calendarImage.Width,
    140. calendarImage.Height);
    141. using (var brush = new SolidBrush(arrorColor))
    142. g.FillPolygon(brush, arrow);
    143. }
    144. using (var pen = new Pen(borderColor))
    145. g.DrawRectangle(pen, 0, 0,
    146. ClientRectangle.Width - 1, ClientRectangle.Height - 1);
    147. }
    148. if (shoulEndPaint)
    149. EndPaint(Handle, ref ps);
    150. DeleteObject(rgn);
    151. }
    152. else
    153. {
    154. base.WndProc(ref m);
    155. }
    156. }
    157. private class UpDownRenderer : NativeWindow
    158. {
    159. public UpDownRenderer(IntPtr hwnd)
    160. {
    161. this.AssignHandle(hwnd);
    162. SetWindowTheme(Handle, string.Empty, string.Empty);
    163. }
    164. private bool Enabled => IsWindowEnabled(Handle);
    165. private Point PointToClient(Point p)
    166. {
    167. var pt = new POINT() { X = p.X, Y = p.Y };
    168. ScreenToClient(Handle, ref pt);
    169. return new Point(pt.X, pt.Y);
    170. }
    171. private Rectangle ClientRectangle
    172. {
    173. get
    174. {
    175. var r = new RECT();
    176. GetWindowRect(Handle, ref r);
    177. return new Rectangle(0, 0, r.R - r.L, r.B - r.T);
    178. }
    179. }
    180. public Color ButtonColor { get; set; }
    181. public Color ArrowColor { get; set; }
    182. private Point[] GetDownArrow(Rectangle r)
    183. {
    184. var middle = new Point(r.Left + r.Width / 2, r.Top + r.Height / 2);
    185. return new Point[]
    186. {
    187. new Point(middle.X - 3, middle.Y - 1),
    188. new Point(middle.X + 4, middle.Y - 1),
    189. new Point(middle.X, middle.Y + 3)
    190. };
    191. }
    192. private Point[] GetUpArrow(Rectangle r)
    193. {
    194. var middle = new Point(r.Left + r.Width / 2, r.Top + r.Height / 2);
    195. return new Point[]
    196. {
    197. new Point(middle.X - 4, middle.Y + 2),
    198. new Point(middle.X + 4, middle.Y + 2),
    199. new Point(middle.X, middle.Y - 3)
    200. };
    201. }
    202. protected override void WndProc(ref Message m)
    203. {
    204. var enabled = Enabled;
    205. var clientRectangle = ClientRectangle;
    206. var backColor = enabled ? ButtonColor : Color.LightGray;
    207. if (m.Msg == WM_MOUSEMOVE)
    208. {
    209. var r = clientRectangle;
    210. var rect = new RECT() { L = r.Left, T = r.Top, R = r.Right, B = r.Bottom };
    211. InvalidateRect(Handle, ref rect, false);
    212. }
    213. if (m.Msg == WM_PAINT)
    214. {
    215. var s = new PAINTSTRUCT();
    216. BeginPaint(Handle, ref s);
    217. using (var g = Graphics.FromHdc(s.hdc))
    218. {
    219. var context = BufferedGraphicsManager.Current;
    220. using (var bg = context.Allocate(g, clientRectangle))
    221. {
    222. var gg = bg.Graphics;
    223. var r1 = new Rectangle(0, 0,
    224. clientRectangle.Width, clientRectangle.Height / 2);
    225. var r2 = new Rectangle(0, clientRectangle.Height / 2,
    226. clientRectangle.Width, clientRectangle.Height / 2 + 1);
    227. using (var backBrush = new SolidBrush(backColor))
    228. {
    229. gg.FillRectangle(backBrush, r1);
    230. gg.FillRectangle(backBrush, r2);
    231. }
    232. gg.DrawLine(Pens.White, r1.Left, r1.Bottom, r1.Right, r1.Bottom);
    233. gg.DrawLine(Pens.White, r2.Left, r2.Top, r2.Right, r2.Top);
    234. if (r1.Contains(PointToClient(Cursor.Position)))
    235. gg.FillPolygon(Brushes.White, GetUpArrow(r1));
    236. else
    237. gg.FillPolygon(Brushes.Black, GetUpArrow(r1));
    238. if (r2.Contains(PointToClient(Cursor.Position)))
    239. gg.FillPolygon(Brushes.White, GetDownArrow(r2));
    240. else
    241. gg.FillPolygon(Brushes.Black, GetDownArrow(r2));
    242. bg.Render(g);
    243. }
    244. }
    245. m.Result = (IntPtr)1;
    246. base.WndProc(ref m);
    247. EndPaint(Handle, ref s);
    248. }
    249. else
    250. base.WndProc(ref m);
    251. }
    252. }
    253. const int WM_PAINT = 0xF;
    254. const int DTM_FIRST = 0x1000;
    255. const int WM_ERASEBKGND = 0x14;
    256. const int DTM_GETDATETIMEPICKERINFO = DTM_FIRST + 14;
    257. const int WM_MOUSEMOVE = 0x0200;
    258. const int DFC_MENU = 2;
    259. const int DFCS_MENUCHECK = 0x0001;
    260. [DllImport("user32.dll")]
    261. static extern bool DrawFrameControl(IntPtr hDC, ref RECT rect, int type, int state);
    262. [DllImport("user32.dll")]
    263. static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
    264. IntPtr wParam, ref DATETIMEPICKERINFO info);
    265. [DllImport("user32.dll")]
    266. static extern IntPtr SendMessage(IntPtr hWnd, int Msg,
    267. IntPtr wParam, IntPtr info);
    268. [StructLayout(LayoutKind.Sequential)]
    269. struct RECT
    270. {
    271. public int L, T, R, B;
    272. }
    273. [StructLayout(LayoutKind.Sequential)]
    274. struct POINT
    275. {
    276. public int X, Y;
    277. }
    278. [StructLayout(LayoutKind.Sequential)]
    279. struct DATETIMEPICKERINFO
    280. {
    281. public int cbSize;
    282. public RECT rcCheck;
    283. public int stateCheck;
    284. public RECT rcButton;
    285. public int stateButton;
    286. public IntPtr hwndEdit;
    287. public IntPtr hwndUD;
    288. public IntPtr hwndDropDown;
    289. }
    290. [DllImport("user32.dll")]
    291. private static extern bool IsWindowEnabled(IntPtr hWnd);
    292. [DllImport("user32.dll")]
    293. static extern bool GetWindowRect(IntPtr hWnd, ref RECT rect);
    294. [StructLayout(LayoutKind.Sequential)]
    295. public struct PAINTSTRUCT
    296. {
    297. public IntPtr hdc;
    298. public bool fErase;
    299. public int rcPaint_left;
    300. public int rcPaint_top;
    301. public int rcPaint_right;
    302. public int rcPaint_bottom;
    303. public bool fRestore;
    304. public bool fIncUpdate;
    305. public int reserved1;
    306. public int reserved2;
    307. public int reserved3;
    308. public int reserved4;
    309. public int reserved5;
    310. public int reserved6;
    311. public int reserved7;
    312. public int reserved8;
    313. }
    314. [DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
    315. static extern int SetWindowTheme(IntPtr hwnd, string pszSubAppName, string pszSubIdList);
    316. [DllImport("user32.dll")]
    317. private static extern IntPtr BeginPaint(IntPtr hWnd, [In, Out] ref PAINTSTRUCT lpPaint);
    318. [DllImport("user32.dll")]
    319. private static extern bool EndPaint(IntPtr hWnd, ref PAINTSTRUCT lpPaint);
    320. [DllImport("gdi32.dll")]
    321. public static extern int SelectClipRgn(IntPtr hDC, IntPtr hRgn);
    322. [DllImport("gdi32.dll")]
    323. internal static extern bool DeleteObject(IntPtr hObject);
    324. [DllImport("gdi32.dll")]
    325. private static extern IntPtr CreateRectRgn(int x1, int y1, int x2, int y2);
    326. [DllImport("user32.dll")]
    327. static extern int ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
    328. [DllImport("user32.dll")]
    329. static extern int InvalidateRect(IntPtr hWnd, ref RECT lpRect, bool bErase);
    330. }


    Dies funktioniert zwar sehr gut, ich möchte aber auch die Hintergrundfarbe ändern. Hiermit könnte ich zwar die Backcolor ändern, aber dabei wird auch der Inhalt überschrieben:

    C#-Quellcode

    1. using (var g=Graphics.FromHdc(dc))
    2. {
    3. using (var bcBrush = new SolidBrush(DefaultBackColor))
    4. {
    5. g.FillRectangle(bcBrush, innerRect);
    6. }
    7. {


    Ich kenne mich weder mit der Entwicklung von Steuerelementen noch mit C# aus und hoffe auf eure Unterstützung.

    aufgrund des Codeumfangs Spoiler hinzugefügt ~VaporiZed

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    AKP schrieb:

    aber dabei wird auch der Inhalt überschrieben:
    Dann rufst Du die Paint-Prozeduren in der verkehrten Reihenfolge auf.
    Zuerst den Hintergrund darstellen, dann den Vordergrund.
    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!

    AKP schrieb:

    Ich bin auf der Suche nach einem Datetimepicker-Steuerelement, bei dem man optisch einiges anpassen kann

    AKP schrieb:

    Ich kenne mich weder mit der Entwicklung von Steuerelementen noch mit C# aus

    Da sind die Erfolgsaussichten ziemlich mau.
    Ich habs nicht probiert, aber beim Standard-DateTimePicker kann man die BackColor nicht ändern, oder?
    Das Github-Teil erbt vom Standard-DateTimePicker - da wird es das auch nicht können.

    Ich hab sowas mal mit Textbox versucht - mit dem .Net-Framework-Instrumentarium ging da nix.
    Vielleicht kann man was mit WinApi zaubern, aber das ist ziemlich speziell und eher nix für Anfänger.

    ErfinderDesRades schrieb:

    Da sind die Erfolgsaussichten ziemlich mau.
    Ich habs nicht probiert, aber beim Standard-DateTimePicker kann man die BackColor nicht ändern, oder?
    Das Github-Teil erbt vom Standard-DateTimePicker - da wird es das auch nicht können.

    Im Prinzip ist das ein OwnerDrawing der im WndProc, der hier zum Teil bei der Message WM_PAINT, stattfindet. Die Frage wäre nun ob das die richtige Message ist, um die Hintergrundfarbe zu ändern. Da gibt es ja noch ein Haufen Messages mehr. Vllt ist es auch die Message WM_ERASEBKGND. Google, google, ach gucke: stackoverflow.com/questions/19…f-a-datetimepicker-in-net
    Mfg -Franky-
    Hallo

    Besten Dank für eure Antworten. Wenn ich das einfüge:

    C#-Quellcode

    1. ​if(m.Msg == WM_ERASEBKGND)
    2. {
    3. using(var g = Graphics.FromHdc(m.WParam))
    4. {
    5. using(var b = new SolidBrush(_backColor))
    6. {
    7. g.FillRectangle(b, ClientRectangle);
    8. }
    9. }
    10. return;
    11. }


    Klappt es leider nicht. Beim Debuggen wird zwar der Hintergrund eingefärbt bis zur Zeile 101:

    C#-Quellcode

    1. ​ DefWndProc(ref m);

    Dann ist die Formatierung wieder weg.

    Wenn ich das Beispiel von deinem Link in VB-Net nehme, wird zwar der Hintergrund eingefärbt, aber die Cursormarkierung fehlt.
    ich sachja: es ist tricky.
    Normalerweise kann man bei .Net-Controls die BackColor festlegen, aber bei manchen Controls ist das von .Net nicht vorgesehen - und das hat vermutlich auch einen Grund.
    Und da wäre nun Code zu finden, der .Net quasi hintergeht - wie gesagt: bei Textbox habichs nicht hingekriegt.

    AKP schrieb:

    aber die Cursormarkierung fehlt.
    genau sowas.
    Das Zeichnen eines editierbaren Controls, mit blinkendem Cursor, an der richtigen Stelle, und so - ich vermute, das ist sehr komplex, und das mag auch der Grund sein, warum .Net bei derartigen Controls das Paint-Event abgeklemmt hat, und auch keine BackColor-Property anbietet etc.

    ErfinderDesRades schrieb:

    aber bei manchen Controls ist das von .Net nicht vorgesehen - und das hat vermutlich auch einen Grund

    Nö. Ich würde sagen das MS denkt, wir bieten dem Programmierer nur Standard-Eigenschaften. Alles andere kann der der Programmierer ja selbst implementieren oder wird gut versteckt/nicht verfügbar gemacht weil sonst könnte man ja Sachen anstellen, die MS vllt. nicht möchte. zB das Handle vom TaskDialog ab NET5 wird nicht dem Programmierer nicht zur Verfügung gestellt. Warum? Hat MS Angst das man diesen dann Subclassen könnte um den Dialog zu manipulieren?

    Nur weil ein Control eine bestimmte Eigenschaft nicht besitzt, heißt das noch lange nicht das man das nicht nachimplementieren kann. Entweder, wenn es eine entsprechende Control-Message gibt, sendet man diese per SendMessage an das Control oder man betreibt OwnerDrawing. Letzteres ist natürlich aufwendiger. 3 Bsp für fehlende Eigenschaften: ProgressBar Eigenschaft State (Normal, Error, Paused) nicht vorhanden. Per SendMessage und PBM_SETSTATE nachrüstbar. Hintergrundfarbe bei Scrollbars. Message WM_CTLCOLORSCROLLBAR des Parent abfangen und hier eine Farbe für die Scrollbar festlegen. SpellCheck in einer Winforms-RTB. Nicht vorhanden. Ebenfalls per Sendmessage mit entsprechenden Messages nachrüstbar.

    OwnerDrawing ist ein ganz anderes Thema. Da muss man halt alles selber zeichnen. Also auch die Markierung wenn man im DateTimePicker auf den Text (Tag, Monat, Jahr) klickt. Alternativ erstellt man sich per API CreateWindowEx sein eigenes DateTimePicker-Control und per API RegisterClassEx -> Struct WNDCLASSEX <- hbrBackground setzt man die BackColor-Eigenschaft. Machbar ist es auf jeden Fall. Nur der Weg dahin ist halt aufwendig.

    ErfinderDesRades schrieb:

    wie gesagt: bei Textbox habichs nicht hingekriegt

    Auch das geht wie der ScreenShot zeigt. Hier wird allerdings ein BitmapBrush, anstelle eines SolidBrush, verwendet um den Hintergrund/BackColor der TextBox zu manipulieren und um den Cursor muss ich mir dabei keine Gedanken machen. Ja, ist mit VB6 gemacht und was da geht, sollte in .NET erst recht Möglich sein.
    Bilder
    • TextBox.png

      88,25 kB, 591×334, 44 mal angesehen
    Mfg -Franky-

    ErfinderDesRades schrieb:

    aber was nützt das nun dem TE?

    Schauen ob es evtl. eine entsprechende Control-Message gibt die man per SendMessage an das Control senden kann (kann ich jetzt schon sagen, gibt es nicht).
    OwnerDrawing: selbst alles zeichnen
    Selbst das Control per CreateWindowEx, RegisterClassEx, mit einer anderen BackColor (hbrBackground) erstellen.

    Na wenn das keine Hinweise sind, weis ich auch nicht.

    Edit: Einen hab ich noch. Müsste man mal in .NET testen. Unter VB6 geht es.

    Visual Basic-Quellcode

    1. Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long
    2. Private Const GCL_HBRBACKGROUND = -10
    3. Private Declare Function SetClassLong Lib "user32" Alias "SetClassLongA" ( _
    4. ByVal hWnd As Long, _
    5. ByVal nIndex As Long, _
    6. ByVal dwNewLong As Long) As Long
    7. Private Sub Form_Load()
    8. SetClassLong DTPicker1.hWnd, GCL_HBRBACKGROUND, CreateSolidBrush(vbCyan)
    9. End Sub


    Aber Achtung! Das wirkt sich dann auf alle DateTimePicker Controls aus, die von der gleichen WNDCLASS stammen.
    Mfg -Franky-

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

    Ja, sind sicher Hinweise, aber auf zu hohem Niveau.
    dein letztes Snippet ist eiglich einfach, aber immer noch zu hoch: es setzt ja voraus, dass man vb6 nach .Net-Code konvertieren kann.
    Aber habichmal gemacht, aus Interesse und für den TE:

    VB.NET-Quellcode

    1. Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Integer) As Integer
    2. Private Const GCL_HBRBACKGROUND = -10
    3. Private Declare Function SetClassLong Lib "user32" Alias "SetClassLongA" (
    4. ByVal hWnd As IntPtr,
    5. ByVal nIndex As Integer,
    6. ByVal dwNewLong As Integer) As Integer
    7. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    8. SetClassLong(DateTimePicker2.Handle, GCL_HBRBACKGROUND, CreateSolidBrush(9))
    9. End Sub
    Tut sich aber nichts.
    Kann sein, es liegt daran, dass ich nicht den Wert von vbCyan weiss - ich hab einfach 9 eingesetzt.
    @ErfinderDesRades
    Jau, der DateTimePicker unter .Net verweigert alles was ich aus VB6 Zeiten kenne um die BackColor zu ändern. Außer Subclassing und WM_xxx Messages auswerten und selber zeichnen. vbCyan wäre 0xFFFF00 gewesen.

    Also bleibt nur OwnerDrawing (Me.SetStyle(ControlStyles.UserPaint, True) wenn man ein vorhandenes Control manipulieren möchte. Denke das die WndProc schon die richtige Stelle ist. Ich kann da evtl. ein kleines Tool empfehlen, mit dem man entsprechende WindowsMessages (WM_xxx) ermitteln kann wenn man bestimmte Aktionen auf einem Control durchführt. Also wenn der Text markiert wird bzw. einen Text (Tag, Monat, Jahr) anklickt. Den Rest müsste man sich ergoogeln und nachbauen. docs.microsoft.com/de-de/windows/win32/controls/control-spy Schade das Control Spy nicht weiter entwickelt wird weil da doch so einige Control-Messages fehlen. Zum Ausprobieren einiger Control-Messages und welche Const zum Erstellen von Controls (CreateWindowEx) was bewirkt, reicht es auf jeden Fall.
    Mfg -Franky-