DateTimePickerBase.cs 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346
  1. 
  2. using System;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Runtime.InteropServices;
  6. using System.Text.RegularExpressions;
  7. using System.Windows.Forms;
  8. using Dongke.WinForm.Utilities;
  9. namespace Dongke.WinForm.Controls
  10. {
  11. /// <summary>
  12. /// 日期控件,该控件用来让用户选择日期和时间并以指定的格式显示此日期和时间。
  13. /// </summary>
  14. public abstract class DateTimePickerBase : DateTimePicker, IDKControl,
  15. IDataVerifiable, IAsyncControl, IChildNativeWindow
  16. {
  17. #region 常量
  18. /// <summary>
  19. /// 日期时间格式过滤字符
  20. /// </summary>
  21. private const string DATETIME_FORMAT_S = "[^yMdHhmsfFt]";
  22. #endregion
  23. #region 获取UpDown控件
  24. [DllImport("user32.dll", ExactSpelling = true)]
  25. private static extern bool EnumChildWindows(HandleRef hwndParent, DateTimePickerBase.EnumChildrenCallback lpEnumFunc, HandleRef lParam);
  26. private delegate bool EnumChildrenCallback(IntPtr hwnd, IntPtr lParam);
  27. private sealed class EnumChildren
  28. {
  29. public IntPtr hwndFound = IntPtr.Zero;
  30. public bool enumChildren(IntPtr hwnd, IntPtr lparam)
  31. {
  32. this.hwndFound = hwnd;
  33. return true;
  34. }
  35. }
  36. #endregion
  37. #region 事件声明
  38. /*
  39. #region TextPaste
  40. /// <summary>
  41. /// 当输入文本粘贴后发生
  42. /// </summary>
  43. private static readonly object EventTextPaste = new object();
  44. /// <summary>
  45. /// TextPaste 事件
  46. /// </summary>
  47. public event TextPasteEventHandler TextPaste
  48. {
  49. add
  50. {
  51. base.Events.AddHandler(EventTextPaste, value);
  52. }
  53. remove
  54. {
  55. base.Events.RemoveHandler(EventTextPaste, value);
  56. }
  57. }
  58. #endregion
  59. */
  60. #region HasErrorChanged
  61. /// <summary>
  62. /// 当 HasError 属性的值更改时发生。
  63. /// </summary>
  64. private static readonly object EventHasErrorChanged = new object();
  65. /// <summary>
  66. /// 当 HasError 属性的值更改时发生。
  67. /// </summary>
  68. [Description("当 HasError 属性的值更改时发生。"), Category("CustomerEx")]
  69. public event EventHandler HasErrorChanged
  70. {
  71. add
  72. {
  73. base.Events.AddHandler(EventHasErrorChanged, value);
  74. }
  75. remove
  76. {
  77. base.Events.RemoveHandler(EventHasErrorChanged, value);
  78. }
  79. }
  80. #endregion
  81. #endregion
  82. #region 成员变量
  83. private ChildNativeWindow _updown = null;
  84. /// <summary>
  85. /// 焦点是否进入控件
  86. /// </summary>
  87. private bool _entered = false;
  88. /// <summary>
  89. /// 鼠标是否进入控件
  90. /// </summary>
  91. private bool _mouseOver = false;
  92. /// <summary>
  93. /// 边框颜色
  94. /// </summary>
  95. private Color? _borderColor = null;
  96. /// <summary>
  97. /// 自定义日期/时间格式字符串
  98. /// </summary>
  99. private string _customFormat = Constant.DATETIME_FORMAT_YYYYMMDDHHMMSS;
  100. /// <summary>
  101. /// 控件中显示的日期和时间格式
  102. /// </summary>
  103. private DateTimePickerFormat _format = DateTimePickerFormat.Custom;
  104. /// <summary>
  105. /// 指示是否设定了日期时间值
  106. /// </summary>
  107. private bool _nullValue = false;
  108. /// <summary>
  109. /// 指示控件是否允许输入null
  110. /// </summary>
  111. private bool _allowNull = true;
  112. /// <summary>
  113. /// 不触发ValueChanged
  114. /// </summary>
  115. private bool _isSetValue = false;
  116. /// <summary>
  117. /// 日期文本(无标点)格式化
  118. /// </summary>
  119. private string _dateTextFormat = null;
  120. /// <summary>
  121. /// 日历选择显示
  122. /// </summary>
  123. private bool _isDropDown = false;
  124. #endregion
  125. #region 构造函数
  126. /// <summary>
  127. /// 日期控件,该控件用来让用户选择日期和时间并以指定的格式显示此日期和时间。
  128. /// </summary>
  129. public DateTimePickerBase()
  130. {
  131. base.ImeMode = ImeMode.Off;
  132. this.Value = null;
  133. this._dateTextFormat = Regex.Replace(this._customFormat, DATETIME_FORMAT_S, string.Empty);
  134. CommonSetting.InitControls(this);
  135. }
  136. #endregion
  137. #region 属性
  138. /// <summary>
  139. /// 获取一个值,该值指示控件是否有输入焦点。
  140. /// </summary>
  141. [DefaultValue(false)]
  142. [Browsable(false)]
  143. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  144. [EditorBrowsable(EditorBrowsableState.Advanced)]
  145. public virtual bool Entered
  146. {
  147. get
  148. {
  149. return this._entered;
  150. }
  151. protected set
  152. {
  153. if (this._entered != value)
  154. {
  155. this._entered = value;
  156. this.InvalidateBorder();
  157. }
  158. }
  159. }
  160. /// <summary>
  161. /// 获取一个值,该值指示鼠标是否在控件上方。
  162. /// </summary>
  163. [DefaultValue(false)]
  164. [Browsable(false)]
  165. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  166. [EditorBrowsable(EditorBrowsableState.Advanced)]
  167. public virtual bool MouseOver
  168. {
  169. get
  170. {
  171. return this._mouseOver;
  172. }
  173. protected set
  174. {
  175. if (this._mouseOver != value)
  176. {
  177. this._mouseOver = value;
  178. this.InvalidateBorder();
  179. }
  180. }
  181. }
  182. /// <summary>
  183. /// 获取日期的开始时间(该日期的00:00:00)
  184. /// </summary>
  185. [Browsable(true), Description("获取日期的开始时间(该日期的00:00:00)"), Category("CustomerEx")]
  186. public virtual DateTime? BeginTime
  187. {
  188. get
  189. {
  190. if (this._nullValue)
  191. {
  192. return null;
  193. }
  194. return this.Value.Value.Date;
  195. }
  196. }
  197. /// <summary>
  198. /// 获取日期的结束时间(该日期的23:59:59)
  199. /// </summary>
  200. [Browsable(true), Description("获取日期的结束时间(该日期的23:59:59)"), Category("CustomerEx")]
  201. public virtual DateTime? EndTime
  202. {
  203. get
  204. {
  205. if (this._nullValue)
  206. {
  207. return null;
  208. }
  209. DateTime dt = this.Value.Value;
  210. return new DateTime(dt.Year, dt.Month, dt.Day, 23, 59, 59);
  211. }
  212. }
  213. /// <summary>
  214. /// 获取或设置与此控件关联的日期文本(无格式)。
  215. /// </summary>
  216. [Browsable(false)]
  217. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  218. [EditorBrowsable(EditorBrowsableState.Advanced)]
  219. public virtual string DateText
  220. {
  221. get
  222. {
  223. if (this._nullValue)
  224. {
  225. return string.Empty;
  226. }
  227. // 日期时间改变时,控件闪烁。
  228. //if (this.Focused)
  229. //{
  230. // // 输入不完整时,自动补齐日期。
  231. // SendKeys.SendWait("{RIGHT}");
  232. // SendKeys.SendWait("{LEFT}");
  233. //}
  234. return this.Value.Value.ToString(this._dateTextFormat);
  235. }
  236. set
  237. {
  238. if (value == null || value.Length == 0)
  239. {
  240. this.Value = null;
  241. return;
  242. }
  243. DateTime dt;
  244. if (DateTime.TryParseExact(value, this._dateTextFormat, null, System.Globalization.DateTimeStyles.None, out dt))
  245. {
  246. this.Value = dt;
  247. }
  248. }
  249. }
  250. #endregion
  251. #region 重写属性
  252. /// <summary>
  253. /// 获取或设置自定义日期/时间格式字符串。
  254. /// </summary>
  255. [DefaultValue(Constant.DATETIME_FORMAT_YYYYMMDDHHMMSS)]
  256. public new virtual string CustomFormat
  257. {
  258. get
  259. {
  260. return this._customFormat;
  261. }
  262. set
  263. {
  264. this._customFormat = value;
  265. this._dateTextFormat = Regex.Replace(this._customFormat, DATETIME_FORMAT_S, string.Empty);
  266. if (!this._nullValue)
  267. {
  268. base.CustomFormat = value;
  269. }
  270. }
  271. }
  272. /// <summary>
  273. /// 获取或设置控件中显示的日期和时间格式。
  274. /// </summary>
  275. [DefaultValue(typeof(DateTimePickerFormat), "Custom")]
  276. public new virtual DateTimePickerFormat Format
  277. {
  278. get
  279. {
  280. return this._format;
  281. }
  282. set
  283. {
  284. this._format = value;
  285. if (!this._nullValue)
  286. {
  287. base.Format = value;
  288. }
  289. }
  290. }
  291. /// <summary>
  292. /// 获取或设置与此控件关联的格式化文本。
  293. /// </summary>
  294. [Browsable(false)]
  295. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  296. [EditorBrowsable(EditorBrowsableState.Advanced)]
  297. public override string Text
  298. {
  299. get
  300. {
  301. if (this._nullValue)
  302. {
  303. return string.Empty;
  304. }
  305. // 日期时间改变时,控件闪烁。
  306. //// 输入不完整时,自动补齐日期。
  307. //if (this.Focused && !this._isDropDown)
  308. //{
  309. // SendKeys.SendWait("{RIGHT}");
  310. // SendKeys.SendWait("{LEFT}");
  311. //}
  312. return base.Text;
  313. }
  314. set
  315. {
  316. if (value == null || value.Length == 0)
  317. {
  318. this.Value = null;
  319. return;
  320. }
  321. if (this._nullValue)
  322. {
  323. this.SetDateValueNotNull();
  324. }
  325. base.Text = value;
  326. }
  327. }
  328. /// <summary>
  329. /// 获取或设置分配给控件的日期/时间值。
  330. /// </summary>
  331. //[Browsable(false)]
  332. //[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  333. //[EditorBrowsable(EditorBrowsableState.Never)]
  334. [Bindable(true)]
  335. [DefaultValue(typeof(DateTime?), "")]
  336. [RefreshProperties(RefreshProperties.All)]
  337. [Description("获取或设置分配给控件的日期/时间值。"), Category("CustomerEx")]
  338. public new virtual DateTime? Value
  339. {
  340. get
  341. {
  342. if (this._allowNull && this._nullValue)
  343. {
  344. return null;
  345. }
  346. // 日期时间改变时,控件闪烁。
  347. //// 输入不完整时,自动补齐日期。
  348. //if (this.Focused && !this._isDropDown)
  349. //{
  350. // SendKeys.SendWait("{RIGHT}");
  351. // SendKeys.SendWait("{LEFT}");
  352. //}
  353. return base.Value;
  354. }
  355. set
  356. {
  357. if (value.HasValue)
  358. {
  359. this.SetDateValueNotNull(value.Value);
  360. }
  361. else
  362. {
  363. if (!this._allowNull)
  364. {
  365. return;
  366. }
  367. if (!this._nullValue)
  368. {
  369. this.SetDateValueNull();
  370. }
  371. }
  372. }
  373. }
  374. /// <summary>
  375. /// 获取或设置一个值,该值指示控件是否允许输入null值。
  376. /// </summary>
  377. [DefaultValue(true)]
  378. [RefreshProperties(RefreshProperties.All)]
  379. [Description("获取或设置一个值,该值指示控件是否允许输入null值。"), Category("CustomerEx")]
  380. public virtual bool AllowNull
  381. {
  382. get
  383. {
  384. return this._allowNull;
  385. }
  386. set
  387. {
  388. this._allowNull = value;
  389. if (!this._allowNull && this._nullValue)
  390. {
  391. this.SetDateValueNotNull();
  392. }
  393. }
  394. }
  395. /// <summary>
  396. /// 获取或设置控件的输入法编辑器 (IME) 模式。
  397. /// </summary>
  398. [Browsable(false)]
  399. [EditorBrowsable(EditorBrowsableState.Never)]
  400. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  401. public new ImeMode ImeMode
  402. {
  403. get
  404. {
  405. return base.ImeMode;
  406. }
  407. set
  408. {
  409. base.ImeMode = value;
  410. }
  411. }
  412. /// <summary>
  413. /// 获取一个用以指示是否可以将 System.Windows.Forms.Control.ImeMode 属性设置为活动值的值,以启用 IME 支持。
  414. /// </summary>
  415. protected override bool CanEnableIme
  416. {
  417. get
  418. {
  419. return false;
  420. }
  421. }
  422. #endregion
  423. #region 重写事件
  424. #region 属性改变
  425. /// <summary>
  426. /// 引发 HasErrorChanged 事件
  427. /// </summary>
  428. /// <param name="e">包含事件数据的 EventArgs</param>
  429. protected virtual void OnHasErrorChanged(EventArgs e)
  430. {
  431. EventHandler eventHandler = (EventHandler)base.Events[EventHasErrorChanged];
  432. if (eventHandler != null)
  433. {
  434. eventHandler(this, e);
  435. }
  436. }
  437. /// <summary>
  438. /// 文本改变事件
  439. /// </summary>
  440. /// <param name="e"></param>
  441. protected override void OnTextChanged(EventArgs e)
  442. {
  443. base.OnTextChanged(EventArgs.Empty);
  444. }
  445. /// <summary>
  446. ///
  447. /// </summary>
  448. /// <param name="e"></param>
  449. protected override void OnValueChanged(EventArgs e)
  450. {
  451. if (this._nullValue && !this._isSetValue)
  452. {
  453. return;
  454. }
  455. // 不显示天数时,如果是31日,没有31日的月份会报错。
  456. if (!this._nullValue &&
  457. this.Format == DateTimePickerFormat.Custom &&
  458. this.CustomFormat != null &&
  459. !this.CustomFormat.Contains("d") &&
  460. this.Value.Value.Day > 28)
  461. {
  462. this.Value = this.Value.Value.AddDays(1 - this.Value.Value.Day);
  463. }
  464. base.OnValueChanged(e);
  465. // TODO 实时验证?
  466. if (true)
  467. {
  468. this.ValidateData();
  469. }
  470. }
  471. #endregion
  472. #region 行为事件
  473. /// <summary>
  474. /// 当显示下拉日历时发生。
  475. /// </summary>
  476. /// <param name="e"></param>
  477. protected override void OnDropDown(EventArgs e)
  478. {
  479. base.OnDropDown(e);
  480. this._isDropDown = true;
  481. }
  482. /// <summary>
  483. /// 当下拉日历被关闭并消失时发生
  484. /// </summary>
  485. /// <param name="e"></param>
  486. protected override void OnCloseUp(EventArgs e)
  487. {
  488. if (!this._allowNull)
  489. {
  490. base.OnCloseUp(e);
  491. return;
  492. }
  493. if (this.ShowCheckBox && !this.Checked)
  494. {
  495. base.OnCloseUp(e);
  496. return;
  497. }
  498. if (Control.MouseButtons == MouseButtons.None)
  499. {
  500. if (this._nullValue)
  501. {
  502. //this.Value = base.Value;
  503. this.SetDateValueNotNull(base.Value);
  504. }
  505. }
  506. base.OnCloseUp(e);
  507. this._isDropDown = false;
  508. }
  509. #endregion
  510. #region 键盘事件
  511. /// <summary>
  512. /// 当有按键动作时发生
  513. /// </summary>
  514. /// <param name="e"></param>
  515. protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
  516. {
  517. if (!this._allowNull)
  518. {
  519. base.OnPreviewKeyDown(e);
  520. return;
  521. }
  522. if (this.ShowCheckBox && !this.Checked)
  523. {
  524. base.OnPreviewKeyDown(e);
  525. return;
  526. }
  527. // 删除时间
  528. if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete)
  529. {
  530. this.Value = null;
  531. base.OnPreviewKeyDown(e);
  532. return;
  533. }
  534. if ((e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9) ||
  535. (e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) ||
  536. (e.KeyCode >= Keys.PageUp && e.KeyCode <= Keys.Down))
  537. {
  538. //PageUp = 33,
  539. //Next = 34,
  540. //PageDown = 34,
  541. //End = 35,
  542. //Home = 36,
  543. //Left = 37,
  544. //Up = 38,。
  545. //Right = 39,
  546. //Down = 40,
  547. if (this._nullValue)
  548. {
  549. this.SetDateValueNotNull();
  550. if (e.KeyCode != Keys.Right)
  551. {
  552. SendKeys.SendWait("{RIGHT}");
  553. }
  554. }
  555. }
  556. base.OnPreviewKeyDown(e);
  557. }
  558. /// <summary>
  559. /// 键盘输入
  560. /// </summary>
  561. /// <param name="e"></param>
  562. protected override void OnKeyPress(KeyPressEventArgs e)
  563. {
  564. base.OnKeyPress(e);
  565. }
  566. /// <summary>
  567. /// 键盘点击
  568. /// </summary>
  569. /// <param name="e"></param>
  570. protected override void OnKeyDown(KeyEventArgs e)
  571. {
  572. base.OnKeyDown(e);
  573. }
  574. #endregion
  575. #region 焦点事件
  576. /// <summary>
  577. /// 输入焦点进入控件
  578. /// </summary>
  579. /// <param name="e"></param>
  580. protected override void OnEnter(EventArgs e)
  581. {
  582. this.Entered = true;
  583. base.OnEnter(e);
  584. }
  585. /// <summary>
  586. /// 获得焦点
  587. /// </summary>
  588. /// <param name="e"></param>
  589. protected override void OnGotFocus(EventArgs e)
  590. {
  591. base.OnGotFocus(e);
  592. }
  593. /// <summary>
  594. /// 失去焦点
  595. /// </summary>
  596. /// <param name="e"></param>
  597. protected override void OnLostFocus(EventArgs e)
  598. {
  599. base.OnLostFocus(e);
  600. }
  601. /// <summary>
  602. /// 输入焦点离开控件
  603. /// </summary>
  604. /// <param name="e"></param>
  605. protected override void OnLeave(EventArgs e)
  606. {
  607. base.OnLeave(e);
  608. }
  609. /// <summary>
  610. /// 控件正在验证
  611. /// </summary>
  612. /// <param name="e"></param>
  613. protected override void OnValidating(CancelEventArgs e)
  614. {
  615. base.OnValidating(e);
  616. if (this.HasError && !this._canLostFocusOnError)
  617. {
  618. e.Cancel = true;
  619. }
  620. }
  621. /// <summary>
  622. /// 控件完成验证
  623. /// </summary>
  624. /// <param name="e"></param>
  625. protected override void OnValidated(EventArgs e)
  626. {
  627. this.Entered = false;
  628. base.OnValidated(e);
  629. }
  630. #endregion
  631. #region 鼠标事件
  632. /// <summary>
  633. /// 鼠标进入控件
  634. /// </summary>
  635. /// <param name="e"></param>
  636. protected override void OnMouseEnter(EventArgs e)
  637. {
  638. this.MouseOver = true;
  639. base.OnMouseEnter(e);
  640. }
  641. /// <summary>
  642. /// 鼠标离开控件
  643. /// </summary>
  644. /// <param name="e"></param>
  645. protected override void OnMouseLeave(EventArgs e)
  646. {
  647. base.OnMouseLeave(e);
  648. this.MouseOver = false;
  649. }
  650. /// <summary>
  651. /// 鼠标移动
  652. /// </summary>
  653. /// <param name="e"></param>
  654. protected override void OnMouseMove(MouseEventArgs e)
  655. {
  656. base.OnMouseMove(e);
  657. }
  658. /// <summary>
  659. /// 鼠标按下
  660. /// </summary>
  661. /// <param name="e"></param>
  662. protected override void OnMouseDown(MouseEventArgs e)
  663. {
  664. base.OnMouseDown(e);
  665. }
  666. /// <summary>
  667. /// 鼠标抬起
  668. /// </summary>
  669. /// <param name="e"></param>
  670. protected override void OnMouseUp(MouseEventArgs e)
  671. {
  672. base.OnMouseUp(e);
  673. }
  674. #endregion
  675. #endregion
  676. #region 重写方法
  677. /// <summary>
  678. /// 返回表示当前 System.Windows.Forms.DateTimePicker 控件的字符串。
  679. /// </summary>
  680. /// <returns></returns>
  681. public override string ToString()
  682. {
  683. if (this._nullValue)
  684. {
  685. return string.Empty;
  686. }
  687. return base.ToString();
  688. }
  689. /*
  690. public struct NMHDR
  691. {
  692. public IntPtr hwndFrom;
  693. public IntPtr idFrom;
  694. public int code;
  695. }
  696. [StructLayout(LayoutKind.Sequential)]
  697. public class SYSTEMTIME
  698. {
  699. public short wYear;
  700. public short wMonth;
  701. public short wDayOfWeek;
  702. public short wDay;
  703. public short wHour;
  704. public short wMinute;
  705. public short wSecond;
  706. public short wMilliseconds;
  707. public override string ToString()
  708. {
  709. return string.Concat(new string[]
  710. {
  711. "[SYSTEMTIME: ",
  712. this.wDay.ToString(CultureInfo.InvariantCulture),
  713. "/",
  714. this.wMonth.ToString(CultureInfo.InvariantCulture),
  715. "/",
  716. this.wYear.ToString(CultureInfo.InvariantCulture),
  717. " ",
  718. this.wHour.ToString(CultureInfo.InvariantCulture),
  719. ":",
  720. this.wMinute.ToString(CultureInfo.InvariantCulture),
  721. ":",
  722. this.wSecond.ToString(CultureInfo.InvariantCulture),
  723. "]"
  724. });
  725. }
  726. }
  727. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  728. public class NMDATETIMECHANGE
  729. {
  730. public NMHDR nmhdr;
  731. public int dwFlags;
  732. public SYSTEMTIME st;
  733. }
  734. internal static SYSTEMTIME DateTimeToSysTime(DateTime time)
  735. {
  736. return new SYSTEMTIME
  737. {
  738. wYear = (short)time.Year,
  739. wMonth = (short)time.Month,
  740. wDayOfWeek = (short)time.DayOfWeek,
  741. wDay = (short)time.Day,
  742. wHour = (short)time.Hour,
  743. wMinute = (short)time.Minute,
  744. wSecond = (short)time.Second,
  745. wMilliseconds = 0
  746. };
  747. }
  748. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  749. public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, SYSTEMTIME lParam);
  750. */
  751. /// <summary>
  752. /// 处理 Windows 消息
  753. /// </summary>
  754. /// <param name="m">要处理的 Windows System.Windows.Forms.Message</param>
  755. protected override void WndProc(ref Message m)
  756. {
  757. /*
  758. if (m.Msg == 0x204E)
  759. {
  760. if (m.HWnd == base.Handle)
  761. {
  762. NMDATETIMECHANGE nMDATETIMECHANGE = (NMDATETIMECHANGE)m.GetLParam(typeof(NMDATETIMECHANGE));
  763. if (nMDATETIMECHANGE.nmhdr.code == -759)
  764. {
  765. if (nMDATETIMECHANGE.dwFlags != 1)
  766. {
  767. if (nMDATETIMECHANGE.st.wYear == 0)
  768. {
  769. return;
  770. }
  771. }
  772. }
  773. }
  774. }
  775. */
  776. if (this.ShowUpDown)
  777. {
  778. if (this._updown == null)
  779. {
  780. DateTimePickerBase.EnumChildren enumChildren = new DateTimePickerBase.EnumChildren();
  781. DateTimePickerBase.EnumChildrenCallback lpEnumFunc = new DateTimePickerBase.EnumChildrenCallback(enumChildren.enumChildren);
  782. DateTimePickerBase.EnumChildWindows(new HandleRef(this, base.Handle), lpEnumFunc, WindowsAPI.NullHandleRef);
  783. if (enumChildren.hwndFound != IntPtr.Zero)
  784. {
  785. this._updown = new ChildNativeWindow(this, "UpDown");
  786. this._updown.AssignHandle(enumChildren.hwndFound);
  787. }
  788. }
  789. }
  790. else
  791. {
  792. if (this._updown != null)
  793. {
  794. this._updown.ReleaseHandle();
  795. this._updown = null;
  796. }
  797. }
  798. base.WndProc(ref m);
  799. // 释放句柄
  800. if (m.Msg == (int)WindowsMessage.WM_NCDESTROY)
  801. {
  802. if (this._updown != null)
  803. {
  804. this._updown.ReleaseHandle();
  805. this._updown = null;
  806. }
  807. return;
  808. }
  809. if (m.Msg == (int)WindowsMessage.WM_PAINT ||
  810. m.Msg == (int)WindowsMessage.WM_NCPAINT ||
  811. m.Msg == (int)WindowsMessage.WM_CTLCOLOREDIT)
  812. {
  813. BorderColorPaint.WmBorderPaint(this._borderColor, this.Width, this.Height, ref m);
  814. }
  815. }
  816. #endregion
  817. #region 公有方法
  818. #endregion
  819. #region 保护方法
  820. /// <summary>
  821. /// 处理DateTimePickerBase内部控件的消息
  822. /// </summary>
  823. /// <param name="child">UpDown</param>
  824. /// <param name="m">消息</param>
  825. /// <returns>消息是否已经处理过</returns>
  826. public virtual bool ChildWndProc(ChildNativeWindow child, ref Message m)
  827. {
  828. switch (m.Msg)
  829. {
  830. case (int)WindowsMessage.WM_LBUTTONDOWN:
  831. if (this._nullValue)
  832. {
  833. this.SetDateValueNotNull();
  834. if (!this.Focused)
  835. {
  836. this.Focus();
  837. }
  838. SendKeys.SendWait("{RIGHT}");
  839. return true;
  840. }
  841. break;
  842. }
  843. return false;
  844. }
  845. #endregion
  846. #region 私有方法
  847. /// <summary>
  848. /// 使父控件的指定区域无效(将其添加到控件的更新区域,下次绘制操作时将重新绘制更新区域),并向父控件发送绘制消息。
  849. /// </summary>
  850. private void InvalidateBorder()
  851. {
  852. Color? borderColor = BorderColorPaint.GetBorderColor(this as IDataVerifiable, this._entered, this._mouseOver);
  853. if (borderColor != this._borderColor)
  854. {
  855. this._borderColor = borderColor;
  856. if (this.Parent == null)
  857. {
  858. this.Invalidate();
  859. }
  860. else
  861. {
  862. this.Parent.Invalidate(this.Bounds, true);
  863. }
  864. }
  865. }
  866. /// <summary>
  867. /// 设置日期
  868. /// </summary>
  869. /// <param name="value">日期</param>
  870. private void SetDateValueNotNull(DateTime value)
  871. {
  872. if (this._nullValue)
  873. {
  874. base.Format = this._format;
  875. base.CustomFormat = this._customFormat;
  876. this._nullValue = false;
  877. if (base.Value != value)
  878. {
  879. this.SetBaseValue(value);
  880. }
  881. else
  882. {
  883. this.OnValueChanged(EventArgs.Empty);
  884. this.OnValidated(EventArgs.Empty);
  885. }
  886. }
  887. else
  888. {
  889. if (base.Value != value)
  890. {
  891. this.SetBaseValue(value);
  892. }
  893. }
  894. }
  895. /// <summary>
  896. /// 设置空日期
  897. /// </summary>
  898. private void SetDateValueNull()
  899. {
  900. base.Format = DateTimePickerFormat.Custom;
  901. base.CustomFormat = Constant.S_SPACE;
  902. this._nullValue = true;
  903. // TODO null 时的默认时间
  904. this.SetBaseValue(DateTime.Now);
  905. }
  906. /// <summary>
  907. /// 设置日期(当前时间)
  908. /// </summary>
  909. private void SetDateValueNotNull()
  910. {
  911. base.Format = this._format;
  912. base.CustomFormat = this._customFormat;
  913. this._nullValue = false;
  914. // TODO null 时的默认时间
  915. this.SetBaseValue(DateTime.Now);
  916. }
  917. /// <summary>
  918. /// 设置日期
  919. /// </summary>
  920. /// <param name="vaue">日期</param>
  921. private void SetBaseValue(DateTime vaue)
  922. {
  923. this._isSetValue = true;
  924. base.Value = vaue;
  925. this._isSetValue = false;
  926. if (!this.Focused)
  927. {
  928. this.OnValidated(EventArgs.Empty);
  929. }
  930. }
  931. #endregion
  932. #region IDataVerifiable 成员
  933. #region 成员变量
  934. /// <summary>
  935. /// 显示边框颜色
  936. /// </summary>
  937. private bool _showBorderColor = true;
  938. /// <summary>
  939. /// 控件的项目名
  940. /// </summary>
  941. private string _itemName = null;
  942. /// <summary>
  943. /// 控件是否是必须输入项目
  944. /// </summary>
  945. private bool _mustInput = false;
  946. /// <summary>
  947. /// 控件在验证输入错误时,如何提示
  948. /// </summary>
  949. private InputErrorAlert _errorAlert = InputErrorAlert.Validated;
  950. /// <summary>
  951. /// 是否显示必须输入项目的提示
  952. /// </summary>
  953. private bool _showMustInputAlert = true;
  954. /// <summary>
  955. /// 验证不通过时,焦点能否离开
  956. /// </summary>
  957. private bool _canLostFocusOnError = true;
  958. /// <summary>
  959. /// 验证是否有错误
  960. /// </summary>
  961. private bool _hasError = false;
  962. /// <summary>
  963. /// 是否自定义错误
  964. /// </summary>
  965. private bool _hasCustomerError = false;
  966. /// <summary>
  967. /// 错误编码
  968. /// </summary>
  969. private ControlErrorCode _errorCode = ControlErrorCode.DKC_0000;
  970. /// <summary>
  971. /// 错误消息
  972. /// </summary>
  973. private string _errorMessage = null;
  974. /// <summary>
  975. /// 自定义错误消息
  976. /// </summary>
  977. private string _customerErrorMessage = null;
  978. #endregion
  979. #region 属性
  980. /// <summary>
  981. /// 获取或设置控件是否显示边框颜色。
  982. /// </summary>
  983. [Description("获取或设置控件是否显示边框颜色。"), Category("IDataVerifiable")]
  984. [DefaultValue(true)]
  985. public bool ShowBorderColor
  986. {
  987. get
  988. {
  989. return this._showBorderColor;
  990. }
  991. set
  992. {
  993. if (this._showBorderColor != value)
  994. {
  995. this._showBorderColor = value;
  996. this.InvalidateBorder();
  997. }
  998. }
  999. }
  1000. /// <summary>
  1001. /// 获取或设置控件的项目名
  1002. /// </summary>
  1003. [Description("获取或设置控件的项目名。"), Category("IDataVerifiable")]
  1004. [DefaultValue(null)]
  1005. public string CDItemName
  1006. {
  1007. get
  1008. {
  1009. return this._itemName;
  1010. }
  1011. set
  1012. {
  1013. this._itemName = value;
  1014. }
  1015. }
  1016. /// <summary>
  1017. /// 获取或设置控件是否必须选中项目。
  1018. /// </summary>
  1019. [Description("获取或设置控件是否必须选中项目。"), Category("IDataVerifiable")]
  1020. [DefaultValue(false)]
  1021. public bool MustInput
  1022. {
  1023. get
  1024. {
  1025. return this._mustInput;
  1026. }
  1027. set
  1028. {
  1029. if (this._mustInput != value)
  1030. {
  1031. this._mustInput = value;
  1032. this.ValidateData();
  1033. if (this._mustInput && this._showMustInputAlert)
  1034. {
  1035. this.InvalidateBorder();
  1036. }
  1037. }
  1038. }
  1039. }
  1040. /// <summary>
  1041. /// 获取或设置控件是否必须选中项目。
  1042. /// </summary>
  1043. [Description("获取或设置控件在验证输入错误时,如何提示。"), Category("IDataVerifiable")]
  1044. [DefaultValue(typeof(InputErrorAlert), "Validated")]
  1045. public InputErrorAlert InputErrorAlert
  1046. {
  1047. get
  1048. {
  1049. return this._errorAlert;
  1050. }
  1051. set
  1052. {
  1053. if (this._errorAlert != value)
  1054. {
  1055. this._errorAlert = value;
  1056. this.InvalidateBorder();
  1057. }
  1058. }
  1059. }
  1060. /// <summary>
  1061. /// 获取或设置控件是否显示必须输入项目提示
  1062. /// </summary>
  1063. [Description("获取或设置控件是否显示必须输入项目提示。"), Category("IDataVerifiable")]
  1064. [DefaultValue(true)]
  1065. public bool ShowMustInputAlert
  1066. {
  1067. get
  1068. {
  1069. return this._showMustInputAlert;
  1070. }
  1071. set
  1072. {
  1073. if (this._showMustInputAlert != value)
  1074. {
  1075. this._showMustInputAlert = value;
  1076. this.InvalidateBorder();
  1077. }
  1078. }
  1079. }
  1080. /// <summary>
  1081. /// 获取或设置当验证不通过时,控件是否可以失去焦点
  1082. /// </summary>
  1083. [Description("获取或设置当验证不通过时,控件是否可以失去焦点。"), Category("IDataVerifiable")]
  1084. [DefaultValue(true)]
  1085. public bool CanLostFocusOnError
  1086. {
  1087. get
  1088. {
  1089. return this._canLostFocusOnError;
  1090. }
  1091. set
  1092. {
  1093. this._canLostFocusOnError = value;
  1094. }
  1095. }
  1096. /// <summary>
  1097. /// 获取控件校验时是否有错误
  1098. /// </summary>
  1099. [Description("获取控件校验时是否有错误。"), Category("IDataVerifiable")]
  1100. [DefaultValue(false)]
  1101. public bool HasError
  1102. {
  1103. get
  1104. {
  1105. return this._hasCustomerError || this._hasError;
  1106. }
  1107. }
  1108. /// <summary>
  1109. /// 获取控件校验时的错误编码
  1110. /// </summary>
  1111. [Description("获取控件校验时的错误编码。"), Category("IDataVerifiable")]
  1112. [DefaultValue(typeof(ControlErrorCode), "DKC_0000")]
  1113. public ControlErrorCode ErrorCode
  1114. {
  1115. get
  1116. {
  1117. return this._hasCustomerError ? ControlErrorCode.DKC_C001 : this._errorCode;
  1118. }
  1119. }
  1120. /// <summary>
  1121. /// 获取控件校验时的错误消息
  1122. /// </summary>
  1123. [Description("获取控件校验时的错误编码。"), Category("IDataVerifiable")]
  1124. [DefaultValue(null)]
  1125. public string ErrorMessage
  1126. {
  1127. get
  1128. {
  1129. return this._hasCustomerError ? this._customerErrorMessage : this._errorMessage;
  1130. }
  1131. }
  1132. #endregion
  1133. #region 公有方法
  1134. /// <summary>
  1135. /// 设置自定义错误
  1136. /// </summary>
  1137. /// <param name="hasError">输入是否有错误</param>
  1138. /// <param name="errorMessage">错误消息</param>
  1139. public virtual void SetCustomerError(bool hasError, string errorMessage)
  1140. {
  1141. if (this._hasCustomerError != hasError ||
  1142. this._customerErrorMessage != errorMessage)
  1143. {
  1144. this._hasCustomerError = hasError;
  1145. this._customerErrorMessage = errorMessage;
  1146. this.OnHasErrorChanged(EventArgs.Empty);
  1147. this.InvalidateBorder();
  1148. }
  1149. }
  1150. /// <summary>
  1151. /// 清除自定义错误
  1152. /// </summary>
  1153. public virtual void ClearCustomerError()
  1154. {
  1155. this.SetCustomerError(false, null);
  1156. }
  1157. /// <summary>
  1158. /// 验证输入内容
  1159. /// </summary>
  1160. /// <returns>验证结果</returns>
  1161. public virtual bool ValidateData()
  1162. {
  1163. if (this._mustInput && this._nullValue)
  1164. {
  1165. this.SetError(true, ControlErrorCode.DKC_0001, this._itemName);
  1166. return true;
  1167. }
  1168. this.ClearError();
  1169. return false;
  1170. }
  1171. /// <summary>
  1172. /// 清除输入项
  1173. /// </summary>
  1174. public virtual void ClearValue()
  1175. {
  1176. //this.Value = null;
  1177. if (this._allowNull)
  1178. {
  1179. this.Value = null;
  1180. }
  1181. else
  1182. {
  1183. this.Value = DateTime.Now;
  1184. }
  1185. }
  1186. #endregion
  1187. #region 保护方法
  1188. /// <summary>
  1189. /// 设置验证不通过错误
  1190. /// </summary>
  1191. /// <param name="hasError">是否有错误</param>
  1192. /// <param name="code">错误编码</param>
  1193. /// <param name="args">设置格式的对象</param>
  1194. protected void SetError(bool hasError, ControlErrorCode code, params object[] args)
  1195. {
  1196. if (this._hasError != hasError ||
  1197. this._errorCode != code)
  1198. {
  1199. this._hasError = hasError;
  1200. this._errorCode = code;
  1201. if (args != null && args.Length > 0)
  1202. {
  1203. this._errorMessage = string.Format(code.GetDescription(), args);
  1204. }
  1205. else
  1206. {
  1207. this._errorMessage = code.GetDescription();
  1208. }
  1209. this.OnHasErrorChanged(EventArgs.Empty);
  1210. this.InvalidateBorder();
  1211. }
  1212. }
  1213. /// <summary>
  1214. /// 清除验证不通过错误
  1215. /// </summary>
  1216. protected void ClearError()
  1217. {
  1218. this.SetError(false, ControlErrorCode.DKC_0000);
  1219. }
  1220. #endregion
  1221. #endregion
  1222. #region IAsyncControl 成员
  1223. /// <summary>
  1224. /// 异步处理开始时,控件状态
  1225. /// </summary>
  1226. private bool _asyncBeginStatus = false;
  1227. private bool _asyncBeginFocused = false;
  1228. /// <summary>
  1229. /// 异步处理开始
  1230. /// </summary>
  1231. /// <param name="doFocus">是否处理焦点</param>
  1232. public virtual void BeginAsync(ref bool doFocus)
  1233. {
  1234. this._asyncBeginFocused = false;
  1235. if (doFocus && this.Focused)
  1236. {
  1237. this._asyncBeginFocused = true;
  1238. doFocus = false;
  1239. }
  1240. this._asyncBeginStatus = this.Enabled;
  1241. this.Enabled = false;
  1242. }
  1243. /// <summary>
  1244. /// 异步处理结束
  1245. /// </summary>
  1246. public virtual void EndAsync()
  1247. {
  1248. this.Enabled = this._asyncBeginStatus;
  1249. if (this._asyncBeginFocused)
  1250. {
  1251. this.Focus();
  1252. }
  1253. }
  1254. #endregion
  1255. }
  1256. }