Goal is to create DateTimePicker similar to the screen shot of this question.
First attempt overriding OnPaint:
public class MyDateTimePicker : DateTimePicker
{
private Image _image;
public MyDateTimePicker() : base()
{
SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw |
ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
}
[Browsable(true)]
public override Color BackColor
{
get
{
return base.BackColor;
}
set
{
base.BackColor = value;
}
}
[Category("Appearance")]
public Color BorderColor { get; set; } = Color.Black;
[Category("Appearance")]
public Color TextColor { get; set; } = Color.Black;
[Category("Appearance")]
public Image Image
{
get
{
return _image;
}
set
{
_image = value;
Invalidate();
}
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
// Fill the Background
e.Graphics.FillRectangle(new SolidBrush(this.BackColor), 0, 0, ClientRectangle.Width, ClientRectangle.Height);
// Draw DateTime text
e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(TextColor), 5, 2);
// Draw Icon
if (_image != null)
{
Rectangle im_rect = new Rectangle(ClientRectangle.Width - 20, 2, ClientRectangle.Height - 4, ClientRectangle.Height - 4);
e.Graphics.DrawImage(_image, im_rect);
}
// Draw Border
e.Graphics.DrawRectangle(Pens.Black, new Rectangle(0, 0, ClientRectangle.Width - 1, ClientRectangle.Height - 1));
}
}
This solution has the following issues: date fields are not clickable, text artifacts when changing date with arrow keys, narrow clickable area of the button.
Second solution overriding WndProc:
public class MyDateTimePicker : DateTimePicker
{
private const int WM_PAINT = 0x000F;
private Color _borderColor = Color.Black;
public MyDateTimePicker() { }
[Category("Appearance")]
public Color BorderColor
{
get { return _borderColor; }
set
{
if (_borderColor != value)
{
_borderColor = value;
this.Invalidate();
}
}
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_PAINT:
base.WndProc(ref m);
using (var g = Graphics.FromHwnd(m.HWnd))
{
var rect = new Rectangle(0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1);
g.DrawRectangle(new Pen(this.BorderColor), rect);
}
m.Result = IntPtr.Zero;
break;
default:
base.WndProc(ref m);
break;
}
}
}
This solution lacks the customization of the button. Maybe anyone knows how to customize button in this way, or how to solve issues of the first solution?
Also if it is possible I would like to change the height of DateTimePicker to match height of ComboBox (currently they differ by 1px).
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…