Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic text Colour on DateTimePicker UserControl - WinForms

I am creating a windows user control based on a DateTimePicker. The control is set to show just the time so it displays thus:

DateTimePicker time only

I have a public property TimeIsValid:

public bool TimeIsValid
{
   get { return _timeIsValid; }
   set
   {
      _timeIsValid = value;
      Refresh();
   }
}

and when this is set to false I want the text to turn red. So I have overridden the OnPaint with the following code:

    protected override void OnPaint(PaintEventArgs e)
     {
        base.OnPaint(e);

        e.Graphics.DrawString(Text, Font, 
        _timeIsValid ? new SolidBrush(Color.Black) : new SolidBrush(Color.Red),
        ClientRectangle);

     }

This did nothing. So in the in the constructor I have added the following code:

public DateTimePicker(IContainer container)
{
    container.Add(this);
    InitializeComponent();
    //code below added
    this.SetStyle(ControlStyles.UserPaint, true);
}

Which works, kind of, but causes some alarming results i.e.

  • The control does not appear selected even when it is.
  • Clicking on the up/down controls changes the underlying value of the control but does not always change the visible value.
  • The control does not repaint properly when changing its value via another control but moving a mouse over the control seems to force the repaint.

Look at this weirdness for instance ...

Partially repainted control

What am I missing?

like image 971
RedEyedMonster Avatar asked Oct 21 '22 19:10

RedEyedMonster


1 Answers

It's a lousy control to try to inherit from, but some things to try:

Add the double-buffer:

this.SetStyle(ControlStyles.UserPaint | 
              ControlStyles.OptimizedDoubleBuffer, true);

Clear the background and draw the highlight if the control has the focus:

protected override void OnPaint(PaintEventArgs e) {
  e.Graphics.Clear(Color.White);
  Color textColor = Color.Red;
  if (this.Focused) {
    textColor = SystemColors.HighlightText;
    e.Graphics.FillRectangle(SystemBrushes.Highlight, 
                             new Rectangle(4, 4, this.ClientSize.Width - SystemInformation.VerticalScrollBarWidth - 8, this.ClientSize.Height - 8));
  }
  TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle, textColor, Color.Empty, TextFormatFlags.VerticalCenter);
  base.OnPaint(e);
}

and invalidate the control when the value changes:

protected override void OnValueChanged(EventArgs eventargs) {
  base.OnValueChanged(eventargs);
  this.Invalidate();
}
like image 103
LarsTech Avatar answered Oct 30 '22 22:10

LarsTech