可以为空值、可以删除显示日期的DateTimePicker

    .Net的DateTimePicker没有提供空白显示的功能,一旦选择了日期,也不可删除而显示空白,且在非Windows XP主体环境下也没有Flat显示功能,直接放在界面上还真不太美观,于是着手改造了一下。
     如果想出时显示时日期为空,则设置Format属性为Custom,设置CustomFormat属性为空格" "即可:

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using Srims.UI.Controls;
namespace DrawFlat
{
    [ToolboxBitmap(
typeof(System.Windows.Forms.DateTimePicker))]
    
public class FlatDateTimePicker: DateTimePicker
    
{
        
ComboInfoHelper

        [DllImport(
"user32.dll", EntryPoint="SendMessageA")]
        
private static extern int SendMessage (IntPtr hwnd, int wMsg, IntPtr wParam, int lParam);

        [DllImport(
"user32")]
        
private static extern IntPtr GetWindowDC (IntPtr hWnd );

        [DllImport(
"user32")]
        
private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC );

        
const int WM_ERASEBKGND = 0x14;
        
const int WM_PAINT = 0xF;
        
const int WM_NC_HITTEST = 0x84;
        
const int WM_NC_PAINT = 0x85;
        
const int WM_PRINTCLIENT = 0x318;
        
const int WM_SETCURSOR = 0x20;


        
private Pen BorderPen  = new Pen(Color.Black, 2);
        
private Pen BorderPenControl  = new Pen(SystemColors.ControlDark, 2);
        
private bool DroppedDown = false;
        
private int InvalidateSince = 0;
        
private static int DropDownButtonWidth = 17;

        
static FlatDateTimePicker()
        
{
            
// 2 pixel extra is for the 3D border around the pulldown button on the left and right
            DropDownButtonWidth = ComboInfoHelper.GetComboDropDownWidth()+2 ;    
        }


        
public FlatDateTimePicker()
            : 
base()
        
{
            
this.SetStyle(ControlStyles.DoubleBuffer, true);
            
//this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        }

        
protected override void OnValueChanged(EventArgs eventargs)
        
{
            
base.OnValueChanged (eventargs);
            
this.Invalidate();
        }


        
protected override void WndProc(ref Message m)
        
{
            
//IntPtr hDC = IntPtr.Zero;
            
//Graphics gdc = null;
            
//switch (m.Msg)
            
//{
            
//    case WM_NC_PAINT:
            
//        hDC = GetWindowDC(m.HWnd);
            
//        gdc = Graphics.FromHdc(hDC);
            
//        SendMessage(this.Handle, WM_ERASEBKGND, hDC, 0);
            
//        SendPrintClientMsg();
            
//        SendMessage(this.Handle, WM_PAINT, IntPtr.Zero, 0);
            
//        OverrideControlBorder(gdc);
            
//        //PaintFlatControlBorder(this, gdc);
            
//        m.Result = (IntPtr)1;    // indicate msg has been processed
            
//        ReleaseDC(m.HWnd, hDC);
            
//        gdc.Dispose();
            
//        break;
            
//    case WM_PAINT:
            
//        base.WndProc(ref m);
            
//        hDC = GetWindowDC(m.HWnd);
            
//        gdc = Graphics.FromHdc(hDC);
            
//        OverrideDropDown(gdc);
            
//        OverrideControlBorder(gdc);
            
//        //PaintFlatControlBorder(this, gdc);
            
//        ReleaseDC(m.HWnd, hDC);
            
//        gdc.Dispose();
            
//        break;
            
//    /*
            
//    // We don't need this anymore, handle by WM_SETCURSOR
            
//    case WM_NC_HITTEST: 
            
//        base.WndProc(ref m);
            
//        if (DroppedDown)
            
//        {
            
//            OverrideDropDown(gdc);
            
//            OverrideControlBorder(gdc);
            
//        }
            
//        break;
            
//    */
            
//    //case WM_SETCURSOR:
            
//    //    base.WndProc(ref m);
            
//    //    // The value 3 is discovered by trial on error, and cover all kinds of scenarios
            
//    //    // InvalidateSince < 2 wil have problem if the control is not in focus and dropdown is clicked
            
//    //    if (DroppedDown && InvalidateSince < 3)
            
//    //    {
            
//    //        Invalidate();
            
//    //        InvalidateSince++;
            
//    //    }
            
//    //    break;
            
//    default:
            
//        base.WndProc(ref m);
            
//        break;
            
//}
            IntPtr hDC = GetWindowDC(m.HWnd);
            Graphics gdc 
= Graphics.FromHdc(hDC);
            
switch (m.Msg)
            
{
                
case WM_NC_PAINT:
                    SendMessage(
this.Handle, WM_ERASEBKGND, hDC, 0);
                    SendPrintClientMsg();
                    SendMessage(
this.Handle, WM_PAINT, IntPtr.Zero, 0);
                    OverrideControlBorder(gdc);

                    m.Result 
= (IntPtr)1// indicate msg has been processed
                    break;
                
case WM_PAINT: base.WndProc(ref m);
                    OverrideControlBorder(gdc);
                    OverrideDropDown(gdc);
                    
break;
                
case WM_NC_HITTEST:
                    
base.WndProc(ref m);
                    
if (DroppedDown)
                        
this.Invalidate(this.ClientRectangle, false);
                    
break;
                
default:
                    
base.WndProc(ref m);
                    
break;
            }

            ReleaseDC(m.HWnd, hDC);
            gdc.Dispose();    

            
        }

        
public static void PaintFlatDropDown(Control ctrl, Graphics g)
        
{
            Rectangle rect 
= new Rectangle(ctrl.Width - DropDownButtonWidth, 0, DropDownButtonWidth, ctrl.Height);
            ControlPaint.DrawComboButton(g, rect, ButtonState.Flat);
        }

        
private void SendPrintClientMsg()
        
{
            
// We send this message for the control to redraw the client area
            Graphics gClient = this.CreateGraphics();
            IntPtr ptrClientDC 
= gClient.GetHdc();
            SendMessage(
this.Handle, WM_PRINTCLIENT, ptrClientDC, 0);
            gClient.ReleaseHdc(ptrClientDC);
            gClient.Dispose();
        }

        
public void SetText(string text)
        
{
            
if (text != "")
            
{
                
this.Format = DateTimePickerFormat.Long;

                
this.Text = text;
            }

            
else
            
{
                
this.Format = DateTimePickerFormat.Custom;
            }

        }

        
private void OverrideDropDown(Graphics g)
        
{
            
if (!this.ShowUpDown)
            
{
                Rectangle rect 
= new Rectangle(this.Width-DropDownButtonWidth, 0, DropDownButtonWidth, this.Height);
                ControlPaint.DrawComboButton(g, rect, ButtonState.Flat);    
            }

        }


        
private void OverrideControlBorder(Graphics g)
        
{
            
//this.Width = this.Width + 4;

            
if (this.Focused == false || this.Enabled == false )
                g.DrawRectangle(BorderPenControl, 
new Rectangle(00this.Width, this.Height));
            
else
                g.DrawRectangle(BorderPen, 
new Rectangle(00this.Width, this.Height));
        }

        
protected override void OnKeyUp(KeyEventArgs e)
        
{
            
if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete)
            
{
                
this.Format = DateTimePickerFormat.Custom;
                
this.CustomFormat = " ";
                
// OnValueChanged(EventArgs.Empty);
            }

            
base.OnKeyUp(e);
        }

        
protected override void OnDropDown(EventArgs eventargs)
        
{
            InvalidateSince 
= 0;
            DroppedDown 
= true;
            
base.OnDropDown (eventargs);
        }

        
protected override void OnCloseUp(EventArgs eventargs)
        
{
            DroppedDown 
= false;
            
this.Format = DateTimePickerFormat.Long;
            
base.OnCloseUp (eventargs);
        }

    
        
protected override void OnLostFocus(System.EventArgs e)
        
{
            
base.OnLostFocus(e);
            
this.Invalidate();
        }


        
protected override void OnGotFocus(System.EventArgs e)
        
{
            
base.OnGotFocus(e);
            
this.Invalidate();
        }
        
        
protected override void OnResize(EventArgs e)
        
{
            
base.OnResize (e);
            
this.Invalidate();
        }


    }

}

 

posted @ 2006-11-30 19:09  大田  阅读(6444)  评论(0编辑  收藏  举报