Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for datetimebox.cs

(view source code of datetimebox.cs as plain text)

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Globalization;
  5. using System.IO;
  6. using System.Runtime.InteropServices;
  7. using System.Text;
  8. using System.Text.RegularExpressions;
  9. using System.Windows.Forms;
  10.  
  11.  
  12. namespace RobvanderWoude
  13. {
  14. 	class DateTimeBox
  15. 	{
  16. 		static string progver = "1.12.1";
  17.  
  18.  
  19. 		static int Main( string[] args )
  20. 		{
  21. 			try
  22. 			{
  23. 				#region Initialize Variables
  24.  
  25. 				int minwidth = 220;
  26. 				int minheight = 135;
  27. 				int maxwidth = Screen.PrimaryScreen.WorkingArea.Width;
  28. 				int maxheight = Screen.PrimaryScreen.WorkingArea.Height;
  29. 				int width = minwidth;
  30. 				int height = minheight;
  31. 				int icon = 167;
  32. 				int maxdaysfuture = 0;
  33. 				int mindaysfuture = 0;
  34. 				bool maxdaysset = false;
  35. 				bool mindaysset = false;
  36. 				bool dateonly = false;
  37. 				bool timeonly = false;
  38. 				bool initialtimeset = false;
  39. 				bool daterangeset = false;
  40. 				bool localizedcaptionset = false;
  41. 				bool canuseampm = !String.IsNullOrWhiteSpace( DateTimeFormatInfo.CurrentInfo.PMDesignator );
  42. 				bool ignoreampm = false;
  43. 				bool appendampm = false;
  44. 				string title = String.Format( "DateTimeBox,  Version {0}", progver );
  45. 				string dateformatgui = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
  46. 				string dateformatout = "yyyy-MM-dd";
  47. 				string timeformatgui = CultureInfo.CurrentCulture.DateTimeFormat.LongTimePattern;
  48. 				string timeformatout = "HH:mm:ss";
  49. 				string datetimeformatout = String.Empty;
  50. 				string cancelcaption = "&Cancel";
  51. 				string okcaption = "&OK";
  52. 				string localizationstring = String.Empty;
  53. 				string initialdatetimestring = String.Empty;
  54. 				DateTime initialdatetime = DateTime.Now;
  55. 				DateTime today = DateTime.Now.Date;
  56. 				DateTime earliest = today.Date;
  57. 				DateTime latest = today.Date;
  58.  
  59.  
  60. 				#endregion Initialize Variables
  61.  
  62.  
  63. 				#region Command Line Parsing
  64.  
  65. 				if ( args.Length > 16 )
  66. 				{
  67. 					return ShowHelp( "Too many command line arguments" );
  68. 				}
  69. 				if ( args.Length > 0 )
  70. 				{
  71. 					foreach ( string arg in args )
  72. 					{
  73. 						if ( arg == "/?" )
  74. 						{
  75. 							return ShowHelp( );
  76. 						}
  77. 					}
  78. 					string localizationpattern = "(;|^)(OK|Cancel)=[^\\\"';]+(;|$)";
  79. 					string datepattern = ".*[dgkmy]+.*";
  80. 					string datetimepattern = ".*[dfghkmstyz]+.*";
  81. 					string timepattern = ".*[fhmstz]+.*";
  82. 					int count = 0;
  83. 					foreach ( string arg in args )
  84. 					{
  85. 						if ( count == 0 && arg.IndexOf( '/' ) == -1 )
  86. 						{
  87. 							// Title can only be specified as the first argument
  88. 							if ( !String.IsNullOrWhiteSpace( arg ) )
  89. 							{
  90. 								title = arg;
  91. 							}
  92. 						}
  93. 						else if ( count == 1 && arg.IndexOf( '/' ) == -1 )
  94. 						{
  95. 							// Initial date/time can only be the second argument
  96. 							initialdatetimestring = arg;
  97. 							initialtimeset = true;
  98. 						}
  99. 						else
  100. 						{
  101. 							if ( arg.IndexOf( '/' ) != 0 )
  102. 							{
  103. 								return ShowHelp( "Invalid command line argument \"{0}\"", arg );
  104. 							}
  105. 							string key = arg;
  106. 							string format = String.Empty;
  107. 							if ( arg.IndexOfAny( ":=".ToCharArray( ) ) != -1 )
  108. 							{
  109. 								key = arg.Substring( 0, arg.ToUpper( ).IndexOfAny( ":=".ToCharArray( ) ) );
  110. 								format = arg.Substring( arg.IndexOfAny( ":=".ToCharArray( ) ) + 1 );
  111. 							}
  112. 							switch ( key.ToUpper( ) )
  113. 							{
  114. 								case "/D":
  115. 									if ( dateonly )
  116. 									{
  117. 										return ShowHelp( "Duplicate command line switch /D" );
  118. 									}
  119. 									dateonly = true;
  120. 									break;
  121. 								case "/DD":
  122. 									dateformatgui = format;
  123. 									if ( !Regex.IsMatch( format, datepattern, RegexOptions.IgnoreCase ) )
  124. 									{
  125. 										return ShowHelp( "Invalid value for {0} switch: \"{1}\"", key.ToUpper( ), format );
  126. 									}
  127. 									break;
  128. 								case "/DE":
  129. 									if ( mindaysset )
  130. 									{
  131. 										return ShowHelp( "Duplicate start of allowed date range /DMIN and/or /DE" );
  132. 									}
  133. 									try
  134. 									{
  135. 										DateTime.TryParse( format, out earliest );
  136. 										mindaysfuture = ( earliest - today ).Days;
  137. 									}
  138. 									catch ( Exception )
  139. 									{
  140. 										return ShowHelp( "Invalid date format: {0}", arg );
  141. 									}
  142. 									daterangeset = true;
  143. 									mindaysset = true;
  144. 									break;
  145. 								case "/DL":
  146. 									if ( maxdaysset )
  147. 									{
  148. 										return ShowHelp( "Duplicate end of allowed date range /DMAX and/or /DL" );
  149. 									}
  150. 									try
  151. 									{
  152. 										DateTime.TryParse( format, out latest );
  153. 										maxdaysfuture = ( latest - today ).Days;
  154. 									}
  155. 									catch ( Exception )
  156. 									{
  157. 										return ShowHelp( "Invalid date format: {0}", arg );
  158. 									}
  159. 									daterangeset = true;
  160. 									maxdaysset = true;
  161. 									break;
  162. 								case "/DMAX":
  163. 									if ( maxdaysset )
  164. 									{
  165. 										return ShowHelp( "Duplicate end of allowed date range /DMAX and/or /DL" );
  166. 									}
  167. 									try
  168. 									{
  169. 										maxdaysfuture = Convert.ToInt32( format );
  170. 										latest = today.AddDays( maxdaysfuture );
  171. 									}
  172. 									catch ( Exception )
  173. 									{
  174. 										return ShowHelp( "Invalid /DMAX integer value \"{0}\"", format );
  175. 									}
  176. 									daterangeset = true;
  177. 									maxdaysset = true;
  178. 									break;
  179. 								case "/DMIN":
  180. 									if ( mindaysset )
  181. 									{
  182. 										return ShowHelp( "Duplicate start of allowed date range /DMIN and/or /DE" );
  183. 									}
  184. 									try
  185. 									{
  186. 										mindaysfuture = Convert.ToInt32( format );
  187. 										earliest = today.AddDays( mindaysfuture );
  188. 									}
  189. 									catch ( Exception )
  190. 									{
  191. 										return ShowHelp( "Invalid /DMIN integer value \"{0}\"", format );
  192. 									}
  193. 									daterangeset = true;
  194. 									mindaysset = true;
  195. 									break;
  196. 								case "/DO":
  197. 									dateformatout = format;
  198. 									if ( !Regex.IsMatch( format, datepattern, RegexOptions.IgnoreCase ) )
  199. 									{
  200. 										return ShowHelp( "Invalid value for {0} switch: \"{1}\"", key.ToUpper( ), format );
  201. 									}
  202. 									break;
  203. 								case "/DTO":
  204. 									datetimeformatout = format;
  205. 									if ( !Regex.IsMatch( format, datetimepattern, RegexOptions.IgnoreCase ) )
  206. 									{
  207. 										return ShowHelp( "Invalid value for {0} switch: \"{1}\"", key.ToUpper( ), format );
  208. 									}
  209. 									break;
  210. 								case "/FT":
  211. 									if ( initialtimeset )
  212. 									{
  213. 										return ShowHelp( "Duplicate initial date/time specification, use either \"{0}\" or {1}, not both", initialdatetimestring, arg );
  214. 									}
  215. 									string file = format;
  216. 									if ( File.Exists( file ) )
  217. 									{
  218. 										initialdatetime = File.GetLastWriteTime( file );
  219. 									}
  220. 									else
  221. 									{
  222. 										return ShowHelp( "File not found: \"{0}\"", file );
  223. 									}
  224. 									break;
  225. 								case "/H":
  226. 									if ( height != minheight )
  227. 									{
  228. 										return ShowHelp( "Duplicate command line switch /H" );
  229. 									}
  230. 									try
  231. 									{
  232. 										height = Convert.ToInt32( format );
  233. 									}
  234. 									catch ( Exception )
  235. 									{
  236. 										return ShowHelp( "Invalid height specified: {0}", arg );
  237. 									}
  238. 									break;
  239. 								case "/I":
  240. 									try
  241. 									{
  242. 										icon = Convert.ToInt32( format );
  243. 										if ( IconExtractor.Extract( "shell32.dll", icon, true ) == null )
  244. 										{
  245. 											return ShowHelp( "Invalid icon index specified for Shell32.dll: {0}", arg );
  246. 										}
  247. 									}
  248. 									catch ( Exception )
  249. 									{
  250. 										return ShowHelp( "Invalid icon index specified for Shell32.dll: {0}", arg );
  251. 									}
  252. 									break;
  253. 								case "/I24":
  254. 									ignoreampm = true;
  255. 									break;
  256. 								case "/L":
  257. 									localizedcaptionset = true;
  258. 									localizationstring = format;
  259. 									foreach ( string test in format.Split( ";".ToCharArray( ), StringSplitOptions.RemoveEmptyEntries ) )
  260. 									{
  261. 										if ( !Regex.IsMatch( format, localizationpattern, RegexOptions.IgnoreCase ) )
  262. 										{
  263. 											return ShowHelp( "Invalid value for {0} switch: \"{1}\"", key.ToUpper( ), format );
  264. 										}
  265. 									}
  266. 									break;
  267. 								case "/O24":
  268. 									appendampm = true;
  269. 									break;
  270. 								case "/T":
  271. 									if ( timeonly )
  272. 									{
  273. 										return ShowHelp( "Duplicate command line switch /T" );
  274. 									}
  275. 									timeonly = true;
  276. 									break;
  277. 								case "/TD":
  278. 									timeformatgui = format;
  279. 									if ( !Regex.IsMatch( format, timepattern, RegexOptions.IgnoreCase ) )
  280. 									{
  281. 										return ShowHelp( "Invalid value for {0} switch: \"{1}\"", key.ToUpper( ), format );
  282. 									}
  283. 									break;
  284. 								case "/TO":
  285. 									timeformatout = format;
  286. 									if ( !Regex.IsMatch( format, timepattern, RegexOptions.IgnoreCase ) )
  287. 									{
  288. 										return ShowHelp( "Invalid value for {0} switch: \"{1}\"", key.ToUpper( ), format );
  289. 									}
  290. 									break;
  291. 								case "/W":
  292. 									if ( width != minwidth )
  293. 									{
  294. 										return ShowHelp( "Duplicate command line switch /W" );
  295. 									}
  296. 									try
  297. 									{
  298. 										width = Convert.ToInt32( format );
  299. 									}
  300. 									catch ( Exception )
  301. 									{
  302. 										return ShowHelp( "Invalid width specified: {0}", arg );
  303. 									}
  304. 									break;
  305. 								default:
  306. 									return ShowHelp( "Invalid command line switch \"{0}\"", arg );
  307. 							}
  308. 						}
  309. 						count += 1;
  310. 					}
  311. 					if ( ( ( dateonly || timeonly ) && !String.IsNullOrWhiteSpace( datetimeformatout ) ) || ( dateonly && timeonly ) )
  312. 					{
  313. 						return ShowHelp( "/D, /T and /DTO cannot be combinded" );
  314. 					}
  315. 				}
  316.  
  317. 				#endregion Command Line Parsing
  318.  
  319.  
  320. 				#region Command Line Validation
  321.  
  322. 				// Validate dialog size
  323. 				if ( dateonly || timeonly )
  324. 				{
  325. 					if ( height == minheight )
  326. 					{
  327. 						height -= 40;
  328. 					}
  329. 					minheight -= 40;
  330. 				}
  331. 				if ( height > maxheight || height < minheight )
  332. 				{
  333. 					return ShowHelp( "Specified height should be in {0}..{1} range", minheight.ToString( ), maxheight.ToString( ) );
  334. 				}
  335. 				if ( width > maxwidth || width < minwidth )
  336. 				{
  337. 					return ShowHelp( "Specified width should be in {0}..{1} range", minwidth.ToString( ), maxwidth.ToString( ) );
  338. 				}
  339.  
  340. 				// Validate format of initial date/time specified
  341. 				if ( !String.IsNullOrEmpty( initialdatetimestring ) )
  342. 				{
  343. 					try
  344. 					{
  345. 						if ( Regex.IsMatch( initialdatetimestring, @"^\d{4}-\d\d-\d\d \d{1,2}:\d\d$" ) )
  346. 						{
  347. 							initialdatetime = DateTime.ParseExact( initialdatetimestring, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture );
  348. 						}
  349. 						else if ( Regex.IsMatch( initialdatetimestring, @"^\d{4}-\d\d-\d\d \d{1,2}:\d\d:\d\d$" ) )
  350. 						{
  351. 							initialdatetime = DateTime.ParseExact( initialdatetimestring, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture );
  352. 						}
  353. 						else if ( dateonly && Regex.IsMatch( initialdatetimestring, @"^\d{4}-\d\d-\d\d$" ) )
  354. 						{
  355. 							initialdatetime = DateTime.ParseExact( initialdatetimestring, "yyyy-MM-dd", CultureInfo.InvariantCulture );
  356. 						}
  357. 						else if ( timeonly && Regex.IsMatch( initialdatetimestring, @"^\d{1,2}:\d\d$" ) )
  358. 						{
  359. 							initialdatetime = DateTime.ParseExact( initialdatetimestring, "HH:mm", CultureInfo.InvariantCulture );
  360. 						}
  361. 						else if ( timeonly && Regex.IsMatch( initialdatetimestring, @"^\d{1,2}:\d\d:\d\d$" ) )
  362. 						{
  363. 							initialdatetime = DateTime.ParseExact( initialdatetimestring, "HH:mm:ss", CultureInfo.InvariantCulture );
  364. 						}
  365. 						else
  366. 						{
  367. 							return ShowHelp( "Invalid initial date/time format in \"{0}\"", initialdatetimestring );
  368. 						}
  369. 					}
  370. 					catch ( Exception )
  371. 					{
  372. 						return ShowHelp( "Invalid initial date/time format in \"{0}\"", initialdatetimestring );
  373. 					}
  374. 				}
  375.  
  376. 				// Validate date range
  377. 				if ( daterangeset )
  378. 				{
  379. 					if ( ( latest - earliest ).Days < 0 )
  380. 					{
  381. 						return ShowHelp( "The earliest allowed date CANNOT be AFTER the latest allowed date" );
  382. 					}
  383. 				}
  384.  
  385. 				#endregion Command Line Validation
  386.  
  387.  
  388. 				#region Set Localized Captions
  389.  
  390. 				if ( localizedcaptionset )
  391. 				{
  392. 					cancelcaption = Load( "user32.dll", 801, cancelcaption );
  393. 					okcaption = Load( "user32.dll", 800, okcaption );
  394.  
  395. 					if ( !String.IsNullOrWhiteSpace( localizationstring ) )
  396. 					{
  397. 						string[] locstrings = localizationstring.Split( ";".ToCharArray( ) );
  398. 						foreach ( string locstring in locstrings )
  399. 						{
  400. 							string key = locstring.Substring( 0, locstring.IndexOf( '=' ) );
  401. 							string val = locstring.Substring( Math.Min( locstring.IndexOf( '=' ) + 1, locstring.Length - 1 ) );
  402. 							if ( !String.IsNullOrWhiteSpace( val ) )
  403. 							{
  404. 								switch ( key.ToUpper( ) )
  405. 								{
  406. 									case "OK":
  407. 										okcaption = val;
  408. 										break;
  409. 									case "CANCEL":
  410. 										cancelcaption = val;
  411. 										break;
  412. 									default:
  413. 										return ShowHelp( "Invalid localization key \"{0}\"", key );
  414. 								}
  415. 							}
  416. 						}
  417. 					}
  418. 				}
  419.  
  420. 				#endregion Set Localized Captions
  421.  
  422.  
  423. 				#region Format check
  424.  
  425. 				// Check if AM/PM is required and available
  426. 				string testformats = ( dateformatgui + dateformatout + datetimeformatout + timeformatgui + timeformatout ).ToLower( );
  427. 				if ( testformats.IndexOf( 't' ) > -1 )
  428. 				{
  429. 					if ( canuseampm )
  430. 					{
  431. 						ignoreampm = false;
  432. 						appendampm = false;
  433. 					}
  434. 					else
  435. 					{
  436. 						if ( timeformatgui.IndexOf( 't' ) > -1 )
  437. 						{
  438. 							if ( ignoreampm )
  439. 							{
  440. 								timeformatgui = Regex.Replace( timeformatgui, @"\s*t+", String.Empty );
  441. 								timeformatgui = Regex.Replace( timeformatgui, "h", "H" );
  442. 							}
  443. 							else
  444. 							{
  445. 								return ShowHelp( "AM/PM time format not available on this computer, use /I24\n\tto ignore this error and use a 24-hour time picker instead,\n\tand /O24 to append AM/PM to the output result" );
  446. 							}
  447. 						}
  448. 						if ( ( timeformatout + datetimeformatout ).IndexOf( 't' ) > -1 )
  449. 						{
  450. 							if ( appendampm )
  451. 							{
  452. 								datetimeformatout = Regex.Replace( datetimeformatout, @"\s*t+", String.Empty );
  453. 								timeformatout = Regex.Replace( timeformatout, @"\s*t+", String.Empty );
  454. 							}
  455. 							else
  456. 							{
  457. 								return ShowHelp( "AM/PM time format not available on this computer,\n\tuse /O24 to append AM/PM to the output result" );
  458. 							}
  459. 						}
  460. 						else
  461. 						{
  462. 							appendampm = false;
  463. 						}
  464. 					}
  465. 				}
  466.  
  467. 				// Check validity of specified formats
  468. 				if ( String.IsNullOrWhiteSpace( datetimeformatout ) )
  469. 				{
  470. 					DateTime d = DateTime.Now;
  471. 					DateTime t = DateTime.Now;
  472. 					string date = String.Empty;
  473. 					string time = String.Empty;
  474. 					if ( !timeonly )
  475. 					{
  476. 						try
  477. 						{
  478. 							date = d.ToString( dateformatgui, CultureInfo.InvariantCulture );
  479. 							d = DateTime.ParseExact( date, dateformatgui, CultureInfo.InvariantCulture );
  480. 						}
  481. 						catch ( FormatException )
  482. 						{
  483. 							return ShowHelp( "Invalid date display format \"{0}\"", dateformatgui );
  484. 						}
  485. 						try
  486. 						{
  487. 							date = d.ToString( dateformatout, CultureInfo.InvariantCulture );
  488. 						}
  489. 						catch ( FormatException )
  490. 						{
  491. 							return ShowHelp( "Invalid date output format \"{0}\"", dateformatout );
  492. 						}
  493. 					}
  494. 					if ( !dateonly )
  495. 					{
  496. 						try
  497. 						{
  498. 							time = t.ToString( timeformatgui, CultureInfo.InvariantCulture );
  499. 							t = DateTime.ParseExact( time, timeformatgui, CultureInfo.InvariantCulture );
  500. 						}
  501. 						catch ( FormatException )
  502. 						{
  503. 							t = DateTime.ParseExact( time, timeformatgui, CultureInfo.CurrentCulture );
  504. 						}
  505. 						try
  506. 						{
  507. 							time = t.ToString( timeformatout, CultureInfo.InvariantCulture );
  508. 						}
  509. 						catch ( FormatException )
  510. 						{
  511. 							return ShowHelp( "Invalid time output format \"{0}\"", timeformatout );
  512. 						}
  513. 					}
  514. 				}
  515. 				else
  516. 				{
  517. 					DateTime dt;
  518. 					string datetime;
  519. 					try
  520. 					{
  521. 						dt = DateTime.ParseExact( DateTime.Now.ToString( dateformatgui + " " + timeformatgui, CultureInfo.InvariantCulture ), dateformatgui + " " + timeformatgui, CultureInfo.InvariantCulture );
  522. 					}
  523. 					catch ( FormatException )
  524. 					{
  525. 						return ShowHelp( "Invalid date/time display format \"{0}\"", dateformatgui + " " + timeformatgui );
  526. 					}
  527. 					try
  528. 					{
  529. 						datetime = dt.ToString( datetimeformatout, CultureInfo.InvariantCulture );
  530. 					}
  531. 					catch ( FormatException )
  532. 					{
  533. 						return ShowHelp( "Invalid date/time output format \"{0}\"", datetimeformatout );
  534. 					}
  535. 				}
  536.  
  537. 				#endregion Format check
  538.  
  539.  
  540. 				#region Form Controls
  541.  
  542. 				Size size = new Size( width, height );
  543. 				Form dtForm = new Form( );
  544. 				dtForm.ClientSize = size;
  545. 				dtForm.FormBorderStyle = FormBorderStyle.FixedDialog;
  546. 				dtForm.MaximizeBox = false;
  547. 				dtForm.MinimizeBox = false;
  548. 				dtForm.StartPosition = FormStartPosition.CenterScreen;
  549. 				dtForm.Text = title;
  550. 				dtForm.Icon = IconExtractor.Extract( "shell32.dll", icon, true );
  551.  
  552. 				Point firstrow = new Point( 15, 15 );
  553. 				Point secondrow = new Point( 15, 55 );
  554.  
  555. 				DateTimePicker datePicker = null;
  556. 				if ( !timeonly )
  557. 				{
  558. 					datePicker = new DateTimePicker( );
  559. 					if ( timeonly || String.IsNullOrWhiteSpace( dateformatgui ) )
  560. 					{
  561. 						datePicker.Format = DateTimePickerFormat.Long;
  562. 					}
  563. 					else
  564. 					{
  565. 						datePicker.CustomFormat = dateformatgui;
  566. 						datePicker.Format = DateTimePickerFormat.Custom;
  567. 					}
  568. 					datePicker.Location = firstrow;
  569. 					if ( daterangeset )
  570. 					{
  571. 						datePicker.MaxDate = latest;
  572. 						datePicker.MinDate = earliest;
  573. 					}
  574. 					datePicker.Size = new Size( size.Width - 30, 25 );
  575. 					if ( daterangeset )
  576. 					{
  577. 						if ( ( earliest - initialdatetime ).Days > 0 )
  578. 						{
  579. 							datePicker.Value = earliest;
  580. 						}
  581. 						else if ( ( initialdatetime - latest ).Days > 0 )
  582. 						{
  583. 							datePicker.Value = latest;
  584. 						}
  585. 						else
  586. 						{
  587. 							datePicker.Value = initialdatetime;
  588. 						}
  589. 					}
  590. 					else
  591. 					{
  592. 						datePicker.Value = initialdatetime;
  593. 					}
  594. 					dtForm.Controls.Add( datePicker );
  595. 				}
  596.  
  597. 				DateTimePicker timePicker = null;
  598. 				if ( !dateonly )
  599. 				{
  600. 					timePicker = new DateTimePicker( );
  601. 					if ( dateonly || String.IsNullOrWhiteSpace( timeformatgui ) )
  602. 					{
  603. 						timePicker.Format = DateTimePickerFormat.Time;
  604. 					}
  605. 					else
  606. 					{
  607. 						timePicker.CustomFormat = timeformatgui;
  608. 						timePicker.Format = DateTimePickerFormat.Custom;
  609. 					}
  610. 					if ( timeonly )
  611. 					{
  612. 						timePicker.Location = firstrow;
  613. 					}
  614. 					else
  615. 					{
  616. 						timePicker.Location = secondrow;
  617. 					}
  618. 					timePicker.ShowUpDown = true;
  619. 					timePicker.Size = new Size( size.Width - 30, 25 );
  620. 					timePicker.Value = initialdatetime;
  621. 					dtForm.Controls.Add( timePicker );
  622. 				}
  623.  
  624. 				Button okButton = new Button( );
  625. 				okButton.DialogResult = DialogResult.OK;
  626. 				okButton.Name = "okButton";
  627. 				okButton.Size = new Size( 80, 25 );
  628. 				okButton.Text = okcaption;
  629. 				okButton.Location = new Point( size.Width / 2 - 10 - 80, size.Height - 43 );
  630. 				dtForm.Controls.Add( okButton );
  631.  
  632. 				Button cancelButton = new Button( );
  633. 				cancelButton.DialogResult = DialogResult.Cancel;
  634. 				cancelButton.Name = "cancelButton";
  635. 				cancelButton.Size = new Size( 80, 25 );
  636. 				cancelButton.Text = cancelcaption;
  637. 				cancelButton.Location = new Point( size.Width / 2 + 10, size.Height - 43 );
  638. 				dtForm.Controls.Add( cancelButton );
  639.  
  640. 				dtForm.AcceptButton = okButton;  // OK on Enter
  641. 				dtForm.CancelButton = cancelButton; // Cancel on Esc
  642. 				dtForm.Activate( );
  643.  
  644. 				#endregion Form Controls
  645.  
  646.  
  647. 				DialogResult result = dtForm.ShowDialog( );
  648. 				if ( result == DialogResult.OK )
  649. 				{
  650. 					string datetime = String.Empty;
  651. 					string ampm = String.Empty;
  652. 					if ( String.IsNullOrWhiteSpace( datetimeformatout ) )
  653. 					{
  654. 						string date = String.Empty;
  655. 						string time = String.Empty;
  656. 						if ( !timeonly )
  657. 						{
  658. 							date = DateTime.ParseExact( datePicker.Text, dateformatgui, CultureInfo.InvariantCulture ).ToString( dateformatout, CultureInfo.InvariantCulture );
  659. 						}
  660. 						if ( !dateonly )
  661. 						{
  662. 							try
  663. 							{
  664. 								time = DateTime.ParseExact( timePicker.Text, timeformatgui, CultureInfo.InvariantCulture ).ToString( timeformatout, CultureInfo.InvariantCulture );
  665. 							}
  666. 							catch ( FormatException )
  667. 							{
  668. 								time = DateTime.ParseExact( timePicker.Text, timeformatgui, CultureInfo.CurrentCulture ).ToString( timeformatout, CultureInfo.InvariantCulture );
  669. 							}
  670. 						}
  671. 						if ( !canuseampm && appendampm )
  672. 						{
  673. 							ampm = DateTime.ParseExact( timePicker.Text, timeformatgui, CultureInfo.CurrentCulture ).ToString( "tt", new CultureInfo( "en-US" ) );
  674. 						}
  675. 						Console.WriteLine( String.Format( "{0}, {1} {2}", date, time, ampm ).Trim( ", ".ToCharArray( ) ) );
  676. 					}
  677. 					else
  678. 					{
  679. 						datetime = DateTime.ParseExact( datePicker.Text + " " + timePicker.Text, dateformatgui + " " + timeformatgui, CultureInfo.InvariantCulture ).ToString( datetimeformatout, CultureInfo.InvariantCulture );
  680. 						if ( !canuseampm && appendampm )
  681. 						{
  682. 							ampm = DateTime.ParseExact( timePicker.Text, timeformatgui, CultureInfo.CurrentCulture ).ToString( "tt", new CultureInfo( "en-US" ) );
  683. 						}
  684. 						Console.WriteLine( String.Format( "{0} {1}", datetime, ampm ).Trim( ) );
  685. 					}
  686. 					return 0;
  687. 				}
  688. 				else
  689. 				{
  690. 					return 2; // Canceled
  691. 				}
  692. 			}
  693. 			catch ( Exception e )
  694. 			{
  695. 				return ShowHelp( "{0}\n\t{1}", e.Message, e.StackTrace );
  696. 			}
  697. 		}
  698.  
  699.  
  700. 		#region Error handling
  701.  
  702. 		public static int ShowHelp( params string[] errmsg )
  703. 		{
  704. 			#region Help Text
  705.  
  706. 			/*
  707. 			DateTimeBox,  Version 1.12
  708. 			Batch tool to present a Date/Time Picker dialog and return the selected
  709. 			date and/or time in the specified format
  710.  
  711. 			Usage:    DATETIMEBOX  [ "title" ]  [ "datetime" ]  [ options ]
  712.  
  713. 			Where:    "title"    is the optional caption in the title bar
  714. 			                     (default: program name and version)
  715. 			          "datetime" is the optional initial date/time for the dialog
  716. 			                     in "yyyy-MM-dd HH:mm" format      (default: now)
  717. 			          options    /D   display and return Date only (default: date and time)
  718. 			                     /T   display and return Time only (default: date and time)
  719. 			                     /I24 Ignore AM/PM in Input on systems with 24-hour format
  720. 			                     /O24 append AM/PM to Output on systems with 24-hour format
  721. 			                     /FT:"file"          use File Timestamp of specified file
  722. 			                                         for the dialog's initial date/time
  723. 			                     /DD:dateformat      Date Display format (GUI)
  724. 			                     /DO:dateformat      Date Output string format
  725. 			                     /TD:timeformat      Time Display format (GUI)
  726. 			                     /TO:timeformat      Time Output string format
  727. 			                     /DTO:datetimeformat Date and Time Output string format
  728. 			                     /DE:yyyy-MM-dd      Earliest date allowed
  729. 			                     /DL:yyyy-MM-dd      Latest date allowed
  730. 			                     /DMAX:numberofdays  MAXimum Date allowed, relative to
  731. 			                                         today, in days (negative number for
  732. 			                                         a date in the past)
  733. 			                     /DMIN:numberofdays  MINimum Date allowed, relative to
  734. 			                                         today, in days (negative number for
  735. 			                                         a date in the past)
  736. 			                     /H:height           window Height (default: 135,
  737. 			                                         minimum: 135, maximum: screen height)
  738. 			                     /I:index            use Icon at index from shell32.dll
  739. 			                     /L[:captions]       Localize or customize button captions
  740. 			                                         (e.g. /L:"OK=Why Not?;Cancel=Never!")
  741. 			                     /W:width            window Width (default: 220,
  742. 			                                         minimum: 220, maximum: screen width)
  743.  
  744. 			Example:  Display date/time in default format, output in yyyyMMddHHmmssfff
  745. 			          format (year, month, day, hours, minutes, seconds, milliseconds),
  746. 			          selected date between today and 90 days in the future:
  747. 			          DATETIMEBOX "When?" /DTO:yyyyMMddHHmmssfff /DMIN:0 /DMAX:90
  748.  
  749. 			Notes:    Available custom date and time formats can be found on MSDN at:
  750. 			          http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx
  751. 			          Note that by default AM/PM time formats ("tt" or "t") cannot be
  752. 			          used on computers with a 24-hour time format. To prevent error
  753. 			          messages, use /I24 to ignore "tt" or "t" (AM/PM) in specified input
  754. 			          and/or output format, and /O24 to append AM/PM to the string on
  755. 			          systems with 24-hour time format.
  756. 			          If specified, the initial date/time must be in "yyyy-MM-dd HH:mm"
  757. 			          or "yyyy-MM-dd HH:mm:ss" format; but with /D "yyyy-MM-dd" format is
  758. 			          accepted, and with /T "HH:mm" and "HH:mm:ss" formats are accepted.
  759. 			          If specified without captions, switch /L forces localized button
  760. 			          captions (e.g. "Cancel" button caption is "Annuleren" on Dutch
  761. 			          systems); if only a single custom caption is specified, the other
  762. 			          one is localized (e.g. with /L:"OK=Gaan" on Dutch systems, "OK"
  763. 			          button caption is "Gaan", "Cancel" button caption is "Annuleren").
  764. 			          The selected date and/or time are written to Standard Out if "OK"
  765. 			          is clicked, otherwise an empty string is returned.
  766. 			          Switches /D, /T and /DTO are mutually exclusive, as are /DMAX and
  767. 			          /DL, and /DMIN and /DE.
  768. 			          Return code 0 for "OK", 1 for (command line) errors, 2 for "Cancel".
  769.  
  770. 			Credits:  On-the-fly form based on code by Gorkem Gencay on StackOverflow:
  771. 			          http://stackoverflow.com/questions/97097#17546909
  772. 			          Code to retrieve localized button captions by Martin Stoeckli:
  773. 			          http://martinstoeckli.ch/csharp/csharp.html#windows_text_resources
  774. 			          Code to extract icons from Shell32.dll by Thomas Levesque:
  775. 		              http://stackoverflow.com/questions/6873026
  776.  
  777. 			Written by Rob van der Woude
  778. 			http://www.robvanderwoude.com
  779. 			*/
  780.  
  781. 			#endregion Help Text
  782.  
  783.  
  784. 			#region Error Message
  785.  
  786. 			if ( errmsg.Length > 0 )
  787. 			{
  788. 				List<string> errargs = new List<string>( errmsg );
  789. 				errargs.RemoveAt( 0 );
  790. 				Console.Error.WriteLine( );
  791. 				Console.ForegroundColor = ConsoleColor.Red;
  792. 				Console.Error.Write( "ERROR:\t" );
  793. 				Console.ForegroundColor = ConsoleColor.White;
  794. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  795. 				Console.ResetColor( );
  796.  
  797. 			}
  798.  
  799. 			#endregion Error Message
  800.  
  801.  
  802. 			#region Show Help
  803.  
  804. 			Console.Error.WriteLine( );
  805.  
  806. 			Console.Error.WriteLine( "DateTimeBox,  Version {0}", progver );
  807.  
  808. 			Console.Error.WriteLine( "Batch tool to present a Date/Time Picker dialog and return the selected" );
  809.  
  810. 			Console.Error.WriteLine( "date and/or time in the specified format" );
  811.  
  812. 			Console.Error.WriteLine( );
  813.  
  814. 			Console.Error.Write( "Usage:    " );
  815. 			Console.ForegroundColor = ConsoleColor.White;
  816. 			Console.Error.WriteLine( "DATETIMEBOX  [ \"title\" ]  [ \"datetime\" ]  [ options ]" );
  817. 			Console.ResetColor( );
  818.  
  819. 			Console.Error.WriteLine( );
  820.  
  821. 			Console.Error.Write( "Where:    " );
  822. 			Console.ForegroundColor = ConsoleColor.White;
  823. 			Console.Error.Write( "\"title\"" );
  824. 			Console.ResetColor( );
  825. 			Console.Error.WriteLine( "    is the optional caption in the title bar" );
  826.  
  827. 			Console.Error.WriteLine( "                     (default: DateTimeBox,  Version {0})", progver );
  828.  
  829. 			Console.ForegroundColor = ConsoleColor.White;
  830. 			Console.Error.Write( "          \"datetime\"" );
  831. 			Console.ResetColor( );
  832. 			Console.Error.WriteLine( " is the optional initial date/time for the dialog" );
  833.  
  834. 			Console.Error.WriteLine( "                     in \"yyyy-MM-dd HH:mm\" format      (default: now)" );
  835.  
  836. 			Console.ForegroundColor = ConsoleColor.White;
  837. 			Console.Error.Write( "          options    /D" );
  838. 			Console.ResetColor( );
  839. 			Console.Error.Write( "   display and return " );
  840. 			Console.ForegroundColor = ConsoleColor.White;
  841. 			Console.Error.Write( "D" );
  842. 			Console.ResetColor( );
  843. 			Console.Error.WriteLine( "ate only (default: date and time)" );
  844.  
  845. 			Console.ForegroundColor = ConsoleColor.White;
  846. 			Console.Error.Write( "                     /T" );
  847. 			Console.ResetColor( );
  848. 			Console.Error.Write( "   display and return " );
  849. 			Console.ForegroundColor = ConsoleColor.White;
  850. 			Console.Error.Write( "T" );
  851. 			Console.ResetColor( );
  852. 			Console.Error.WriteLine( "ime only (default: date and time)" );
  853.  
  854. 			Console.ForegroundColor = ConsoleColor.White;
  855. 			Console.Error.Write( "                     /I24 I" );
  856. 			Console.ResetColor( );
  857. 			Console.Error.Write( "gnore AM/PM in " );
  858. 			Console.ForegroundColor = ConsoleColor.White;
  859. 			Console.Error.Write( "I" );
  860. 			Console.ResetColor( );
  861. 			Console.Error.Write( "nput on systems with " );
  862. 			Console.ForegroundColor = ConsoleColor.White;
  863. 			Console.Error.Write( "24" );
  864. 			Console.ResetColor( );
  865. 			Console.Error.WriteLine( "-hour format" );
  866.  
  867. 			Console.ForegroundColor = ConsoleColor.White;
  868. 			Console.Error.Write( "                     /O24" );
  869. 			Console.ResetColor( );
  870. 			Console.Error.Write( " append AM/PM to " );
  871. 			Console.ForegroundColor = ConsoleColor.White;
  872. 			Console.Error.Write( "O" );
  873. 			Console.ResetColor( );
  874. 			Console.Error.Write( "utput on systems with " );
  875. 			Console.ForegroundColor = ConsoleColor.White;
  876. 			Console.Error.Write( "24" );
  877. 			Console.ResetColor( );
  878. 			Console.Error.WriteLine( "-hour format" );
  879.  
  880. 			Console.ForegroundColor = ConsoleColor.White;
  881. 			Console.Error.Write( "                     /FT:\"file\"" );
  882. 			Console.ResetColor( );
  883. 			Console.Error.Write( "          use " );
  884. 			Console.ForegroundColor = ConsoleColor.White;
  885. 			Console.Error.Write( "F" );
  886. 			Console.ResetColor( );
  887. 			Console.Error.Write( "ile " );
  888. 			Console.ForegroundColor = ConsoleColor.White;
  889. 			Console.Error.Write( "T" );
  890. 			Console.ResetColor( );
  891. 			Console.Error.Write( "imestamp of specified " );
  892. 			Console.ForegroundColor = ConsoleColor.White;
  893. 			Console.Error.WriteLine( "file" );
  894. 			Console.ResetColor( );
  895.  
  896. 			Console.Error.WriteLine( "                                         for the dialog's initial date/time" );
  897.  
  898. 			Console.ForegroundColor = ConsoleColor.White;
  899. 			Console.Error.Write( "                     /DD:dateformat      D" );
  900. 			Console.ResetColor( );
  901. 			Console.Error.Write( "ate " );
  902. 			Console.ForegroundColor = ConsoleColor.White;
  903. 			Console.Error.Write( "D" );
  904. 			Console.ResetColor( );
  905. 			Console.Error.WriteLine( "isplay format (GUI)" );
  906.  
  907. 			Console.ForegroundColor = ConsoleColor.White;
  908. 			Console.Error.Write( "                     /DO:dateformat      D" );
  909. 			Console.ResetColor( );
  910. 			Console.Error.Write( "ate " );
  911. 			Console.ForegroundColor = ConsoleColor.White;
  912. 			Console.Error.Write( "O" );
  913. 			Console.ResetColor( );
  914. 			Console.Error.WriteLine( "utput string format" );
  915.  
  916. 			Console.ForegroundColor = ConsoleColor.White;
  917. 			Console.Error.Write( "                     /TD:timeformat      T" );
  918. 			Console.ResetColor( );
  919. 			Console.Error.Write( "ime " );
  920. 			Console.ForegroundColor = ConsoleColor.White;
  921. 			Console.Error.Write( "D" );
  922. 			Console.ResetColor( );
  923. 			Console.Error.WriteLine( "isplay format (GUI)" );
  924.  
  925. 			Console.ForegroundColor = ConsoleColor.White;
  926. 			Console.Error.Write( "                     /TO:timeformat      T" );
  927. 			Console.ResetColor( );
  928. 			Console.Error.Write( "ime " );
  929. 			Console.ForegroundColor = ConsoleColor.White;
  930. 			Console.Error.Write( "O" );
  931. 			Console.ResetColor( );
  932. 			Console.Error.WriteLine( "utput string format" );
  933.  
  934. 			Console.ForegroundColor = ConsoleColor.White;
  935. 			Console.Error.Write( "                     /DTO:datetimeformat D" );
  936. 			Console.ResetColor( );
  937. 			Console.Error.Write( "ate and " );
  938. 			Console.ForegroundColor = ConsoleColor.White;
  939. 			Console.Error.Write( "T" );
  940. 			Console.ResetColor( );
  941. 			Console.Error.Write( "ime " );
  942. 			Console.ForegroundColor = ConsoleColor.White;
  943. 			Console.Error.Write( "O" );
  944. 			Console.ResetColor( );
  945. 			Console.Error.WriteLine( "utput string format" );
  946.  
  947. 			Console.ForegroundColor = ConsoleColor.White;
  948. 			Console.Error.Write( "                     /DE:yyyy-MM-dd      E" );
  949. 			Console.ResetColor( );
  950. 			Console.Error.Write( "arliest " );
  951. 			Console.ForegroundColor = ConsoleColor.White;
  952. 			Console.Error.Write( "D" );
  953. 			Console.ResetColor( );
  954. 			Console.Error.WriteLine( "ate allowed" );
  955.  
  956. 			Console.ForegroundColor = ConsoleColor.White;
  957. 			Console.Error.Write( "                     /DL:yyyy-MM-dd      L" );
  958. 			Console.ResetColor( );
  959. 			Console.Error.Write( "atest " );
  960. 			Console.ForegroundColor = ConsoleColor.White;
  961. 			Console.Error.Write( "D" );
  962. 			Console.ResetColor( );
  963. 			Console.Error.WriteLine( "ate allowed" );
  964.  
  965. 			Console.ForegroundColor = ConsoleColor.White;
  966. 			Console.Error.Write( "                     /DMAX:numberofdays  MAX" );
  967. 			Console.ResetColor( );
  968. 			Console.Error.Write( "imum " );
  969. 			Console.ForegroundColor = ConsoleColor.White;
  970. 			Console.Error.Write( "D" );
  971. 			Console.ResetColor( );
  972. 			Console.Error.WriteLine( "ate allowed, relative to" );
  973.  
  974. 			Console.Error.Write( "                                         today, in " );
  975. 			Console.ForegroundColor = ConsoleColor.White;
  976. 			Console.Error.Write( "days" );
  977. 			Console.ResetColor( );
  978. 			Console.Error.WriteLine( " (negative number for" );
  979.  
  980. 			Console.Error.WriteLine( "                                         a date in the past)" );
  981.  
  982. 			Console.ForegroundColor = ConsoleColor.White;
  983. 			Console.Error.Write( "                     /DMIN:numberofdays  MIN" );
  984. 			Console.ResetColor( );
  985. 			Console.Error.Write( "imum " );
  986. 			Console.ForegroundColor = ConsoleColor.White;
  987. 			Console.Error.Write( "D" );
  988. 			Console.ResetColor( );
  989. 			Console.Error.WriteLine( "ate allowed, relative to" );
  990.  
  991. 			Console.Error.Write( "                                         today, in " );
  992. 			Console.ForegroundColor = ConsoleColor.White;
  993. 			Console.Error.Write( "days" );
  994. 			Console.ResetColor( );
  995. 			Console.Error.WriteLine( " (negative number for" );
  996.  
  997. 			Console.Error.WriteLine( "                                         a date in the past)" );
  998.  
  999. 			Console.ForegroundColor = ConsoleColor.White;
  1000. 			Console.Error.Write( "                     /H:height" );
  1001. 			Console.ResetColor( );
  1002. 			Console.Error.Write( "           window " );
  1003. 			Console.ForegroundColor = ConsoleColor.White;
  1004. 			Console.Error.Write( "H" );
  1005. 			Console.ResetColor( );
  1006. 			Console.Error.WriteLine( "eight (default: 135," );
  1007.  
  1008. 			Console.Error.WriteLine( "                                         minimum: 135, maximum: screen height)" );
  1009.  
  1010. 			Console.ForegroundColor = ConsoleColor.White;
  1011. 			Console.Error.Write( "                     /I:index" );
  1012. 			Console.ResetColor( );
  1013. 			Console.Error.Write( "            use " );
  1014. 			Console.ForegroundColor = ConsoleColor.White;
  1015. 			Console.Error.Write( "I" );
  1016. 			Console.ResetColor( );
  1017. 			Console.Error.Write( "con at " );
  1018. 			Console.ForegroundColor = ConsoleColor.White;
  1019. 			Console.Error.Write( "index" );
  1020. 			Console.ResetColor( );
  1021. 			Console.Error.WriteLine( " from shell32.dll" );
  1022.  
  1023. 			Console.ForegroundColor = ConsoleColor.White;
  1024. 			Console.Error.Write( "                     /L[:captions]       L" );
  1025. 			Console.ResetColor( );
  1026. 			Console.Error.Write( "ocalize or customize button " );
  1027. 			Console.ForegroundColor = ConsoleColor.White;
  1028. 			Console.Error.WriteLine( "captions" );
  1029. 			Console.ResetColor( );
  1030.  
  1031. 			Console.Error.Write( "                                         (e.g. " );
  1032. 			Console.ForegroundColor = ConsoleColor.White;
  1033. 			Console.Error.Write( "/L:\"OK=Why Not?;Cancel=Never!\"" );
  1034. 			Console.ResetColor( );
  1035. 			Console.Error.WriteLine( ")" );
  1036.  
  1037. 			Console.ForegroundColor = ConsoleColor.White;
  1038. 			Console.Error.Write( "                     /W:width" );
  1039. 			Console.ResetColor( );
  1040. 			Console.Error.Write( "            window " );
  1041. 			Console.ForegroundColor = ConsoleColor.White;
  1042. 			Console.Error.Write( "W" );
  1043. 			Console.ResetColor( );
  1044. 			Console.Error.WriteLine( "idth (default: 220," );
  1045.  
  1046. 			Console.Error.WriteLine( "                                         minimum: 220, maximum: screen width)" );
  1047.  
  1048. 			Console.Error.WriteLine( );
  1049.  
  1050. 			Console.Error.WriteLine( "Example:  Display date/time in default format, output in yyyyMMddHHmmssfff" );
  1051.  
  1052. 			Console.Error.WriteLine( "          format (year, month, day, hours, minutes, seconds, milliseconds)," );
  1053.  
  1054. 			Console.Error.WriteLine( "          selected date between today and 90 days in the future:" );
  1055.  
  1056. 			Console.ForegroundColor = ConsoleColor.White;
  1057. 			Console.Error.WriteLine( "          DATETIMEBOX \"When?\" /DTO:yyyyMMddHHmmssfff /DMIN:0 /DMAX:90" );
  1058. 			Console.ResetColor( );
  1059.  
  1060. 			Console.Error.WriteLine( );
  1061.  
  1062. 			Console.Error.WriteLine( "Notes:    Available custom date and time formats can be found on MSDN at:" );
  1063.  
  1064. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  1065. 			Console.Error.WriteLine( "          http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx" );
  1066. 			Console.ResetColor( );
  1067.  
  1068. 			Console.Error.WriteLine( "          Note that by default AM/PM time formats (\"tt\" or \"t\") cannot be" );
  1069.  
  1070. 			Console.Error.WriteLine( "          used on computers with a 24-hour time format. To prevent error" );
  1071.  
  1072. 			Console.Error.Write( "          messages, use " );
  1073. 			Console.ForegroundColor = ConsoleColor.White;
  1074. 			Console.Error.Write( "/I24" );
  1075. 			Console.ResetColor( );
  1076. 			Console.Error.WriteLine( " to ignore \"tt\" or \"t\" (AM/PM) in specified input" );
  1077.  
  1078. 			Console.Error.Write( "          and/or output format, and " );
  1079. 			Console.ForegroundColor = ConsoleColor.White;
  1080. 			Console.Error.Write( "/O24" );
  1081. 			Console.ResetColor( );
  1082. 			Console.Error.WriteLine( " to append AM/PM to the string on" );
  1083.  
  1084. 			Console.Error.WriteLine( "          systems with 24-hour time format." );
  1085.  
  1086. 			Console.Error.WriteLine( "          If specified, the initial date/time must be in \"yyyy-MM-dd HH:mm\"" );
  1087.  
  1088. 			Console.Error.Write( "          or \"yyyy-MM-dd HH:mm:ss\" format; but with " );
  1089. 			Console.ForegroundColor = ConsoleColor.White;
  1090. 			Console.Error.Write( "/D" );
  1091. 			Console.ResetColor( );
  1092. 			Console.Error.WriteLine( " \"yyyy-MM-dd\" format is" );
  1093.  
  1094. 			Console.Error.Write( "          accepted, and with " );
  1095. 			Console.ForegroundColor = ConsoleColor.White;
  1096. 			Console.Error.Write( "/T" );
  1097. 			Console.ResetColor( );
  1098. 			Console.Error.WriteLine( " \"HH:mm\" and \"HH:mm:ss\" formats are accepted." );
  1099.  
  1100. 			Console.Error.Write( "          If specified without " );
  1101. 			Console.ForegroundColor = ConsoleColor.White;
  1102. 			Console.Error.Write( "captions" );
  1103. 			Console.ResetColor( );
  1104. 			Console.Error.Write( ", switch " );
  1105. 			Console.ForegroundColor = ConsoleColor.White;
  1106. 			Console.Error.Write( "/L" );
  1107. 			Console.ResetColor( );
  1108. 			Console.Error.WriteLine( " forces localized button" );
  1109.  
  1110. 			Console.Error.WriteLine( "          captions (e.g. \"Cancel\" button caption is \"Annuleren\" on Dutch" );
  1111.  
  1112. 			Console.Error.WriteLine( "          systems); if only a single custom caption is specified, the other" );
  1113.  
  1114. 			Console.Error.Write( "          one is localized (e.g. with " );
  1115. 			Console.ForegroundColor = ConsoleColor.White;
  1116. 			Console.Error.Write( "/L:\"OK=Gaan\"" );
  1117. 			Console.ResetColor( );
  1118. 			Console.Error.WriteLine( " on Dutch systems, \"OK\"" );
  1119.  
  1120. 			Console.Error.WriteLine( "          button caption is \"Gaan\", \"Cancel\" button caption is \"Annuleren\")." );
  1121.  
  1122. 			Console.Error.WriteLine( "          The selected date and/or time are written to Standard Out if \"OK\"" );
  1123.  
  1124. 			Console.Error.WriteLine( "          is clicked, otherwise an empty string is returned." );
  1125.  
  1126. 			Console.Error.Write( "          Switches " );
  1127. 			Console.ForegroundColor = ConsoleColor.White;
  1128. 			Console.Error.Write( "/D" );
  1129. 			Console.ResetColor( );
  1130. 			Console.Error.Write( ", " );
  1131. 			Console.ForegroundColor = ConsoleColor.White;
  1132. 			Console.Error.Write( "/T" );
  1133. 			Console.ResetColor( );
  1134. 			Console.Error.Write( " and " );
  1135. 			Console.ForegroundColor = ConsoleColor.White;
  1136. 			Console.Error.Write( "/DTO" );
  1137. 			Console.ResetColor( );
  1138. 			Console.Error.WriteLine( " are mutually exclusive." );
  1139.  
  1140. 			Console.Error.WriteLine( "          Return code 0 for \"OK\", 1 for (command line) errors, 2 for \"Cancel\"." );
  1141.  
  1142. 			Console.Error.WriteLine( );
  1143.  
  1144. 			Console.Error.WriteLine( "Credits:  On-the-fly form based on code by Gorkem Gencay on StackOverflow:" );
  1145.  
  1146. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  1147. 			Console.Error.WriteLine( "          http://stackoverflow.com/questions/17546909" );
  1148. 			Console.ResetColor( );
  1149.  
  1150. 			Console.Error.WriteLine( "          Code to retrieve localized button captions by Martin Stoeckli:" );
  1151.  
  1152. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  1153. 			Console.Error.WriteLine( "          http://martinstoeckli.ch/csharp/csharp.html#windows_text_resources" );
  1154. 			Console.ResetColor( );
  1155.  
  1156. 			Console.Error.WriteLine( "          Code to extract icons from Shell32.dll by Thomas Levesque:" );
  1157.  
  1158. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  1159. 			Console.Error.WriteLine( "          http://stackoverflow.com/questions/6873026" );
  1160. 			Console.ResetColor( );
  1161.  
  1162. 			Console.Error.WriteLine( );
  1163.  
  1164. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  1165.  
  1166. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  1167.  
  1168. 			#endregion Show Help
  1169.  
  1170.  
  1171. 			return 1;
  1172. 		}
  1173.  
  1174. 		#endregion Error handling
  1175.  
  1176.  
  1177. 		#region Get Localized Captions
  1178.  
  1179. 		// Code to retrieve localized captions by Martin Stoeckli
  1180. 		// http://martinstoeckli.ch/csharp/csharp.html#windows_text_resources
  1181.  
  1182. 		/// <summary>
  1183. 		/// Searches for a text resource in a Windows library.
  1184. 		/// Sometimes, using the existing Windows resources, you can make your code
  1185. 		/// language independent and you don't have to care about translation problems.
  1186. 		/// </summary>
  1187. 		/// <example>
  1188. 		///   btnCancel.Text = Load("user32.dll", 801, "Cancel");
  1189. 		///   btnYes.Text = Load("user32.dll", 805, "Yes");
  1190. 		/// </example>
  1191. 		/// <param name="libraryName">Name of the windows library like "user32.dll"
  1192. 		/// or "shell32.dll"</param>
  1193. 		/// <param name="ident">Id of the string resource.</param>
  1194. 		/// <param name="defaultText">Return this text, if the resource string could
  1195. 		/// not be found.</param>
  1196. 		/// <returns>Requested string if the resource was found,
  1197. 		/// otherwise the <paramref name="defaultText"/></returns>
  1198. 		public static string Load( string libraryName, UInt32 ident, string defaultText )
  1199. 		{
  1200. 			IntPtr libraryHandle = GetModuleHandle( libraryName );
  1201. 			if ( libraryHandle != IntPtr.Zero )
  1202. 			{
  1203. 				StringBuilder sb = new StringBuilder( 1024 );
  1204. 				int size = LoadString( libraryHandle, ident, sb, 1024 );
  1205. 				if ( size > 0 )
  1206. 					return sb.ToString( );
  1207. 			}
  1208. 			return defaultText;
  1209. 		}
  1210.  
  1211. 		[DllImport( "kernel32.dll", CharSet = CharSet.Auto )]
  1212. 		private static extern IntPtr GetModuleHandle( string lpModuleName );
  1213.  
  1214. 		[DllImport( "user32.dll", CharSet = CharSet.Auto )]
  1215. 		private static extern int LoadString( IntPtr hInstance, UInt32 uID, StringBuilder lpBuffer, Int32 nBufferMax );
  1216.  
  1217. 		#endregion Get Localized Captions
  1218.  
  1219.  
  1220. 		#region Extract Icons
  1221.  
  1222. 		// Code to extract icons from Shell32.dll by Thomas Levesque
  1223. 		// http://stackoverflow.com/questions/6873026
  1224.  
  1225. 		public class IconExtractor
  1226. 		{
  1227.  
  1228. 			public static Icon Extract( string file, int number, bool largeIcon )
  1229. 			{
  1230. 				IntPtr large;
  1231. 				IntPtr small;
  1232. 				ExtractIconEx( file, number, out large, out small, 1 );
  1233. 				try
  1234. 				{
  1235. 					return Icon.FromHandle( largeIcon ? large : small );
  1236. 				}
  1237. 				catch
  1238. 				{
  1239. 					return null;
  1240. 				}
  1241.  
  1242. 			}
  1243.  
  1244. 			[DllImport( "Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall )]
  1245. 			private static extern int ExtractIconEx( string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons );
  1246. 		}
  1247.  
  1248. 		#endregion Extract Icons
  1249. 	}
  1250. }
  1251.  

page last modified: 2024-04-16; loaded in 0.0643 seconds