Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for multiplechoicebox.cs

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.IO;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7. using System.Text.RegularExpressions;
  8. using System.Windows.Forms;
  9.  
  10.  
  11. namespace RobvanderWoude
  12. {
  13. 	class MultipleChoiceBox
  14. 	{
  15. 		public static string progver = "1.00";
  16.  
  17.  
  18. 		#region Global Variables
  19.  
  20. 		public const int defaultwindowheight = 320;
  21. 		public const int defaultwindowwidth = 480;
  22. 		public const int minimumwindowheight = 90;
  23. 		public const int minimumwindowwidth = 200;
  24. 		public static int screenheight = Screen.PrimaryScreen.WorkingArea.Height;
  25. 		public static int screenwidth = Screen.PrimaryScreen.WorkingArea.Width;
  26. 		public static int maximumwindowheight = screenheight;
  27. 		public static int maximumwindowwidth = screenwidth;
  28. 		public static int borderX = 0;
  29. 		public static int borderY = 0;
  30.  
  31. 		#endregion Global Variables
  32.  
  33.  
  34. 		[STAThread]
  35. 		static int Main( string[] args )
  36. 		{
  37. 			#region Initialize Variables
  38.  
  39. 			char delimiter = ';';
  40. 			List<string> namedargs = new List<string>( );
  41. 			List<string> unnamedargs = new List<string>( );
  42. 			string file = String.Empty;
  43. 			string list = String.Empty;
  44. 			string cancelcaption = "&Cancel";
  45. 			string okcaption = "&OK";
  46. 			string localizationstring = String.Empty;
  47. 			string prompt = String.Empty;
  48. 			string selectedtext = String.Empty;
  49. 			string title = String.Format( "MultioleChoiceBox,  Version {0}", progver );
  50. 			bool deduplist = false;
  51. 			bool delimiterset = false;
  52. 			bool heightset = false;
  53. 			bool iconset = false;
  54. 			bool indexset = false;
  55. 			bool localizedcaptionset = false;
  56. 			bool monospaced = false;
  57. 			bool skipfirstitem = false;
  58. 			bool sortlist = false;
  59. 			bool tablengthset = false;
  60. 			bool topmost = true;
  61. 			bool widthset = false;
  62. 			double cbsafetyfactor = 1.05;
  63. 			int columns = 0;
  64. 			int defaultitems = 0;
  65. 			int icon = 23;
  66. 			int promptheight = 20;
  67. 			int rc = 0;
  68. 			int rows = 0;
  69. 			int tablength = 4;
  70. 			int windowheight = defaultwindowheight;
  71. 			int windowwidth = defaultwindowwidth;
  72. 			Label labelPrompt = new Label( );
  73.  
  74. 			bool isredirected = Console.IsInputRedirected; // Requires .NET Framework 4.5
  75. 			bool listset = isredirected;
  76. 			int redirectnum = ( isredirected ? 1 : 0 );
  77. 			int arguments = args.Length + redirectnum;
  78.  
  79. 			int[] borders = BorderDimensions( );
  80. 			borderX = borders[0];
  81. 			borderY = borders[1];
  82. 			maximumwindowheight = screenheight - borderY;
  83. 			maximumwindowwidth = screenwidth - borderX;
  84.  
  85. 			#endregion Initialize Variables
  86.  
  87.  
  88. 			#region Command Line Parsing
  89.  
  90. 			if ( arguments == 0 )
  91. 			{
  92. 				return ShowHelp( );
  93. 			}
  94.  
  95. 			if ( arguments > 16 )
  96. 			{
  97. 				return ShowHelp( "Too many command line arguments" );
  98. 			}
  99.  
  100. 			// Split up named and unnamed arguments
  101. 			foreach ( string arg in args )
  102. 			{
  103. 				if ( arg[0] == '/' )
  104. 				{
  105. 					namedargs.Add( arg );
  106. 				}
  107. 				else
  108. 				{
  109. 					unnamedargs.Add( arg );
  110. 				}
  111. 			}
  112.  
  113. 			// Read Standard Input if the list is redirected
  114. 			if ( isredirected )
  115. 			{
  116. 				try
  117. 				{
  118. 					string delim = delimiter.ToString( );
  119. 					list = String.Join( delim, Console.In.ReadToEnd( ).Split( "\n\r".ToCharArray( ), StringSplitOptions.RemoveEmptyEntries ) );
  120. 					// Trim list items, remove empty ones
  121. 					string pattern = "\\s*" + delim + "+\\s*";
  122. 					list = Regex.Replace( list, pattern, delim );
  123. 				}
  124. 				catch ( Exception e )
  125. 				{
  126. 					return ShowHelp( e.Message );
  127. 				}
  128. 			}
  129.  
  130. 			// First, validate the named arguments
  131. 			#region Named Arguments
  132.  
  133. 			foreach ( string arg in namedargs )
  134. 			{
  135. 				if ( arg.Length > 1 && !arg.Contains( ":" ) && !arg.Contains( "=" ) )
  136. 				{
  137. 					#region Boolean Named Arguments
  138.  
  139. 					string key = arg.ToUpper( );
  140. 					switch ( key )
  141. 					{
  142. 						case "/?":
  143. 						case "/HELP":
  144. 							return ShowHelp( );
  145. 						case "/??":
  146. 						case "/???":
  147. 						case "/A":
  148. 						case "/ALIAS":
  149. 						case "/ALIASES":
  150. 							return ShowAliases( );
  151. 						case "/DE":
  152. 						case "/DEDUP":
  153. 							if ( deduplist )
  154. 							{
  155. 								return ShowHelp( "Duplicate command line switch /DE" );
  156. 							}
  157. 							deduplist = true;
  158. 							break;
  159. 						case "/K":
  160. 						case "/SKIP":
  161. 						case "/SKIPFIRST":
  162. 						case "/SKIPFIRSTITEM":
  163. 							if ( skipfirstitem )
  164. 							{
  165. 								return ShowHelp( "Duplicate command line switch /K" );
  166. 							}
  167. 							skipfirstitem = true;
  168. 							break;
  169. 						case "/L":
  170. 						case "/LOCALIZED":
  171. 						case "/LOCALIZEDCAPTIONS":
  172. 							if ( localizedcaptionset )
  173. 							{
  174. 								return ShowHelp( "Duplicate command line switch /L" );
  175. 							}
  176. 							localizedcaptionset = true;
  177. 							break;
  178. 						case "/MF":
  179. 						case "/MONO":
  180. 						case "/MONOSPACED":
  181. 						case "/MONOSPACEDFONT":
  182. 							if ( monospaced )
  183. 							{
  184. 								return ShowHelp( "Duplicate command line switch /MF" );
  185. 							}
  186. 							monospaced = true;
  187. 							break;
  188. 						case "/NM":
  189. 						case "/NONMODAL":
  190. 						case "/NON-MODAL":
  191. 							if ( !topmost )
  192. 							{
  193. 								return ShowHelp( "Duplicate command line switch /NM" );
  194. 							}
  195. 							topmost = false;
  196. 							break;
  197. 						case "/S":
  198. 						case "/SORT":
  199. 						case "/SORTLIST":
  200. 							if ( sortlist )
  201. 							{
  202. 								return ShowHelp( "Duplicate command line switch /S" );
  203. 							}
  204. 							sortlist = true;
  205. 							break;
  206. 						default:
  207. 							return ShowHelp( "Invalid command line switch {0} or missing value", arg );
  208. 					}
  209.  
  210. 					#endregion Boolean Named Arguments
  211. 				}
  212. 				else if ( arg.Length > 3 && ( arg.Contains( ":" ) || arg.Contains( "=" ) ) )
  213. 				{
  214. 					#region Key/Value Named Arguments
  215.  
  216. 					string key = arg.ToUpper( ).Substring( 0, arg.IndexOfAny( ":=".ToCharArray( ) ) );
  217. 					string val = arg.Substring( arg.IndexOfAny( ":=".ToCharArray( ) ) + 1 );
  218. 					switch ( key )
  219. 					{
  220. 						case "/C":
  221. 						case "/COL":
  222. 						case "/COLS":
  223. 						case "/COLUMNS":
  224. 							if ( columns != 0 )
  225. 							{
  226. 								return ShowHelp( "Duplicate command line switch /C" );
  227. 							}
  228. 							try
  229. 							{
  230. 								columns = Convert.ToInt32( val );
  231. 								if ( columns < 0 )
  232. 								{
  233. 									return ShowHelp( "Columns must be a positive integer" );
  234. 								}
  235. 							}
  236. 							catch ( Exception )
  237. 							{
  238. 								return ShowHelp( "Invalid columns value \"{0}\"", arg );
  239. 							}
  240. 							break;
  241. 						case "/D":
  242. 						case "/DELIMITER":
  243. 							if ( delimiterset )
  244. 							{
  245. 								return ShowHelp( "Duplicate command line switch /D" );
  246. 							}
  247. 							if ( val.Length == 1 )
  248. 							{
  249. 								delimiter = val[0];
  250. 							}
  251. 							else if ( val.Length == 3 && ( ( val[0] == '"' && val[2] == '"' ) || ( val[0] == '\'' && val[2] == '\'' ) ) )
  252. 							{
  253. 								delimiter = val[1];
  254. 							}
  255. 							else
  256. 							{
  257. 								return ShowHelp( String.Format( "Invalid delimiter specified \"{0}\"", arg ) );
  258. 							}
  259. 							break;
  260. 						case "/F":
  261. 						case "/FILE":
  262. 							if ( listset )
  263. 							{
  264. 								return ShowHelp( "Duplicate command line switch /F" );
  265. 							}
  266. 							file = val;
  267. 							if ( String.IsNullOrEmpty( file ) || !File.Exists( file ) )
  268. 							{
  269. 								return ShowHelp( "List file not found: \"{0}\"", file );
  270. 							}
  271. 							else
  272. 							{
  273. 								try
  274. 								{
  275. 									string delim = delimiter.ToString( );
  276. 									list = String.Join( delim, File.ReadLines( file ) );
  277. 									string pattern = delim + "{2,}";
  278. 									// Remove empty list items
  279. 									Regex.Replace( list, pattern, delim );
  280. 								}
  281. 								catch ( Exception e )
  282. 								{
  283. 									return ShowHelp( e.Message );
  284. 								}
  285. 							}
  286. 							listset = true;
  287. 							break;
  288. 						case "/H":
  289. 						case "/HEIGHT":
  290. 							if ( heightset )
  291. 							{
  292. 								return ShowHelp( "Duplicate command line switch /H" );
  293. 							}
  294. 							try
  295. 							{
  296. 								windowheight = Convert.ToInt32( val );
  297. 								if ( windowheight < minimumwindowheight || windowheight > maximumwindowheight )
  298. 								{
  299. 									return ShowHelp( String.Format( "Height {0} outside allowed range of {1}..{2}", val, minimumwindowheight, maximumwindowheight ) );
  300. 								}
  301. 							}
  302. 							catch ( Exception e )
  303. 							{
  304. 								return ShowHelp( String.Format( "Invalid height \"{0}\": {1}", val, e.Message ) );
  305. 							}
  306. 							heightset = true;
  307. 							break;
  308. 						case "/I":
  309. 						case "/ICON":
  310. 							if ( iconset )
  311. 							{
  312. 								return ShowHelp( "Duplicate command line switch /I" );
  313. 							}
  314. 							try
  315. 							{
  316. 								icon = Convert.ToInt32( val );
  317. 							}
  318. 							catch ( Exception )
  319. 							{
  320. 								return ShowHelp( "Invalid icon index: {0}", val );
  321. 							}
  322. 							iconset = true;
  323. 							break;
  324. 						case "/L":
  325. 						case "/LOCALIZED":
  326. 						case "/LOCALIZEDCAPTIONS":
  327. 							if ( localizedcaptionset )
  328. 							{
  329. 								return ShowHelp( "Duplicate command line switch /L" );
  330. 							}
  331. 							localizedcaptionset = true;
  332. 							localizationstring = val;
  333. 							string localizationpattern = "(;|^)(OK|Cancel)=[^\\\"';]+(;|$)";
  334. 							foreach ( string substring in localizationstring.Split( ";".ToCharArray( ), StringSplitOptions.RemoveEmptyEntries ) )
  335. 							{
  336. 								if ( !Regex.IsMatch( substring, localizationpattern, RegexOptions.IgnoreCase ) )
  337. 								{
  338. 									return ShowHelp( "Invalid value for /L switch: \"{1}\"", localizationstring );
  339. 								}
  340. 							}
  341. 							break;
  342. 						case "/P":
  343. 						case "/DEFAULT":
  344. 						case "/DEFAULTITEMS":
  345. 						case "/PRE":
  346. 						case "/PRESELECTED":
  347. 						case "/PRESELECTEDITEMS":
  348. 							if ( indexset )
  349. 							{
  350. 								return ShowHelp( "Duplicate command line switch /P" );
  351. 							}
  352. 							try
  353. 							{
  354. 								defaultitems = Convert.ToInt32( val );
  355. 							}
  356. 							catch ( Exception e )
  357. 							{
  358. 								return ShowHelp( String.Format( "Invalid preselected items value \"{0}\": {1}", arg, e.Message ) );
  359. 							}
  360. 							break;
  361. 						case "/R":
  362. 						case "/ROWS":
  363. 							if ( rows != 0 )
  364. 							{
  365. 								return ShowHelp( "Duplicate command line switch /R" );
  366. 							}
  367. 							try
  368. 							{
  369. 								rows = Convert.ToInt32( val );
  370. 								if ( rows < 0 )
  371. 								{
  372. 									return ShowHelp( "Rows must be a positive integer" );
  373. 								}
  374. 							}
  375. 							catch ( Exception )
  376. 							{
  377. 								return ShowHelp( "Invalid rows value \"{0}\"", arg );
  378. 							}
  379. 							break;
  380. 						case "/T:":
  381. 						case "/TAB":
  382. 						case "/TABLENGTH":
  383. 							if ( tablengthset )
  384. 							{
  385. 								return ShowHelp( "Duplicate command line switch /T" );
  386. 							}
  387. 							try
  388. 							{
  389. 								tablength = Convert.ToInt32( val );
  390. 								if ( tablength < 4 || tablength > 16 )
  391. 								{
  392. 									return ShowHelp( String.Format( "Tab length {0} outside allowed range of {1}..{2}", val, 4, 16 ) );
  393. 								}
  394. 							}
  395. 							catch ( Exception e )
  396. 							{
  397. 								return ShowHelp( String.Format( "Invalid tab length \"{0}\": {1}", val, e.Message ) );
  398. 							}
  399. 							tablengthset = true;
  400. 							break;
  401. 						case "/W":
  402. 						case "/WIDTH":
  403. 							if ( widthset )
  404. 							{
  405. 								return ShowHelp( "Duplicate command line switch /W" );
  406. 							}
  407. 							try
  408. 							{
  409. 								windowwidth = Convert.ToInt32( val );
  410. 								if ( windowwidth < minimumwindowwidth || windowwidth > maximumwindowwidth )
  411. 								{
  412. 									return ShowHelp( String.Format( "Width {0} outside allowed range of {1}..{2}", val, minimumwindowwidth, maximumwindowwidth ) );
  413. 								}
  414. 							}
  415. 							catch ( Exception e )
  416. 							{
  417. 								return ShowHelp( String.Format( "Invalid width \"{0}\": {1}", val, e.Message ) );
  418. 							}
  419. 							widthset = true;
  420. 							break;
  421. 						default:
  422. 							return ShowHelp( String.Format( "Invalid command line switch \"{0}\"", arg ) );
  423. 					}
  424.  
  425. 					#endregion Key/Value Named Arguments
  426.  
  427. 				}
  428. 			}
  429.  
  430. 			#endregion Named Arguments
  431.  
  432.  
  433. 			// Next, validate unnamed arguments
  434. 			#region Unnamed Arguments
  435.  
  436. 			if ( listset ) // This check is the reason why named arguments had to be validated before unnamed ones: /F switch changes the meaning of unnamed arguments
  437. 			{
  438. 				switch ( unnamedargs.Count )
  439. 				{
  440. 					case 0:
  441. 						break;
  442. 					case 1:
  443. 						prompt = unnamedargs[0];
  444. 						break;
  445. 					case 2:
  446. 						prompt = unnamedargs[0];
  447. 						title = unnamedargs[1];
  448. 						break;
  449. 					case 3:
  450. 						return ShowHelp( "Invalid command line argument: {0}", unnamedargs[2] );
  451. 					default:
  452. 						unnamedargs.RemoveRange( 0, 2 );
  453. 						return ShowHelp( "Invalid command line arguments: {0}", String.Join( ", ", unnamedargs ) );
  454. 				}
  455. 			}
  456. 			else
  457. 			{
  458. 				switch ( unnamedargs.Count )
  459. 				{
  460. 					case 0:
  461. 						break;
  462. 					case 1:
  463. 						list = unnamedargs[0];
  464. 						listset = true;
  465. 						break;
  466. 					case 2:
  467. 						list = unnamedargs[0];
  468. 						prompt = unnamedargs[1];
  469. 						listset = true;
  470. 						break;
  471. 					case 3:
  472. 						list = unnamedargs[0];
  473. 						prompt = unnamedargs[1];
  474. 						title = unnamedargs[2];
  475. 						listset = true;
  476. 						break;
  477. 					case 4:
  478. 						return ShowHelp( "Invalid command line argument: {0}", unnamedargs[3] );
  479. 					default:
  480. 						unnamedargs.RemoveRange( 0, 3 );
  481. 						return ShowHelp( "Invalid command line arguments: {0}", String.Join( ", ", unnamedargs ) );
  482. 				}
  483. 			}
  484.  
  485. 			#endregion Unnamed Arguments
  486.  
  487.  
  488. 			#region Validate Specified Values and Combinations
  489.  
  490. 			if ( !listset )
  491. 			{
  492. 				return ShowHelp( "Mandatory list not specified" );
  493. 			}
  494.  
  495. 			if ( rows * columns != 0 )
  496. 			{
  497. 				return ShowHelp( "You may specify the number of either columns or rows, but not both" );
  498. 			}
  499.  
  500. 			int listrange = ( 1 << ( list.Split( new char[] { delimiter }, StringSplitOptions.RemoveEmptyEntries ).Length ) ) - 1;
  501. 			if ( defaultitems < 0 || defaultitems > listrange )
  502. 			{
  503. 				return ShowHelp( String.Format( "Preselected items ({0}) outside list range (0..{1})", defaultitems, listrange ) );
  504. 			}
  505.  
  506. 			#endregion Validate Specified Values and Combinations
  507.  
  508. 			#endregion Command Line Parsing
  509.  
  510.  
  511. 			#region Set Localized Captions
  512.  
  513. 			if ( localizedcaptionset )
  514. 			{
  515. 				cancelcaption = Load( "user32.dll", 801, cancelcaption );
  516. 				okcaption = Load( "user32.dll", 800, okcaption );
  517.  
  518. 				if ( !String.IsNullOrWhiteSpace( localizationstring ) )
  519. 				{
  520. 					string[] locstrings = localizationstring.Split( ";".ToCharArray( ) );
  521. 					foreach ( string locstring in locstrings )
  522. 					{
  523. 						string key = locstring.Substring( 0, locstring.IndexOf( '=' ) );
  524. 						string val = locstring.Substring( Math.Min( locstring.IndexOf( '=' ) + 1, locstring.Length - 1 ) );
  525. 						if ( !String.IsNullOrWhiteSpace( val ) )
  526. 						{
  527. 							switch ( key.ToUpper( ) )
  528. 							{
  529. 								case "OK":
  530. 									okcaption = val;
  531. 									break;
  532. 								case "CANCEL":
  533. 									cancelcaption = val;
  534. 									break;
  535. 								default:
  536. 									return ShowHelp( "Invalid localization key \"{0}\"", key );
  537. 							}
  538. 						}
  539. 					}
  540. 				}
  541. 			}
  542.  
  543. 			#endregion Set Localized Captions
  544.  
  545.  
  546. 			#region Parse List
  547.  
  548. 			List<string> listitems = new List<string>( list.Split( delimiter.ToString( ).ToCharArray( ), StringSplitOptions.RemoveEmptyEntries ) );
  549. 			if ( skipfirstitem )
  550. 			{
  551. 				listitems.RemoveAt( 0 );
  552. 			}
  553. 			for ( int i = 0; i < listitems.Count; i++ )
  554. 			{
  555. 				listitems[i] = listitems[i].Trim( );
  556. 			}
  557. 			if ( deduplist )
  558. 			{
  559. 				List<string> deduped = new List<string>( );
  560. 				foreach ( string key in listitems )
  561. 				{
  562. 					if ( !deduped.Contains( key ) )
  563. 					{
  564. 						deduped.Add( key );
  565. 					}
  566. 				}
  567. 				listitems = deduped;
  568. 			}
  569. 			if ( sortlist )
  570. 			{
  571. 				listitems.Sort( StringComparer.OrdinalIgnoreCase );
  572. 			}
  573.  
  574. 			#endregion Parse List
  575.  
  576.  
  577. 			#region Main Form
  578.  
  579. 			Form multiplechoiceform = new Form( );
  580. 			multiplechoiceform.FormBorderStyle = FormBorderStyle.FixedDialog;
  581. 			multiplechoiceform.MaximizeBox = false;
  582. 			multiplechoiceform.MinimizeBox = false;
  583. 			multiplechoiceform.StartPosition = FormStartPosition.CenterParent;
  584. 			multiplechoiceform.Text = title;
  585. 			multiplechoiceform.Icon = IconExtractor.Extract( "shell32.dll", icon, true );
  586.  
  587. 			#endregion Main Form
  588.  
  589.  
  590. 			#region Initial Sizes
  591.  
  592. 			int horizontalmargin = 10;
  593. 			int verticalmargin = 10;
  594. 			int promptwidth = 0;
  595. 			int cbtextheight = 0; // checkbox text height
  596. 			int cbtextwidth = 0; // checkbox text width
  597. 			int cbwidth = 15; // checkbox width without text
  598. 			int buttonheight = 25;
  599. 			int buttonwidth = 80;
  600.  
  601. 			#endregion Initial Sizes
  602.  
  603.  
  604. 			#region Prompt
  605.  
  606. 			if ( String.IsNullOrWhiteSpace( prompt ) )
  607. 			{
  608. 				promptheight = -1 * verticalmargin;
  609. 			}
  610. 			else
  611. 			{
  612. 				if ( monospaced )
  613. 				{
  614. 					labelPrompt.Font = new Font( FontFamily.GenericMonospace, labelPrompt.Font.Size );
  615. 				}
  616.  
  617. 				// Calculate required height for single prompt line
  618. 				promptheight = TextRenderer.MeasureText( "Test", labelPrompt.Font ).Height;
  619.  
  620. 				// Replace tabs with spaces
  621. 				if ( prompt.IndexOf( "\\t", StringComparison.Ordinal ) > -1 )
  622. 				{
  623. 					string tab = new String( ' ', tablength );
  624. 					// First split the prompt on newlines
  625. 					string[] prompt2 = prompt.Split( new string[] { "\\n" }, StringSplitOptions.None );
  626. 					for ( int i = 0; i < prompt2.Length; i++ )
  627. 					{
  628. 						if ( prompt2[i].IndexOf( "\\t", StringComparison.Ordinal ) > -1 )
  629. 						{
  630. 							// Split each "sub-line" of the prompt on tabs
  631. 							string[] prompt3 = prompt2[i].Split( new string[] { "\\t" }, StringSplitOptions.None );
  632. 							// Each substring before a tab gets n spaces attached, and then is shortened to the greatest possible multiple of n
  633. 							for ( int j = 0; j < prompt3.Length - 1; j++ )
  634. 							{
  635. 								prompt3[j] += tab;
  636. 								int length = prompt3[j].Length;
  637. 								length /= tablength;
  638. 								length *= tablength;
  639. 								prompt3[j] = prompt3[j].Substring( 0, length );
  640. 							}
  641. 							prompt2[i] = String.Join( "", prompt3 );
  642. 						}
  643. 					}
  644. 					prompt = String.Join( "\n", prompt2 );
  645. 				}
  646. 				prompt = prompt.Replace( "\\n", "\n" ).Replace( "\\r", "\r" );
  647. 				labelPrompt.Text = prompt;
  648. 				string[] lines = prompt.Split( "\n".ToCharArray( ) );
  649. 				int promptlines = lines.Length;
  650.  
  651. 				foreach ( string line in lines )
  652. 				{
  653. 					promptwidth = Math.Max( promptwidth, TextRenderer.MeasureText( line, labelPrompt.Font ).Width );
  654. 				}
  655.  
  656. 				// Calculate required height for multiple line prompt
  657. 				promptheight = promptlines * promptheight;
  658. 			}
  659.  
  660. 			#endregion Prompt
  661.  
  662.  
  663. 			#region Checkboxes
  664.  
  665. 			List<CheckBox> checkboxes = new List<CheckBox>( );
  666. 			for ( int i = 0; i < listitems.Count; i++ )
  667. 			{
  668. 				CheckBox checkbox = new CheckBox( );
  669. 				checkbox.Text = listitems[i];
  670. 				checkbox.Checked = ( ( defaultitems & ( 1 << i ) ) > 0 );
  671. 				cbtextwidth = Math.Max( cbtextwidth, Convert.ToInt32( TextRenderer.MeasureText( listitems[i], checkbox.Font ).Width * cbsafetyfactor ) );
  672. 				cbtextheight = Math.Max( cbtextheight, Convert.ToInt32( TextRenderer.MeasureText( listitems[i], checkbox.Font ).Height * cbsafetyfactor ) );
  673. 				checkboxes.Add( checkbox );
  674. 			}
  675.  
  676. 			GroupBox cbgroup = new GroupBox( );
  677.  
  678. 			#endregion Checkboxes
  679.  
  680.  
  681. 			#region Buttons
  682.  
  683. 			Button okButton = new Button( );
  684. 			okButton.DialogResult = DialogResult.OK;
  685. 			okButton.Name = "okButton";
  686. 			okButton.Text = okcaption;
  687.  
  688. 			Button cancelButton = new Button( );
  689. 			cancelButton.DialogResult = DialogResult.Cancel;
  690. 			cancelButton.Name = "cancelButton";
  691. 			cancelButton.Text = cancelcaption;
  692.  
  693. 			#endregion Buttons
  694.  
  695.  
  696. 			#region Calculate Window Layout
  697.  
  698. 			if ( rows > 0 )
  699. 			{
  700. 				rows = Math.Min( rows, listitems.Count );
  701. 				columns = (int) Math.Floor( (decimal) ( listitems.Count + rows - 1 ) / rows );
  702. 			}
  703. 			else if ( columns > 0 )
  704. 			{
  705. 				columns = Math.Min( columns, listitems.Count );
  706. 				rows = (int) Math.Floor( (decimal) ( listitems.Count + columns - 1 ) / columns );
  707. 			}
  708. 			else
  709. 			{
  710. 				columns = 1;
  711. 				rows = listitems.Count;
  712. 			}
  713.  
  714. 			int cbgroupwidth = 0;
  715. 			int cbgroupheight = 0;
  716. 			int rowheight = 0;
  717. 			int colwidth = 0;
  718.  
  719. 			if ( widthset )
  720. 			{
  721. 				cbgroupwidth = windowwidth - 2 * horizontalmargin;
  722. 				colwidth = (int) Math.Floor( (decimal) ( cbgroupwidth - horizontalmargin - columns * ( cbwidth + horizontalmargin ) ) / columns );
  723. 			}
  724. 			else
  725. 			{
  726. 				colwidth = cbtextwidth + cbwidth;
  727. 				cbgroupwidth = Math.Max( minimumwindowwidth - 2 * horizontalmargin, columns * ( colwidth + horizontalmargin ) + 2 * horizontalmargin );
  728. 				colwidth = Math.Max( colwidth, Convert.ToInt32( ( cbgroupwidth - 2 * horizontalmargin ) / columns ) - horizontalmargin );
  729. 				windowwidth = Math.Max( minimumwindowwidth, cbgroupwidth + 2 * horizontalmargin );
  730. 			}
  731.  
  732. 			if ( heightset )
  733. 			{
  734. 				cbgroupheight = windowheight - promptheight - buttonheight - 4 * verticalmargin;
  735. 				rowheight = (int) Math.Floor( (decimal) ( cbgroupheight - 2 * verticalmargin ) / rows );
  736. 			}
  737. 			else
  738. 			{
  739. 				rowheight = cbtextheight + verticalmargin;
  740. 				windowheight = Math.Max( minimumwindowheight, 6 * verticalmargin + promptheight + buttonheight + rows * rowheight );
  741. 				cbgroupheight = rows * rowheight + 2 * verticalmargin;
  742. 			}
  743.  
  744. 			#endregion Calculate Window Layout
  745.  
  746.  
  747. 			#region Check Available Group Box Space
  748.  
  749. 			if ( cbgroupheight / rows < rowheight || cbgroupwidth / columns < colwidth )
  750. 			{
  751. 				return ShowHelp( "Window size too small to display all checkboxes;\n\tincrease window size, reduce or remove prompt,\n\tand/or change number of rows and columns" );
  752. 			}
  753.  
  754. 			#endregion Check Available Group Box Space
  755.  
  756.  
  757. 			#region Build Form
  758.  
  759. 			Size windowsize = new Size( windowwidth, windowheight );
  760. 			multiplechoiceform.ClientSize = windowsize;
  761.  
  762. 			if ( !String.IsNullOrWhiteSpace( prompt ) )
  763. 			{
  764. 				labelPrompt.Size = new Size( windowwidth - 2 * horizontalmargin, promptheight );
  765. 				labelPrompt.Location = new Point( horizontalmargin, verticalmargin );
  766. 				multiplechoiceform.Controls.Add( labelPrompt );
  767. 			}
  768.  
  769. 			cbgroup.Size = new Size( cbgroupwidth, cbgroupheight );
  770. 			cbgroup.Location = new Point( horizontalmargin, promptheight + 2 * verticalmargin );
  771.  
  772. 			foreach ( CheckBox checkbox in checkboxes )
  773. 			{
  774. 				cbgroup.Controls.Add( checkbox );
  775. 			}
  776. 			multiplechoiceform.Controls.Add( cbgroup );
  777.  
  778. 			for ( int row = 0; row < rows; row++ )
  779. 			{
  780. 				for ( int column = 0; column < columns; column++ )
  781. 				{
  782. 					int index = row * columns + column;
  783. 					if ( index < checkboxes.Count )
  784. 					{
  785. 						int x = Convert.ToInt32( horizontalmargin + column * ( colwidth + horizontalmargin ) );
  786. 						int y = Convert.ToInt32( verticalmargin + row * rowheight );
  787. 						checkboxes[index].Size = new Size( colwidth + horizontalmargin, rowheight );
  788. 						checkboxes[index].Location = new Point( x, y );
  789. 					}
  790. 				}
  791. 			}
  792.  
  793. 			okButton.Size = new Size( buttonwidth, buttonheight );
  794. 			okButton.Location = new Point( windowwidth / 2 - horizontalmargin - buttonwidth, windowheight - buttonheight - verticalmargin );
  795. 			multiplechoiceform.Controls.Add( okButton );
  796.  
  797. 			cancelButton.Size = new Size( buttonwidth, buttonheight );
  798. 			cancelButton.Location = new Point( windowwidth / 2 + horizontalmargin, windowheight - buttonheight - verticalmargin );
  799. 			multiplechoiceform.Controls.Add( cancelButton );
  800.  
  801. 			multiplechoiceform.AcceptButton = okButton;  // OK on Enter
  802. 			multiplechoiceform.CancelButton = cancelButton; // Cancel on Esc
  803.  
  804. 			#endregion Build Form
  805.  
  806.  
  807. 			#region Show Dialog
  808.  
  809. 			multiplechoiceform.TopMost = topmost;
  810. 			DialogResult result = multiplechoiceform.ShowDialog( );
  811. 			if ( result == DialogResult.OK )
  812. 			{
  813. 				rc = 0;
  814. 				for ( int i = 0; i < cbgroup.Controls.Count; i++ )
  815. 				{
  816. 					Control control = cbgroup.Controls[i];
  817. 					if ( control.GetType( ) == typeof( CheckBox ) )
  818. 					{
  819. 						CheckBox cb = (CheckBox) control;
  820. 						if ( cb.Checked )
  821. 						{
  822. 							selectedtext += cb.Text + ";";
  823. 							rc += ( 1 << i );
  824. 						}
  825. 					}
  826. 				}
  827. 				// Display selected items
  828. 				Console.WriteLine( selectedtext );
  829. 			}
  830. 			else
  831. 			{
  832. 				rc = -1;
  833. 			}
  834.  
  835. 			#endregion Show Dialog
  836.  
  837.  
  838. 			return rc;
  839. 		}
  840.  
  841.  
  842. 		#region Error handling
  843.  
  844. 		public static int ShowAliases()
  845. 		{
  846. 			int rc = ShowHelp( );
  847.  
  848. 			Console.Error.WriteLine( );
  849.  
  850. 			Console.Error.WriteLine( );
  851.  
  852. 			Console.ForegroundColor = ConsoleColor.White;
  853. 			Console.Error.WriteLine( "Switch\tAlias(es)" );
  854.  
  855. 			Console.Error.WriteLine( "======\t=========" );
  856.  
  857. 			Console.Error.WriteLine( );
  858.  
  859. 			Console.Error.Write( "/?\t" );
  860. 			Console.ResetColor( );
  861. 			Console.Error.WriteLine( "/HELP" );
  862.  
  863. 			Console.Error.WriteLine( );
  864.  
  865. 			Console.ForegroundColor = ConsoleColor.White;
  866. 			Console.Error.Write( "/A\t" );
  867. 			Console.ResetColor( );
  868. 			Console.Error.WriteLine( "/??, /???, /ALIAS or /ALIASES" );
  869.  
  870. 			Console.Error.WriteLine( );
  871.  
  872. 			Console.ForegroundColor = ConsoleColor.White;
  873. 			Console.Error.Write( "/C\t" );
  874. 			Console.ResetColor( );
  875. 			Console.Error.WriteLine( "/COL, /COLS or /COLUMNS" );
  876.  
  877. 			Console.Error.WriteLine( );
  878.  
  879. 			Console.ForegroundColor = ConsoleColor.White;
  880. 			Console.Error.Write( "/D\t" );
  881. 			Console.ResetColor( );
  882. 			Console.Error.WriteLine( "/DELIMITER" );
  883.  
  884. 			Console.Error.WriteLine( );
  885.  
  886. 			Console.ForegroundColor = ConsoleColor.White;
  887. 			Console.Error.Write( "/DE\t" );
  888. 			Console.ResetColor( );
  889. 			Console.Error.WriteLine( "/DEDUP" );
  890.  
  891. 			Console.Error.WriteLine( );
  892.  
  893. 			Console.ForegroundColor = ConsoleColor.White;
  894. 			Console.Error.Write( "/F\t" );
  895. 			Console.ResetColor( );
  896. 			Console.Error.WriteLine( "/FILE" );
  897.  
  898. 			Console.Error.WriteLine( );
  899.  
  900. 			Console.ForegroundColor = ConsoleColor.White;
  901. 			Console.Error.Write( "/H\t" );
  902. 			Console.ResetColor( );
  903. 			Console.Error.WriteLine( "/HEIGHT" );
  904.  
  905. 			Console.Error.WriteLine( );
  906.  
  907. 			Console.ForegroundColor = ConsoleColor.White;
  908. 			Console.Error.Write( "/I\t" );
  909. 			Console.ResetColor( );
  910. 			Console.Error.WriteLine( "/ICON" );
  911.  
  912. 			Console.Error.WriteLine( );
  913.  
  914. 			Console.ForegroundColor = ConsoleColor.White;
  915. 			Console.Error.Write( "/K\t" );
  916. 			Console.ResetColor( );
  917. 			Console.Error.WriteLine( "/SKIP, /SKIPFIRST or /SKIPFIRSTITEM" );
  918.  
  919. 			Console.Error.WriteLine( );
  920.  
  921. 			Console.ForegroundColor = ConsoleColor.White;
  922. 			Console.Error.Write( "/L\t" );
  923. 			Console.ResetColor( );
  924. 			Console.Error.WriteLine( "/LOCALIZED or /LOCALIZEDCAPTIONS" );
  925.  
  926. 			Console.Error.WriteLine( );
  927.  
  928. 			Console.ForegroundColor = ConsoleColor.White;
  929. 			Console.Error.Write( "/MF\t" );
  930. 			Console.ResetColor( );
  931. 			Console.Error.WriteLine( "/MONO, /MONOSPACED or /MONOSPACEDFONT" );
  932.  
  933. 			Console.Error.WriteLine( );
  934.  
  935. 			Console.ForegroundColor = ConsoleColor.White;
  936. 			Console.Error.Write( "/NM\t" );
  937. 			Console.ResetColor( );
  938. 			Console.Error.WriteLine( "/NONMODAL or /NON-MODAL" );
  939.  
  940. 			Console.Error.WriteLine( );
  941.  
  942. 			Console.ForegroundColor = ConsoleColor.White;
  943. 			Console.Error.Write( "/P\t" );
  944. 			Console.ResetColor( );
  945. 			Console.Error.WriteLine( "/DEFAULT, /DEFAULTITEMS, /PRE, /PRESELECTED or /PRESELECTEDITEMS" );
  946.  
  947. 			Console.Error.WriteLine( );
  948.  
  949. 			Console.ForegroundColor = ConsoleColor.White;
  950. 			Console.Error.Write( "/R\t" );
  951. 			Console.ResetColor( );
  952. 			Console.Error.WriteLine( "/ROWS" );
  953.  
  954. 			Console.Error.WriteLine( );
  955.  
  956. 			Console.ForegroundColor = ConsoleColor.White;
  957. 			Console.Error.Write( "/S\t" );
  958. 			Console.ResetColor( );
  959. 			Console.Error.WriteLine( "/SORT or /SORTLIST" );
  960.  
  961. 			Console.Error.WriteLine( );
  962.  
  963. 			Console.ForegroundColor = ConsoleColor.White;
  964. 			Console.Error.Write( "/T\t" );
  965. 			Console.ResetColor( );
  966. 			Console.Error.WriteLine( "/TAB or /TABLENGTH" );
  967.  
  968. 			Console.Error.WriteLine( );
  969.  
  970. 			Console.ForegroundColor = ConsoleColor.White;
  971. 			Console.Error.Write( "/W\t" );
  972. 			Console.ResetColor( );
  973. 			Console.Error.WriteLine( "/WIDTH" );
  974.  
  975. 			Console.Error.WriteLine( );
  976.  
  977. 			return rc;
  978. 		}
  979.  
  980.  
  981. 		public static int ShowHelp( params string[] errmsg )
  982. 		{
  983. 			#region Help Text
  984.  
  985. 			/*
  986. 			MultipleChoiceBox,  Version 1.00
  987. 			Batch tool to present a Checkbox dialog and return the selected items
  988.  
  989. 			Usage:   MULTIPLECHOICEBOX  "list"  [ "prompt" [ "title" ] ]  [ options ]
  990.  
  991. 			   or:   MULTIPLECHOICEBOX  /F:"listfile"  [ "prompt" [ "title" ] ] [ options ]
  992.  
  993. 			   or:   listcommand |  MULTIPLECHOICEBOX  [ "prompt" [ "title" ] ] [ options ]
  994.  
  995. 			Where:   "list"          is a list of items to populate the checkbox group
  996. 			         "listcommand"   is a command whose standard output is used as a list
  997. 			                         of items to populate the checkbox group
  998. 			         "prompt"        is the optional text above the checkbox group
  999. 			                         (default: none)
  1000. 			         "title"         is the window title
  1001. 			                         (default: "MultipleChoiceBox,  Version 1.00")
  1002. 			Options: /A              show Aliases for command line switches (see Notes)
  1003. 			         /C:columns      sets then number of Columns for the checkbox group
  1004. 			                         (default: 1)
  1005. 			         /D:"delimiter"  sets the Delimiter character for "list"
  1006. 			                         (default: semicolon)
  1007. 			         /DE             DEdup: remove duplicates from "list"
  1008. 			         /F:"listfile"   use list from text File (one list item per line)
  1009. 			         /H:height       sets the window Height (default: autosized to make
  1010. 			                         content fit; minimum: 90; maximum: screen height - 68)
  1011. 			         /I:index        use Icon at index from shell32.dll (default: 23)
  1012. 			         /K              sKip first item of list (e.g. a header line)
  1013. 			         /L[:"captions"] Localize or customize button captions
  1014. 			                         (e.g. /L:"OK=Why Not?;Cancel=No Way!")
  1015. 			         /MF             use Monospaced Font in prompt (default: proportional)
  1016. 			         /NM             make dialog Non-Modal (default: Modal, i.e. on top)
  1017. 			         /P:initial      Preselect the initial checkboxes' state (see Notes)
  1018. 			         /R:rows         sets then number of Rows for the checkbox group
  1019. 			                         (default: one row per list item)
  1020. 			         /S              Sort list (default: unsorted)
  1021. 			         /T:tablength    sets the number of spaces for Tabs in prompt
  1022. 			                         (4..16; default: 4)
  1023. 			         /W:width        sets the window Width (default: autosized to make
  1024. 			                         content fit; minimum: 200; maximum: screen width - 16)
  1025.  
  1026. 			Notes:   The selected item text is written to Standard Out if "OK" is clicked,
  1027. 			         otherwise an empty string is returned.
  1028. 			         Most command line switches have one or more aliases, e.g. instead
  1029. 			         of /R:5 you can use /ROWS:5 to make your batch files more readable;
  1030. 			         use command line switch /A to get a list of all available aliases.
  1031. 			         Use either "list" or /F:"listfile" or "listcommand".
  1032. 			         Linefeeds (\n), tabs (\t) and doublequotes (\") are allowed in the
  1033. 			         prompt text (but not in the title); with tabs, /MF is recommended.
  1034. 			         To get a custom title without prompt, use " " for prompt.
  1035. 			         If specified without captions, switch /L forces localized button
  1036. 			         captions (e.g. "Cancel" button caption is "Annuleren" on Dutch
  1037. 			         systems); if only a single custom caption is specified, the other
  1038. 			         one is localized (e.g. with /L:"OK=Gaan" on Dutch systems, "OK"
  1039. 			         button caption is "Gaan", "Cancel" button caption is "Annuleren").
  1040. 			         With /P the inital state of each checkbox can be set; e.g. /P:5
  1041. 			         wil set the 1st (1<<0 = 1) and 3rd (1<<2 = 4) checkboxes checked.
  1042. 			         Return code is a binary representation of the checked items, e.g. 5
  1043. 			         (0101) if only the 1st and 3rd checkboxes were checked, -1 on errors.
  1044. 			         Be aware that the return code may be useless after sorting the list.
  1045.  
  1046. 			Credits: On-the-fly form based on code by Gorkem Gencay on StackOverflow:
  1047. 			         http://stackoverflow.com/questions/97097#17546909
  1048. 			         Code to retrieve localized button captions by Martin Stoeckli:
  1049. 			         http://martinstoeckli.ch/csharp/csharp.html#windows_text_resources
  1050. 			         Code to extract icons from Shell32.dll by Thomas Levesque:
  1051. 			         http://stackoverflow.com/questions/6873026
  1052.  
  1053. 			Written by Rob van der Woude
  1054. 			http://www.robvanderwoude.com
  1055. 			*/
  1056.  
  1057. 			#endregion Help Text
  1058.  
  1059.  
  1060. 			#region Error Message
  1061.  
  1062. 			if ( errmsg.Length > 0 )
  1063. 			{
  1064. 				List<string> errargs = new List<string>( errmsg );
  1065. 				errargs.RemoveAt( 0 );
  1066. 				Console.Error.WriteLine( );
  1067. 				Console.ForegroundColor = ConsoleColor.Red;
  1068. 				Console.Error.Write( "ERROR:\t" );
  1069. 				Console.ForegroundColor = ConsoleColor.White;
  1070. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  1071. 				Console.ResetColor( );
  1072. 			}
  1073.  
  1074. 			#endregion Error Message
  1075.  
  1076.  
  1077. 			#region Show Help Text
  1078.  
  1079. 			Console.Error.WriteLine( );
  1080.  
  1081. 			Console.Error.WriteLine( "RadioButtonBox,  Version {0}", progver );
  1082.  
  1083. 			Console.Error.WriteLine( "Batch tool to present a Checkbox dialog and return the selected items" );
  1084.  
  1085. 			Console.Error.WriteLine( );
  1086.  
  1087. 			Console.Error.Write( "Usage:   " );
  1088. 			Console.ForegroundColor = ConsoleColor.White;
  1089. 			Console.Error.WriteLine( "MULTIPLECHOICEBOX  \"list\"  [ \"prompt\" [ \"title\" ] ] [ options ]" );
  1090. 			Console.ResetColor( );
  1091.  
  1092. 			Console.Error.WriteLine( );
  1093.  
  1094. 			Console.Error.Write( "   or:   " );
  1095. 			Console.ForegroundColor = ConsoleColor.White;
  1096. 			Console.Error.WriteLine( "MULTIPLECHOICEBOX  /F:\"listfile\"  [ \"prompt\" [ \"title\" ] ] [ options ]" );
  1097. 			Console.ResetColor( );
  1098.  
  1099. 			Console.Error.WriteLine( );
  1100.  
  1101. 			Console.Error.Write( "   or:   " );
  1102. 			Console.ForegroundColor = ConsoleColor.White;
  1103. 			Console.Error.WriteLine( "listcommand |  MULTIPLECHOICEBOX  [ \"prompt\" [ \"title\" ] ] [ options ]" );
  1104. 			Console.ResetColor( );
  1105.  
  1106. 			Console.Error.WriteLine( );
  1107.  
  1108. 			Console.Error.Write( "Where:   " );
  1109. 			Console.ForegroundColor = ConsoleColor.White;
  1110. 			Console.Error.Write( "\"list\"" );
  1111. 			Console.ResetColor( );
  1112. 			Console.Error.WriteLine( "          is a list of items to populate the checkbox group" );
  1113.  
  1114. 			Console.ForegroundColor = ConsoleColor.White;
  1115. 			Console.Error.Write( "         \"listcommand\"" );
  1116. 			Console.ResetColor( );
  1117. 			Console.Error.Write( "   is a " );
  1118. 			Console.ForegroundColor = ConsoleColor.White;
  1119. 			Console.Error.Write( "command" );
  1120. 			Console.ResetColor( );
  1121. 			Console.Error.Write( " whose standard output is used as a " );
  1122. 			Console.ForegroundColor = ConsoleColor.White;
  1123. 			Console.Error.WriteLine( "list" );
  1124. 			Console.ResetColor( );
  1125.  
  1126. 			Console.Error.WriteLine( "                         of items to populate the checkbox group" );
  1127.  
  1128. 			Console.ForegroundColor = ConsoleColor.White;
  1129. 			Console.Error.Write( "         \"prompt\"" );
  1130. 			Console.ResetColor( );
  1131. 			Console.Error.WriteLine( "        is the optional text above the checkbox group" );
  1132.  
  1133. 			Console.Error.WriteLine( "                         (default: none)" );
  1134.  
  1135. 			Console.ForegroundColor = ConsoleColor.White;
  1136. 			Console.Error.Write( "         \"title\"" );
  1137. 			Console.ResetColor( );
  1138. 			Console.Error.WriteLine( "         is the window title" );
  1139.  
  1140. 			Console.Error.WriteLine( "                         (default: \"MultipleChoiceBox,  Version {0}\")", progver );
  1141.  
  1142. 			Console.Error.Write( "Options: " );
  1143. 			Console.ForegroundColor = ConsoleColor.White;
  1144. 			Console.Error.Write( "/A" );
  1145. 			Console.ResetColor( );
  1146. 			Console.Error.Write( "              show " );
  1147. 			Console.ForegroundColor = ConsoleColor.White;
  1148. 			Console.Error.Write( "A" );
  1149. 			Console.ResetColor( );
  1150. 			Console.Error.WriteLine( "liases for command line switches (see Notes)" );
  1151.  
  1152. 			Console.ForegroundColor = ConsoleColor.White;
  1153. 			Console.Error.Write( "         /C:columns" );
  1154. 			Console.ResetColor( );
  1155. 			Console.Error.Write( "      sets the number of " );
  1156. 			Console.ForegroundColor = ConsoleColor.White;
  1157. 			Console.Error.Write( "C" );
  1158. 			Console.ResetColor( );
  1159. 			Console.Error.WriteLine( "olumns for the checkbox group" );
  1160.  
  1161. 			Console.Error.WriteLine( "                         (default: 1)" );
  1162.  
  1163. 			Console.ForegroundColor = ConsoleColor.White;
  1164. 			Console.Error.Write( "         /D:\"delimiter\"" );
  1165. 			Console.ResetColor( );
  1166. 			Console.Error.Write( "  sets the " );
  1167. 			Console.ForegroundColor = ConsoleColor.White;
  1168. 			Console.Error.Write( "D" );
  1169. 			Console.ResetColor( );
  1170. 			Console.Error.Write( "elimiter character for " );
  1171. 			Console.ForegroundColor = ConsoleColor.White;
  1172. 			Console.Error.WriteLine( "\"list\"" );
  1173. 			Console.ResetColor( );
  1174.  
  1175. 			Console.Error.WriteLine( "                         (default: semicolon)" );
  1176.  
  1177. 			Console.ForegroundColor = ConsoleColor.White;
  1178. 			Console.Error.Write( "         /DE             DE" );
  1179. 			Console.ResetColor( );
  1180. 			Console.Error.Write( "dup: remove duplicates from " );
  1181. 			Console.ForegroundColor = ConsoleColor.White;
  1182. 			Console.Error.WriteLine( "\"list\"" );
  1183. 			Console.ResetColor( );
  1184.  
  1185. 			Console.ForegroundColor = ConsoleColor.White;
  1186. 			Console.Error.Write( "         /F:\"listfile\"" );
  1187. 			Console.ResetColor( );
  1188. 			Console.Error.Write( "   use list from text " );
  1189. 			Console.ForegroundColor = ConsoleColor.White;
  1190. 			Console.Error.Write( "F" );
  1191. 			Console.ResetColor( );
  1192. 			Console.Error.WriteLine( "ile (one list item per line)" );
  1193.  
  1194. 			Console.ForegroundColor = ConsoleColor.White;
  1195. 			Console.Error.Write( "         /H:height" );
  1196. 			Console.ResetColor( );
  1197. 			Console.Error.Write( "       sets the window " );
  1198. 			Console.ForegroundColor = ConsoleColor.White;
  1199. 			Console.Error.Write( "H" );
  1200. 			Console.ResetColor( );
  1201. 			Console.Error.WriteLine( "eight (default: autosized to make" );
  1202.  
  1203. 			Console.Error.WriteLine( "                         content fit; minimum: {0}; maximum: screen height - {1})", minimumwindowheight, borderY );
  1204.  
  1205. 			Console.ForegroundColor = ConsoleColor.White;
  1206. 			Console.Error.Write( "         /I:index" );
  1207. 			Console.ResetColor( );
  1208. 			Console.Error.Write( "        use " );
  1209. 			Console.ForegroundColor = ConsoleColor.White;
  1210. 			Console.Error.Write( "I" );
  1211. 			Console.ResetColor( );
  1212. 			Console.Error.Write( "con at " );
  1213. 			Console.ForegroundColor = ConsoleColor.White;
  1214. 			Console.Error.Write( "index" );
  1215. 			Console.ResetColor( );
  1216. 			Console.Error.WriteLine( " from shell32.dll (default: 23)" );
  1217.  
  1218. 			Console.ForegroundColor = ConsoleColor.White;
  1219. 			Console.Error.Write( "         /K" );
  1220. 			Console.ResetColor( );
  1221. 			Console.Error.Write( "              s" );
  1222. 			Console.ForegroundColor = ConsoleColor.White;
  1223. 			Console.Error.Write( "K" );
  1224. 			Console.ResetColor( );
  1225. 			Console.Error.WriteLine( "ip first item of list (e.g. a header line)" );
  1226.  
  1227. 			Console.ForegroundColor = ConsoleColor.White;
  1228. 			Console.Error.Write( "         /L[:\"captions\"] L" );
  1229. 			Console.ResetColor( );
  1230. 			Console.Error.Write( "ocalize or customize button " );
  1231. 			Console.ForegroundColor = ConsoleColor.White;
  1232. 			Console.Error.WriteLine( "captions" );
  1233. 			Console.ResetColor( );
  1234.  
  1235. 			Console.Error.Write( "                         (e.g. " );
  1236. 			Console.ForegroundColor = ConsoleColor.White;
  1237. 			Console.Error.Write( "/L:\"OK=Why Not?;Cancel=No Way!\"" );
  1238. 			Console.ResetColor( );
  1239. 			Console.Error.WriteLine( ")" );
  1240.  
  1241. 			Console.ForegroundColor = ConsoleColor.White;
  1242. 			Console.Error.Write( "         /MF" );
  1243. 			Console.ResetColor( );
  1244. 			Console.Error.Write( "             use " );
  1245. 			Console.ForegroundColor = ConsoleColor.White;
  1246. 			Console.Error.Write( "M" );
  1247. 			Console.ResetColor( );
  1248. 			Console.Error.Write( "onospaced " );
  1249. 			Console.ForegroundColor = ConsoleColor.White;
  1250. 			Console.Error.Write( "F" );
  1251. 			Console.ResetColor( );
  1252. 			Console.Error.Write( "ont in " );
  1253. 			Console.ForegroundColor = ConsoleColor.White;
  1254. 			Console.Error.Write( "prompt" );
  1255. 			Console.ResetColor( );
  1256. 			Console.Error.WriteLine( " (default: proportional)" );
  1257.  
  1258. 			Console.ForegroundColor = ConsoleColor.White;
  1259. 			Console.Error.Write( "         /NM" );
  1260. 			Console.ResetColor( );
  1261. 			Console.Error.Write( "             make dialog " );
  1262. 			Console.ForegroundColor = ConsoleColor.White;
  1263. 			Console.Error.Write( "N" );
  1264. 			Console.ResetColor( );
  1265. 			Console.Error.Write( "on-" );
  1266. 			Console.ForegroundColor = ConsoleColor.White;
  1267. 			Console.Error.Write( "M" );
  1268. 			Console.ResetColor( );
  1269. 			Console.Error.WriteLine( "odal (default: modal, i.e. on top)" );
  1270.  
  1271. 			Console.ForegroundColor = ConsoleColor.White;
  1272. 			Console.Error.Write( "         /P:initial      P" );
  1273. 			Console.ResetColor( );
  1274. 			Console.Error.Write( "reselect the " );
  1275. 			Console.ForegroundColor = ConsoleColor.White;
  1276. 			Console.Error.Write( "initial" );
  1277. 			Console.ResetColor( );
  1278. 			Console.Error.WriteLine( " checkboxes' state (see Notes)" );
  1279.  
  1280. 			Console.ForegroundColor = ConsoleColor.White;
  1281. 			Console.Error.Write( "         /R:rows" );
  1282. 			Console.ResetColor( );
  1283. 			Console.Error.Write( "         sets then number of " );
  1284. 			Console.ForegroundColor = ConsoleColor.White;
  1285. 			Console.Error.Write( "R" );
  1286. 			Console.ResetColor( );
  1287. 			Console.Error.WriteLine( "ows for the checkbox group" );
  1288.  
  1289. 			Console.Error.WriteLine( "                         (default: one row per list item)" );
  1290.  
  1291. 			Console.ForegroundColor = ConsoleColor.White;
  1292. 			Console.Error.Write( "         /S              S" );
  1293. 			Console.ResetColor( );
  1294. 			Console.Error.WriteLine( "ort list (default: unsorted)" );
  1295.  
  1296. 			Console.ForegroundColor = ConsoleColor.White;
  1297. 			Console.Error.Write( "         /T:tablength" );
  1298. 			Console.ResetColor( );
  1299. 			Console.Error.Write( "    sets the number of spaces for " );
  1300. 			Console.ForegroundColor = ConsoleColor.White;
  1301. 			Console.Error.Write( "T" );
  1302. 			Console.ResetColor( );
  1303. 			Console.Error.Write( "abs in " );
  1304. 			Console.ForegroundColor = ConsoleColor.White;
  1305. 			Console.Error.WriteLine( "prompt" );
  1306. 			Console.ResetColor( );
  1307.  
  1308. 			Console.Error.WriteLine( "                         (4..16; default: 4)" );
  1309.  
  1310. 			Console.ForegroundColor = ConsoleColor.White;
  1311. 			Console.Error.Write( "         /W:width" );
  1312. 			Console.ResetColor( );
  1313. 			Console.Error.Write( "        sets the window " );
  1314. 			Console.ForegroundColor = ConsoleColor.White;
  1315. 			Console.Error.Write( "W" );
  1316. 			Console.ResetColor( );
  1317. 			Console.Error.WriteLine( "idth (default: autosized to make" );
  1318.  
  1319. 			Console.Error.WriteLine( "                         content fit; minimum: {0}; maximum: screen width - {1})", minimumwindowwidth, borderX );
  1320.  
  1321. 			Console.Error.WriteLine( );
  1322.  
  1323. 			Console.Error.WriteLine( "Notes:   The selected item text is written to Standard Out if \"OK\" is clicked," );
  1324.  
  1325. 			Console.Error.WriteLine( "         otherwise an empty string is returned." );
  1326.  
  1327. 			Console.Error.WriteLine( "         Most command line switches have one or more aliases, e.g. instead" );
  1328.  
  1329. 			Console.Error.Write( "         of " );
  1330. 			Console.ForegroundColor = ConsoleColor.White;
  1331. 			Console.Error.Write( "/R:5" );
  1332. 			Console.ResetColor( );
  1333. 			Console.Error.Write( " you can use " );
  1334. 			Console.ForegroundColor = ConsoleColor.White;
  1335. 			Console.Error.Write( "/ROWS:5" );
  1336. 			Console.ResetColor( );
  1337. 			Console.Error.WriteLine( " to make your batch files more readable;" );
  1338.  
  1339. 			Console.Error.Write( "         use command line switch " );
  1340. 			Console.ForegroundColor = ConsoleColor.White;
  1341. 			Console.Error.Write( "/A" );
  1342. 			Console.ResetColor( );
  1343. 			Console.Error.WriteLine( " to get a list of all available aliases." );
  1344.  
  1345. 			Console.Error.Write( "         Use either " );
  1346. 			Console.ForegroundColor = ConsoleColor.White;
  1347. 			Console.Error.Write( "\"list\"" );
  1348. 			Console.ResetColor( );
  1349. 			Console.Error.Write( " or " );
  1350. 			Console.ForegroundColor = ConsoleColor.White;
  1351. 			Console.Error.Write( "/F:\"listfile\"" );
  1352. 			Console.ResetColor( );
  1353. 			Console.Error.Write( " or " );
  1354. 			Console.ForegroundColor = ConsoleColor.White;
  1355. 			Console.Error.Write( "\"listcommand\"" );
  1356. 			Console.ResetColor( );
  1357. 			Console.Error.WriteLine( "." );
  1358.  
  1359. 			Console.Error.WriteLine( "         Linefeeds (\\n), tabs (\\t) and doublequotes (\\\") are allowed in the" );
  1360.  
  1361. 			Console.ForegroundColor = ConsoleColor.White;
  1362. 			Console.Error.Write( "         prompt" );
  1363. 			Console.ResetColor( );
  1364. 			Console.Error.Write( " text (but not in the " );
  1365. 			Console.ForegroundColor = ConsoleColor.White;
  1366. 			Console.Error.Write( "title" );
  1367. 			Console.ResetColor( );
  1368. 			Console.Error.Write( "); with tabs, " );
  1369. 			Console.ForegroundColor = ConsoleColor.White;
  1370. 			Console.Error.Write( "/MF" );
  1371. 			Console.ResetColor( );
  1372. 			Console.Error.WriteLine( " is recommended." );
  1373.  
  1374. 			Console.Error.WriteLine( "         To get a custom title without prompt, use \" \" for prompt." );
  1375.  
  1376. 			Console.Error.Write( "         If specified without " );
  1377. 			Console.ForegroundColor = ConsoleColor.White;
  1378. 			Console.Error.Write( "captions" );
  1379. 			Console.ResetColor( );
  1380. 			Console.Error.Write( ", switch " );
  1381. 			Console.ForegroundColor = ConsoleColor.White;
  1382. 			Console.Error.Write( "/L" );
  1383. 			Console.ResetColor( );
  1384. 			Console.Error.WriteLine( " forces localized button" );
  1385.  
  1386. 			Console.Error.WriteLine( "         captions (e.g. \"Cancel\" button caption is \"Annuleren\" on Dutch" );
  1387.  
  1388. 			Console.Error.WriteLine( "         systems); if only a single custom caption is specified, the other" );
  1389.  
  1390. 			Console.Error.Write( "         one is localized (e.g. with " );
  1391. 			Console.ForegroundColor = ConsoleColor.White;
  1392. 			Console.Error.Write( "/L:\"OK=Gaan\"" );
  1393. 			Console.ResetColor( );
  1394. 			Console.Error.WriteLine( " on Dutch systems, \"OK\"" );
  1395.  
  1396. 			Console.Error.WriteLine( "         button caption is \"Gaan\", \"Cancel\" button caption is \"Annuleren\")." );
  1397.  
  1398. 			Console.Error.WriteLine( "         Return code 0 for \"OK\", 1 for (command line) errors, 2 for \"Cancel\"." );
  1399.  
  1400. 			Console.Error.Write( "         With " );
  1401. 			Console.ForegroundColor = ConsoleColor.White;
  1402. 			Console.Error.Write( "/P" );
  1403. 			Console.ResetColor( );
  1404. 			Console.Error.Write( " the " );
  1405. 			Console.ForegroundColor = ConsoleColor.White;
  1406. 			Console.Error.Write( "inital" );
  1407. 			Console.ResetColor( );
  1408. 			Console.Error.Write( " state of each checkbox can be set; e.g. " );
  1409. 			Console.ForegroundColor = ConsoleColor.White;
  1410. 			Console.Error.WriteLine( "/P:5" );
  1411. 			Console.ResetColor( );
  1412.  
  1413. 			Console.Error.WriteLine( "         wil set the 1st (1<<0 = 1) and 3rd (1<<2 = 4) checkboxes checked." );
  1414.  
  1415. 			Console.Error.WriteLine( "         Return code is a binary representation of the checked items, e.g. 5" );
  1416.  
  1417. 			Console.Error.WriteLine( "         (0101) if only the 1st and 3rd checkboxes were checked, -1 on errors." );
  1418.  
  1419. 			Console.Error.WriteLine( "         Be aware that the return code may be useless after sorting the list." );
  1420.  
  1421. 			Console.Error.WriteLine( );
  1422.  
  1423. 			Console.Error.WriteLine( "Credits: On-the-fly form based on code by Gorkem Gencay on StackOverflow:" );
  1424.  
  1425. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  1426. 			Console.Error.WriteLine( "         http://stackoverflow.com/questions/17546909" );
  1427. 			Console.ResetColor( );
  1428.  
  1429. 			Console.Error.WriteLine( "         Code to retrieve localized button captions by Martin Stoeckli:" );
  1430.  
  1431. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  1432. 			Console.Error.WriteLine( "         http://martinstoeckli.ch/csharp/csharp.html#windows_text_resources" );
  1433. 			Console.ResetColor( );
  1434.  
  1435. 			Console.Error.WriteLine( "         Code to extract icons from Shell32.dll by Thomas Levesque:" );
  1436.  
  1437. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  1438. 			Console.Error.WriteLine( "         http://stackoverflow.com/questions/6873026" );
  1439. 			Console.ResetColor( );
  1440.  
  1441. 			Console.Error.WriteLine( );
  1442.  
  1443. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  1444.  
  1445. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  1446.  
  1447. 			#endregion Show Help Text
  1448.  
  1449.  
  1450. 			return -1;
  1451. 		}
  1452.  
  1453. 		#endregion Error handling
  1454.  
  1455.  
  1456. 		#region Get Window Border Dimensions
  1457.  
  1458. 		public static int[] BorderDimensions()
  1459. 		{
  1460. 			Form testform = new Form( );
  1461. 			Size testsize = new Size( 300, 200 );
  1462. 			testform.Size = testsize;
  1463. 			int deltaX = testform.Size.Width - testform.ClientSize.Width + Screen.PrimaryScreen.Bounds.Width - Screen.PrimaryScreen.WorkingArea.Width;
  1464. 			int deltaY = testform.Size.Height - testform.ClientSize.Height + Screen.PrimaryScreen.Bounds.Height - Screen.PrimaryScreen.WorkingArea.Height;
  1465. 			testform.Dispose( );
  1466. 			return new int[] { deltaX, deltaY };
  1467. 		}
  1468.  
  1469. 		#endregion Get Window Border Dimensions
  1470.  
  1471.  
  1472. 		#region Get Localized Captions
  1473.  
  1474. 		// Code to retrieve localized captions by Martin Stoeckli
  1475. 		// http://martinstoeckli.ch/csharp/csharp.html#windows_text_resources
  1476.  
  1477. 		/// <summary>
  1478. 		/// Searches for a text resource in a Windows library.
  1479. 		/// Sometimes, using the existing Windows resources, you can make your code
  1480. 		/// language independent and you don't have to care about translation problems.
  1481. 		/// </summary>
  1482. 		/// <example>
  1483. 		///   btnCancel.Text = Load("user32.dll", 801, "Cancel");
  1484. 		///   btnYes.Text = Load("user32.dll", 805, "Yes");
  1485. 		/// </example>
  1486. 		/// <param name="libraryName">Name of the windows library like "user32.dll"
  1487. 		/// or "shell32.dll"</param>
  1488. 		/// <param name="ident">Id of the string resource.</param>
  1489. 		/// <param name="defaultText">Return this text, if the resource string could
  1490. 		/// not be found.</param>
  1491. 		/// <returns>Requested string if the resource was found,
  1492. 		/// otherwise the <paramref name="defaultText"/></returns>
  1493. 		public static string Load( string libraryName, UInt32 ident, string defaultText )
  1494. 		{
  1495. 			IntPtr libraryHandle = GetModuleHandle( libraryName );
  1496. 			if ( libraryHandle != IntPtr.Zero )
  1497. 			{
  1498. 				StringBuilder sb = new StringBuilder( 1024 );
  1499. 				int size = LoadString( libraryHandle, ident, sb, 1024 );
  1500. 				if ( size > 0 )
  1501. 					return sb.ToString( );
  1502. 			}
  1503. 			return defaultText;
  1504. 		}
  1505.  
  1506. 		[DllImport( "kernel32.dll", CharSet = CharSet.Auto )]
  1507. 		private static extern IntPtr GetModuleHandle( string lpModuleName );
  1508.  
  1509. 		[DllImport( "user32.dll", CharSet = CharSet.Auto )]
  1510. 		private static extern int LoadString( IntPtr hInstance, UInt32 uID, StringBuilder lpBuffer, Int32 nBufferMax );
  1511.  
  1512. 		#endregion Get Localized Captions
  1513.  
  1514.  
  1515. 		#region Extract Icons
  1516.  
  1517. 		// Code to extract icons from Shell32.dll by Thomas Levesque
  1518. 		// http://stackoverflow.com/questions/6873026
  1519.  
  1520. 		public class IconExtractor
  1521. 		{
  1522.  
  1523. 			public static Icon Extract( string file, int number, bool largeIcon )
  1524. 			{
  1525. 				IntPtr large;
  1526. 				IntPtr small;
  1527. 				ExtractIconEx( file, number, out large, out small, 1 );
  1528. 				try
  1529. 				{
  1530. 					return Icon.FromHandle( largeIcon ? large : small );
  1531. 				}
  1532. 				catch
  1533. 				{
  1534. 					return null;
  1535. 				}
  1536.  
  1537. 			}
  1538.  
  1539. 			[DllImport( "Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall )]
  1540. 			private static extern int ExtractIconEx( string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons );
  1541. 		}
  1542.  
  1543. 		#endregion Extract Icons
  1544. 	}
  1545. }
  1546.  

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