更改带有 ShowCheckBox 属性 集的 DateTimePicker 的边框颜色

Changing the border color of a DateTimePicker with ShowCheckBox property set

使用 DateTimePicker 的 属性 更改边框颜色对外观绝对没有影响。如果日期时间选择器的字段为空(showCheckbox 属性 true 并且复选框未选中,如何将边框颜色更改为红色以进行错误验证。

Edit1:我在谈论 Windows 表格。我也尝试了下面的代码,但没有成功。
Edit2:比如DateTimePicker控件的TextChanged事件或者ShowCheckbox是未勾选事件,如果文本为空,则边框颜色变为红色。

Edit3: https://ibb.co/T04W8M0 如果未选中该复选框并且文本区域显示为空,则 border-color 应为红色。

https://www.codeproject.com/Articles/30660/A-DateTimePicker-with-working-BackColorShowCheckbox为真,此处不设置)

Changing the background color of a DateTimePicker in .NETShowCheckbox为真,此处不设置)

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
    Graphics g = this.CreateGraphics();

    //The dropDownRectangle defines position and size of dropdownbutton block, 
    //the width is fixed to 17 and height to 16. 
    //The dropdownbutton is aligned to right
    Rectangle dropDownRectangle = 
       new Rectangle(ClientRectangle.Width - 17, 0, 17, 16);
    Brush bkgBrush;
    ComboBoxState visualState;

    //When the control is enabled the brush is set to Backcolor, 
    //otherwise to color stored in _backDisabledColor
    if (this.Enabled) {
         bkgBrush = new SolidBrush(this.BackColor);
         visualState = ComboBoxState.Normal;
    }
    else {
        bkgBrush = new SolidBrush(this._backDisabledColor);
        visualState = ComboBoxState.Disabled;
    }

    // Painting...in action

    //Filling the background
    g.FillRectangle(bkgBrush, 0, 0, ClientRectangle.Width, ClientRectangle.Height);
    
    //Drawing the datetime text
    g.DrawString(this.Text, this.Font, Brushes.Black, 0, 2);

    //Drawing the dropdownbutton using ComboBoxRenderer
    ComboBoxRenderer.DrawDropDownButton(g, dropDownRectangle, visualState);

    g.Dispose();
    bkgBrush.Dispose();
}

如果您只想更改 DateTimePicker 的边框颜色,以防当前 DateTime 未根据某些条件(您必须定义)通过验证,您可以使用自定义控件派生的 DateTimePicker,覆盖WndProc, trap WM_PAINT 并使用所选颜色绘制边框。

您发布的代码阻止控件使用默认值绘制自身。虽然这不是禁止,但您必须重新绘制控件的所有部分,包括文本选择字段(在本例中为特殊字段, C# 中不可用的功能)。
在这种情况下,用户无法手动编辑日期时间值(使用文本框字段)。

▶ 此处,ValidateDateTimeValue() 方法将验证当前日期时间值并在验证过程失败时更改边框颜色。
使其适应您实际需要验证的任何条件,目前尚不清楚描述中的内容。 Text通常不为空,除非CustomFormat属性设置为白色space(或者Binding的Format事件改变以类似的方式)。

ErrorBorderColor public 属性 允许更改验证失败时绘制的边框颜色。

IsValidDateTime 属性 returns 验证程序的结果。

using System.Drawing;

public class DateTimePickerEx : DateTimePicker
{
    private const int WM_PAINT = 0x000F;
    private Color m_ErrorBorderColor = Color.Red;
    private bool m_IsValidDateTime = true;

    public DateTimePickerEx() { } 

    public Color ErrorBorderColor {
        get => m_ErrorBorderColor;
        set {
            if (m_ErrorBorderColor != value) {
                m_ErrorBorderColor = value;
                this.Invalidate();
            }
        }
    }

    public bool IsValidDateTime {
        get => m_IsValidDateTime;
        private set {
            m_IsValidDateTime = value;
            this.Invalidate();
        }
    }

    public void ValidateDateTimeValue()
    {
        bool isValid = true;
        // Validate the new Value. e.g.
        if (this.ShowCheckBox && !this.Checked) {
            // A placeholder sub-condition: the Text is can only appear empty when 
            // setting a CustomFormat  = " "
            if (this.Text.Trim() == string.Empty) {
                isValid = false;
            }
        }
        // Set the results of the validation to the property.
        // This will also set the Border Color
        IsValidDateTime = isValid;
    }

    protected override void OnValueChanged(EventArgs e)
    {
        base.OnValueChanged(e);
        if (!this.IsHandleCreated) return;
        ValidateDateTimeValue();
    }

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg) {
            case WM_PAINT:
                base.WndProc(ref m);
                if (!m_IsValidDateTime) {
                    using (var g = Graphics.FromHwnd(m.HWnd)) {
                        var rect = new Rectangle(0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1);
                        g.DrawRectangle(Pens.Red, rect);
                    }
                    m.Result = IntPtr.Zero;
                }
                break;
            default:
                base.WndProc(ref m);
                break;
        }
    }
}