답변

2

DateTimePicker에서 상속받은 컨트롤을 만들고 DTN_DATETIMECHANGE 알림을 처리합니다. 그런 다음에 DateTimePicker의 새로운 CheckedChanged 이벤트에 대한 처리기를 추가 할 DataGridView에의 EditingControlShowing 이벤트를 처리, 또는 당신은 EditingControl로 DateTimePickerEx하여 자신의 DataGridViewColumn 및 셀 유형을 만들 수 있습니다

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Data; 
using System.Diagnostics; 

public class DateTimePickerEx : DateTimePicker 
{ 
    private bool _checked; 
    private const int WM_REFLECT = 0x2000; 
    public event CheckedChangedEventHandler CheckedChanged; 
    public delegate void CheckedChangedEventHandler(object sender, System.EventArgs e); 

    public DateTimePickerEx() 
    { 
    this._checked = this.Checked; 
    } 

    private void WmDateTimeChange(ref Message m) 
    { 
    NMDATETIMECHANGE nmdatetimechange = m.GetLParam(typeof(NMDATETIMECHANGE)); 

    if (nmdatetimechange.dwFlags == GetDateTimeValues.GDT_NONE) { 
     if (this.ShowCheckBox && !this.Checked) { 
     this._checked = false; 
     if (CheckedChanged != null) { 
      CheckedChanged(this, EventArgs.Empty); 
     } 
     } 
    } else { 
     if (this.ShowCheckBox && this.Checked && !this._checked) { 
     this._checked = true; 
     if (CheckedChanged != null) { 
      CheckedChanged(this, EventArgs.Empty); 
     } 
     } 

     this.Value = SysTimeToDateTime(nmdatetimechange.st); 
    } 

    m.Result = IntPtr.Zero; 
    } 

