可编辑日期选择器






4.78/5 (21投票s)
基于 CDateTimeCtrl 的完全可编辑的日期选择器控件。

引言
虽然我喜欢在用户需要输入日期时使用标准的日期选择器控件,但我经常发现需要使其完全可编辑。标准控件有其自身的可编辑方式,但这并没有给我一个可以随心所欲的纯编辑控件。
文档
该控件基于微软的 CDateTimeCtrl
类。我使用了一个巧妙的技巧,允许我用自己的编辑控件和按钮完全替换标准控件,同时仍然允许该类从 CDateTimeCtrl
派生。我通过销毁现有窗口,然后创建自己的窗口并将其附加到类中来实现这一点。有关工作原理,请参见 CDateTimeEditCtrl::OnRecreate
。
由于我完成这项工作的方式,使用该控件与使用 CDateTimeCtrl
相同。您应该像平常一样将日期选择器添加到对话框资源中,然后为此创建一个类型为 CDateTimeEditCtrl
的成员变量。通常的日期选择器样式都受支持,但 DTS_UPDOWN
、DTS_SHOWNONE
、DTS_APPCANPARSE
、DTS_LONGDATEFORMAT
和 DTS_TIMEFORMAT
除外。
发送到控件的消息会以与标准控件相同的方式进行解释和处理,但 DTM_GETRANGE
、DTM_SETRANGE
和 DTM_SETFORMAT
除外,它们不受支持。控件中事件的通知会像在标准选择器中一样发送到父窗口。已添加一些额外的 public
函数来提供增强的功能。下面的列表列出了 public
函数。
函数
BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
提供与
CDateTimeCtrl
相同的行为。CEdit* GetEditControl() const;
返回指向控件编辑控件部分的指针,允许直接操作其属性。
void EnableButton(BOOL bEnable = TRUE);
启用或禁用用于下拉
Calendar
控件的按钮。void RestoreFocus(BOOL bRestore = TRUE);
确定点击按钮时的行为。如果为
TRUE
,则控件将在点击按钮时将焦点重置回具有焦点的前一个窗口。否则,焦点将设置到编辑控件。如果控件不可编辑,焦点将始终设置回先前聚焦的窗口。默认情况下,焦点设置到编辑控件。void SetNonEditable(BOOL bNonEditable = TRUE);
用于使控件的编辑部分不可编辑。默认为可编辑。
BOOL GetNonEditable();
返回编辑控件当前是否可编辑。
virtual BOOL IsValidDate(LPCTSTR lpszDate = NULL);
返回传入的日期字符串是否有效。如果
lpszDate
为NULL
,则返回编辑控件中的文本是否为有效的日期字符串。void SetValidCharsOnly(BOOL bValidCharsOnly = TRUE);
设置用户是否只能输入有效的字符。
BOOL GetValidCharsOnly();
返回用户是否只能在编辑控件中输入有效字符。
void SetValidChars(LPCTSTR lpszValidChars = NULL);
设置用户可以在编辑控件中输入的有效字符。如果指定
NULL
,则使用默认字符(0-9 和当前用户的区域设置日期分隔符)。如果用户更改区域设置,则控件将检测到此更改并使用新的分隔符。CString GetValidChars();
返回已设置为用户可以在编辑控件中输入的有效字符。
void SetAllowUpDownKeys(BOOL bAllow = TRUE);
设置上下箭头键是否会递增/递减包含光标的日期字符串的部分。
BOOL GetAllowUpDownKeys();
返回上下键是否会递增/递减日期字符串的部分。
BOOL SetButtonImageID(UINT nID, UINT nDisabledID = 0);
指定一个资源 ID,用于加载按钮图像。为了获得最佳效果,图像应为 13 像素宽和 12 像素高。
nDisabledID
可选地指定一个用于按钮禁用状态的图像。UINT GetButtonImageID(UINT* pDisabledID = NULL) const;
返回当前按钮图像的 ID。禁用按钮的 ID 可以在
pDisabledID
中检索。void GetButtonImageIDs(UINT& nID, UINT& nDisabledID) const;
检索当前按钮图像的 ID。
void SetReadOnly(BOOL bReadOnly = TRUE);
将控件设置为只读。这类似于禁用状态,但文本不会显示为灰色,并且可以选择。
BOOL GetReadOnly() const;
返回控件当前是否设置为只读。
历史
- 2008 年 1 月 21 日 - 版本 3.7
- 已更新以在 Vista 上正常工作。
- 2007 年 4 月 20 日 - 版本 3.6.1
- 修复了丢失和不正确的
NM_KILLFOCUS
通知。 - 已更改为可在 VC7 (Visual Studio 2003) 和 VC8 (Visual Studio 2005) 中正确编译。
- 已添加修复,以解决在父窗口初始化时隐藏的控件被显示的问题。
- 修复了丢失和不正确的
- 2005 年 12 月 22 日 - 版本 3.6
- 添加了“只读”状态,以允许半禁用状态。
- 已更新以识别 XP 主题更改并相应地重绘。
- 修复了在 F4 键按下时,日历控件可能以不可编辑模式显示,并且日期可以通过使用上下箭头键更改的错误。
- 添加了对在控件禁用或只读时使用的“禁用”图像的支持。
- 修复了使用
ES_READONLY
样式创建控件失败的错误。 - 将按钮/编辑/日历/XP 样式类嵌套,因此它们不会出现在 ClassView 的顶层。
- 2005 年 4 月 4 日 - 版本 3.5
- 已更新以支持 XP 样式。
- 更改为在禁用时将编辑控件变灰(由 Hans-Georg Ulrich 建议)。
- 已添加修复,以启用与 Visual Studio .NET 的编译(感谢 Mark Harmon)。
- 2004 年 7 月 9 日 - 版本 3.4
- 修复了在
calendar
控件中通过单击日历区域外部来关闭月份菜单,然后阻止日历被关闭,除非先单击回calendar
控件(由 winkle 报告)。 - 修复了当对话框上有两个或更多控件实例时,控件重新创建时发生的断言失败(由 pimOOsse 和 Rick Austin 报告)。
- 修复了在
- 2003 年 7 月 9 日 - 版本 3.3
- 已更新以支持 Unicode。
- 2003 年 4 月 15 日 - 版本 3.2
- 扩展了控件以接受
DTM_SETRANGE
和DTM_GETRANGE
消息。 - 修复了
DTS_RIGHTALIGN
的不正确实现。 - 添加了使用位图作为按钮而不是向下箭头的设施。
WM_NOTIFY
通知现在从日期控件的子窗口传递到父窗口。- 修复了点击当前(带圈)日期时,如果编辑控件为空,日历关闭且未将选定的日期放入编辑控件的错误。
- 扩展了控件以接受
- 2003 年 1 月 20 日 - 版本 3.1
- 修复了当新日期文本在
DTN_DATETIMECHANGE
处理程序中设置时(例如,将日期限制在某个边界内),并且用户选择了一个“越界”日期并关闭日历,选定的日期被复制到编辑控件,覆盖了“固定”日期的错误。
- 修复了当新日期文本在
- 2003 年 1 月 17 日 - 版本 3
- 修复了当从父对话框的
OnInitDialog
或等效函数调用Get
/SetWindowText
、SetFont
或任何导致发送DTM_XXX
消息的函数时,第一次发生断言的错误。
- 修复了当从父对话框的
- 2003 年 1 月 7 日 - 版本 2
- 编辑控件通知(例如
EN_CHANGE
)现在发送到日期控件的父窗口。 - 添加了 Marc Clifton 建议的功能。
- 添加了验证日期字符串的函数(
IsValidDate
)。 - 添加了只允许在编辑控件中键入有效字符的函数。还添加了一个设置有效字符的函数。默认有效字符为 0-9 和当前用户的区域设置日期分隔符。如果用户更改区域设置,则控件将自动识别并使用新的分隔符。
- 添加了使用上下键编辑日期文本部分的功能。当日期更改时,父窗口会收到
DTN_DATETIMECHANGE
通知。
- 添加了验证日期字符串的函数(
- 编辑控件通知(例如
- 2003 年 1 月 3 日 - 版本 1
- First version.