    private bool WmReflectCommand(ref Message m) 
    { 
    if (m.HWnd == this.Handle) { 
     long code = NMHDR.FromMessage(m).code; 

     switch (code) { 
     case FWEx.Win32API.DateTimePickerNotifications.DTN_DATETIMECHANGE: 
      this.WmDateTimeChange(ref m); 
      return true; 
     } 

     return false; 
    } 
    } 

    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] 
    protected override void WndProc(ref System.Windows.Forms.Message m) 
    { 
    if (m.Msg != 71 && m.Msg != 513) { 
     switch ((WindowsMessages)m.Msg) { 
     case WindowsMessages.WM_NOTIFY + WM_REFLECT: 
      if (!this.WmReflectCommand(ref m)) { 
      break; 
      } 

      return; 

      break; 
     } 
    } 

    base.WndProc(m); 
    } 

    private System.DateTime SysTimeToDateTime(SYSTEMTIME st) 
    { 
    return new System.DateTime(st.Year, st.Month, st.Day, st.Hour, st.Minute, st.Second); 
    } 

    /// <summary> 
    /// This structure contains information about a change that has taken place in a date and time picker (DTP) control. 
    /// This structure is used with the DTN_DATETIMECHANGE notification message. 
    /// </summary> 
    /// <remarks></remarks> 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    public struct NMDATETIMECHANGE 
    { 
    /// <summary> 
    /// NMHDR structure that contains information about the notification message. 
    /// </summary> 
    public NMHDR nmhdr; 
    /// <summary> 
    /// Specifies if the control was set to no date status (for DTS_SHOWNONE only). 
    /// Also specifies whether the contents of the st member are valid and contain current time information. 
    /// </summary> 
    public GetDateTimeValues dwFlags; 
    /// <summary> 
    /// SYSTEMTIME structure that contains information about the current system date and time. 
    /// </summary> 
    public SYSTEMTIME st; 
    } 

    /// <summary> 
    /// This structure contains information about a message. 
    /// The pointer to this structure is specified as the lParam member of the WM_NOTIFY message. 
    /// </summary> 
    [StructLayout(LayoutKind.Sequential)] 
    public struct NMHDR 
    { 
    /// <summary> 
    /// Window handle to the control sending a message. 
    /// </summary> 

    public IntPtr hwndFrom; 
    /// <summary> 
    /// Identifier of the control sending a message. 
    /// </summary> 

    public IntPtr idFrom; 
    /// <summary> 
    /// Notification code. This member can be a control-specific notification code or it can be one of the common notification codes. The following values are supported if you include mouse support in your device platform: 
    /// - NM_RCLICK 
    /// - NM_RDBCLICK 
    /// </summary> 

    public int code; 
    public static NMHDR FromMessage(System.Windows.Forms.Message msg) 
    { 
     return (NMHDR)msg.GetLParam(typeof(NMHDR)); 
    } 
    } 

    /// <summary> 
    /// Specifies a date and time, using individual members for the month, day, year, weekday, hour, minute, second, and millisecond. 
    /// The time is either in coordinated universal time (UTC) or local time, depending on the function that is being called. 
    /// </summary> 
    /// <remarks> 
    /// It is not recommended that you add and subtract values from the SYSTEMTIME structure to obtain relative times. 
    /// </remarks> 
    public struct SYSTEMTIME 
    { 
    /// <summary> 
    /// The year. The valid values for this member are 1601 through 30827. 
    /// </summary> 
    public short Year; 
    /// <summary> 
    /// The month. 
    /// </summary> 
    public short Month; 
    /// <summary> 
    /// The day of the week. Sunday = 0. 
    /// </summary> 
    public short DayOfWeek; 
    /// <summary> 
    /// The day of the month. The valid values for this member are 1 through 31. 
    /// </summary> 
    public short Day; 
    /// <summary> 
    /// The hour. The valid values for this member are 0 through 23. 
    /// </summary> 
    public short Hour; 
    /// <summary> 
    /// The minute. The valid values for this member are 0 through 59. 
    /// </summary> 
    public short Minute; 
    /// <summary> 
    /// The second. The valid values for this member are 0 through 59. 
    /// </summary> 
    public short Second; 
    /// <summary> 
    /// The millisecond. The valid values for this member are 0 through 999. 
    /// </summary> 
    public short Milliseconds; 
    } 

    public enum GetDateTimeValues 
    { 
    /// <summary> 
    /// Error. 
    /// </summary> 
    GDT_ERROR = -1, 
    /// <summary> 
    /// The control is not set to the no date status. 
    /// The st member contains the current date and time. 
    /// </summary> 
    GDT_VALID = 0, 
    /// <summary> 
    /// The control is set to no date status. 
    /// The no date status applies only to controls that are set to the DTS_SHOWNONE style. 
    /// </summary> 
    GDT_NONE = 1 
    } 

    public enum WindowsMessages 
    { 
    /// <summary> 
    ///Sent by a common control to its parent window when an event has occurred or the control requires some information. 
    /// </summary> 
    WM_NOTIFY = 0x4e 
    } 

    public enum DateTimePickerNotifications 
    { 
    DTN_FIRST = -740, 
    DTN_LAST = -745, 
    DTN_FIRST2 = -753, 
    DTN_LAST2 = -799, 
    DTN_DATETIMECHANGE = DTN_FIRST2 - 6, 
    DTN_USERSTRING = DTN_FIRST2 - 5, 
    DTN_WMKEYDOWN = DTN_FIRST2 - 4, 
    DTN_FORMAT = DTN_FIRST2 - 3, 
    DTN_FORMATQUERY = DTN_FIRST2 - 2, 
    DTN_DROPDOWN = DTN_FIRST2 - 1, 
    DTN_CLOSEUP = DTN_FIRST2 
    } 
} 

처리 DataGridView.EditingControlShowing에 DateTimePickerEx.CheckedChanged :

private void dgv_EditingControlShowing(System.Object sender, System.Windows.Forms.DataGridViewEditingControlShowingEventArgs e) 
    { 
     switch (this.dgv.CurrentCellAddress.X) { 
       case 0: // your DateTimePickerEx column number 
        DateTimePickerEx dtp = e.Control as DateTimePickerEx; 

        if (dtp != null) { 
          dtp.CheckedChanged += (object sen, EventArgs ea) => { 
            //TODO: Add your code here 
          }; 
        } 

       break; 
     } 
    } 
관련 문제