Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for dropdownbox.cs

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.IO;
  5. using System.Linq;
  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 DropDownBox
  15. 	{
  16. 		public static string progver = "1.17";
  17. 		public static bool returnindex0 = false;
  18. 		public static bool returnindex1 = false;
  19.  
  20. 		[STAThread]
  21. 		static int Main( string[] args )
  22. 		{
  23. 			#region Initialize Variables
  24.  
  25. 			const int defaultheight = 90;
  26. 			const int defaultwidth = 200;
  27.  
  28. 			char delimiter = ';';
  29. 			List<string> namedargs = new List<string>( );
  30. 			List<string> unnamedargs = new List<string>( );
  31. 			string file = String.Empty;
  32. 			string list = String.Empty;
  33. 			string cancelcaption = "&Cancel";
  34. 			string okcaption = "&OK";
  35. 			string localizationstring = String.Empty;
  36. 			string prompt = String.Empty;
  37. 			string selectedText = String.Empty;
  38. 			string title = String.Format( "DropDownBox,  Version {0}", progver );
  39. 			bool delimiterset = false;
  40. 			bool heightset = false;
  41. 			bool iconset = false;
  42. 			bool indexset = false;
  43. 			bool localizedcaptionset = false;
  44. 			bool monospaced = false;
  45. 			bool skipfirstitem = false;
  46. 			bool sortlist = false;
  47. 			bool tablengthset = false;
  48. 			bool topmost = true;
  49. 			bool widthset = false;
  50. 			int height = defaultheight;
  51. 			int icon = 23;
  52. 			int selectedindex = 0;
  53. 			int tablength = 4;
  54. 			int width = defaultwidth;
  55.  
  56. 			bool isredirected = Console.IsInputRedirected; // Requires .NET Framework 4.5
  57. 			bool listset = isredirected;
  58. 			int redirectnum = ( isredirected ? 1 : 0 );
  59. 			int arguments = args.Length + redirectnum;
  60.  
  61. 			#endregion Initialize Variables
  62.  
  63.  
  64. 			#region Command Line Parsing
  65.  
  66. 			if ( arguments == 0 )
  67. 			{
  68. 				return ShowHelp( );
  69. 			}
  70.  
  71. 			if ( arguments > 13 )
  72. 			{
  73. 				return ShowHelp( "Too many command line arguments" );
  74. 			}
  75.  
  76. 			// Split up named and unnamed arguments
  77. 			foreach ( string arg in args )
  78. 			{
  79. 				if ( arg == "/?" )
  80. 				{
  81. 					return ShowHelp( );
  82. 				}
  83. 				if ( arg[0] == '/' )
  84. 				{
  85. 					namedargs.Add( arg );
  86. 				}
  87. 				else
  88. 				{
  89. 					unnamedargs.Add( arg );
  90. 				}
  91. 			}
  92.  
  93. 			// Read Standard Input if the list is redirected
  94. 			if ( isredirected )
  95. 			{
  96. 				try
  97. 				{
  98. 					string delim = delimiter.ToString( );
  99. 					list = string.Join( delim, Console.In.ReadToEnd( ).Split( "\n\r".ToCharArray( ), StringSplitOptions.RemoveEmptyEntries ) );
  100. 					// Trim list items, remove empty ones
  101. 					string pattern = "\\s*" + delim + "+\\s*";
  102. 					list = Regex.Replace( list, pattern, delim );
  103. 				}
  104. 				catch ( Exception e )
  105. 				{
  106. 					return ShowHelp( e.Message );
  107. 				}
  108. 			}
  109.  
  110. 			// First, validate the named arguments
  111. 			#region Named Arguments
  112.  
  113. 			foreach ( string arg in namedargs )
  114. 			{
  115. 				if ( arg.Length < 3 && arg.ToUpper( ) != "/K" && arg.ToUpper( ) != "/L" && arg.ToUpper( ) != "/S" )
  116. 				{
  117. 					return ShowHelp( "Invalid command line switch {0} or missing value", arg );
  118. 				}
  119. 				if ( arg.ToUpper( ) == "/K" )
  120. 				{
  121. 					if ( skipfirstitem )
  122. 					{
  123. 						return ShowHelp( "Duplicate command line switch /K" );
  124. 					}
  125. 					skipfirstitem = true;
  126. 				}
  127. 				else if ( arg.ToUpper( ) == "/L" )
  128. 				{
  129. 					if ( localizedcaptionset )
  130. 					{
  131. 						return ShowHelp( "Duplicate command line switch /L" );
  132. 					}
  133. 					localizedcaptionset = true;
  134. 				}
  135. 				else if ( arg.ToUpper( ) == "/S" )
  136. 				{
  137. 					if ( sortlist )
  138. 					{
  139. 						return ShowHelp( "Duplicate command line switch /S" );
  140. 					}
  141. 					sortlist = true;
  142. 				}
  143. 				else
  144. 				{
  145. 					switch ( arg.Substring( 0, 3 ).ToUpper( ) )
  146. 					{
  147. 						case "/C:":
  148. 							if ( iconset )
  149. 							{
  150. 								return ShowHelp( "Duplicate command line switch /D" );
  151. 							}
  152. 							try
  153. 							{
  154. 								icon = Convert.ToInt32( arg.Substring( 3 ) );
  155. 							}
  156. 							catch ( Exception )
  157. 							{
  158. 								return ShowHelp( "Invalid icon index: {0}", arg.Substring( 3 ) );
  159. 							}
  160. 							iconset = true;
  161. 							break;
  162. 						case "/D:":
  163. 							if ( delimiterset )
  164. 							{
  165. 								return ShowHelp( "Duplicate command line switch /D" );
  166. 							}
  167. 							string test = arg.Substring( 3 );
  168. 							if ( test.Length == 1 )
  169. 							{
  170. 								delimiter = test[0];
  171. 							}
  172. 							else if ( test.Length == 3 && ( ( test[0] == '"' && test[2] == '"' ) || ( test[0] == '\'' && test[2] == '\'' ) ) )
  173. 							{
  174. 								delimiter = test[1];
  175. 							}
  176. 							else
  177. 							{
  178. 								return ShowHelp( "Invalid delimiter specified \"{0}\"", arg );
  179. 							}
  180. 							break;
  181. 						case "/F:":
  182. 							if ( listset )
  183. 							{
  184. 								return ShowHelp( "Duplicate command line switch /F" );
  185. 							}
  186. 							file = arg.Substring( 3 );
  187. 							if ( string.IsNullOrEmpty( file ) || !File.Exists( file ) )
  188. 							{
  189. 								return ShowHelp( "List file not found: \"{0}\"", file );
  190. 							}
  191. 							else
  192. 							{
  193. 								try
  194. 								{
  195. 									string delim = delimiter.ToString( );
  196. 									list = String.Join( delim, File.ReadLines( file ) );
  197. 									// Remove empty list items
  198. 									string pattern = delim + "{2,}";
  199. 									list = Regex.Replace( list, pattern, delim );
  200. 									pattern = "(^" + delim + "|" + delim + "$)";
  201. 									list = Regex.Replace( list, pattern, string.Empty );
  202. 								}
  203. 								catch ( Exception e )
  204. 								{
  205. 									return ShowHelp( e.Message );
  206. 								}
  207. 							}
  208. 							listset = true;
  209. 							break;
  210. 						case "/H:":
  211. 							if ( heightset )
  212. 							{
  213. 								return ShowHelp( "Duplicate command line switch /H" );
  214. 							}
  215. 							try
  216. 							{
  217. 								height = Convert.ToInt32( arg.Substring( 3 ) );
  218. 								if ( height < defaultheight || height > Screen.PrimaryScreen.Bounds.Height )
  219. 								{
  220. 									return ShowHelp( "Height {0} outside allowed range of {1}..{2}", arg.Substring( 3 ), defaultheight.ToString( ), Screen.PrimaryScreen.Bounds.Height.ToString( ) );
  221. 								}
  222. 							}
  223. 							catch ( Exception e )
  224. 							{
  225. 								return ShowHelp( "Invalid height \"{0}\": {1}", arg.Substring( 3 ), e.Message );
  226. 							}
  227. 							heightset = true;
  228. 							break;
  229. 						case "/I:":
  230. 							if ( indexset )
  231. 							{
  232. 								return ShowHelp( "Duplicate command line switch /I" );
  233. 							}
  234. 							try
  235. 							{
  236. 								selectedindex = Convert.ToInt32( arg.Substring( 3 ) );
  237. 							}
  238. 							catch ( Exception e )
  239. 							{
  240. 								return ShowHelp( "Invalid index value \"{0}\": {1}", arg, e.Message );
  241. 							}
  242. 							break;
  243. 						case "/L:":
  244. 							if ( localizedcaptionset )
  245. 							{
  246. 								return ShowHelp( "Duplicate command line switch /L" );
  247. 							}
  248. 							localizedcaptionset = true;
  249. 							localizationstring = arg.Substring( 3 );
  250. 							string localizationpattern = "(;|^)(OK|Cancel)=[^\\\"';]+(;|$)";
  251. 							foreach ( string substring in localizationstring.Split( ";".ToCharArray( ), StringSplitOptions.RemoveEmptyEntries ) )
  252. 							{
  253. 								if ( !Regex.IsMatch( substring, localizationpattern, RegexOptions.IgnoreCase ) )
  254. 								{
  255. 									return ShowHelp( "Invalid value for /L switch: \"{1}\"", localizationstring );
  256. 								}
  257. 							}
  258. 							break;
  259. 						case "/MF":
  260. 							if ( monospaced )
  261. 							{
  262. 								return ShowHelp( "Duplicate command line switch /MF" );
  263. 							}
  264. 							monospaced = true;
  265. 							break;
  266. 						case "/NM":
  267. 							if ( !topmost )
  268. 							{
  269. 								return ShowHelp( "Duplicate command line switch /NM" );
  270. 							}
  271. 							topmost = false;
  272. 							break;
  273. 						case "/R0":
  274. 						case "/RO":
  275. 							if ( returnindex0 || returnindex1 )
  276. 							{
  277. 								return ShowHelp( "Duplicate command line switch /R0, /R1, /RI and/or /RO" );
  278. 							}
  279. 							returnindex0 = true;
  280. 							break;
  281. 						case "/R1":
  282. 						case "/RI":
  283. 							if ( returnindex0 || returnindex1 )
  284. 							{
  285. 								return ShowHelp( "Duplicate command line switch /R0, /R1, /RI and/or /RO" );
  286. 							}
  287. 							returnindex1 = true;
  288. 							break;
  289. 						case "/T:":
  290. 							if ( tablengthset )
  291. 							{
  292. 								return ShowHelp( "Duplicate command line switch /T" );
  293. 							}
  294. 							try
  295. 							{
  296. 								tablength = Convert.ToInt32( arg.Substring( 3 ) );
  297. 								if ( tablength < 4 || tablength > 16 )
  298. 								{
  299. 									return ShowHelp( "Tab length {0} outside allowed range of 4..16", arg.Substring( 3 ) );
  300. 								}
  301. 							}
  302. 							catch ( Exception e )
  303. 							{
  304. 								return ShowHelp( "Invalid tab length \"{0}\": {1}", arg.Substring( 3 ), e.Message );
  305. 							}
  306. 							tablengthset = true;
  307. 							break;
  308. 						case "/W:":
  309. 							if ( widthset )
  310. 							{
  311. 								return ShowHelp( "Duplicate command line switch /W" );
  312. 							}
  313. 							try
  314. 							{
  315. 								width = Convert.ToInt32( arg.Substring( 3 ) );
  316. 								if ( width < defaultwidth || width > Screen.PrimaryScreen.Bounds.Width )
  317. 								{
  318. 									return ShowHelp( "Width {0} outside allowed range of {1}..{2}", arg.Substring( 3 ), defaultwidth.ToString( ), Screen.PrimaryScreen.Bounds.Width.ToString( ) );
  319. 								}
  320. 							}
  321. 							catch ( Exception e )
  322. 							{
  323. 								return ShowHelp( "Invalid width \"{0}\": {1}", arg.Substring( 3 ), e.Message );
  324. 							}
  325. 							widthset = true;
  326. 							break;
  327. 						default:
  328. 							return ShowHelp( "Invalid command line switch \"{0}\"", arg );
  329. 					}
  330. 				}
  331. 			}
  332.  
  333. 			#endregion Named Arguments
  334.  
  335.  
  336. 			// Next, validate unnamed arguments
  337. 			#region Unnamed Arguments
  338.  
  339. 			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
  340. 			{
  341. 				switch ( unnamedargs.Count )
  342. 				{
  343. 					case 0:
  344. 						break;
  345. 					case 1:
  346. 						prompt = unnamedargs[0];
  347. 						break;
  348. 					case 2:
  349. 						prompt = unnamedargs[0];
  350. 						title = unnamedargs[1];
  351. 						break;
  352. 					case 3:
  353. 						return ShowHelp( "Invalid command line argument: {0}", unnamedargs[2] );
  354. 					default:
  355. 						unnamedargs.RemoveRange( 0, 2 );
  356. 						return ShowHelp( "Invalid command line arguments: {0}", String.Join( ", ", unnamedargs ) );
  357. 				}
  358. 			}
  359. 			else
  360. 			{
  361. 				switch ( unnamedargs.Count )
  362. 				{
  363. 					case 0:
  364. 						break;
  365. 					case 1:
  366. 						list = unnamedargs[0];
  367. 						listset = true;
  368. 						break;
  369. 					case 2:
  370. 						list = unnamedargs[0];
  371. 						prompt = unnamedargs[1];
  372. 						listset = true;
  373. 						break;
  374. 					case 3:
  375. 						list = unnamedargs[0];
  376. 						prompt = unnamedargs[1];
  377. 						title = unnamedargs[2];
  378. 						listset = true;
  379. 						break;
  380. 					case 4:
  381. 						return ShowHelp( "Invalid command line argument: {0}", unnamedargs[3] );
  382. 					default:
  383. 						unnamedargs.RemoveRange( 0, 3 );
  384. 						return ShowHelp( "Invalid command line arguments: {0}", String.Join( ", ", unnamedargs ) );
  385. 				}
  386. 			}
  387.  
  388. 			#endregion Unnamed Arguments
  389.  
  390.  
  391. 			// List is mandatory
  392. 			if ( !listset )
  393. 			{
  394. 				return ShowHelp( "No list specified" );
  395. 			}
  396.  
  397. 			// Validate selected index
  398. 			int listrange = list.Split( delimiter ).Length - 1;
  399. 			if ( selectedindex < 0 || selectedindex > listrange )
  400. 			{
  401. 				return ShowHelp( "Selected index ({0}) outside list range (0..{0})", selectedindex.ToString( ), listrange.ToString( ) );
  402. 			}
  403.  
  404. 			#endregion Command Line Parsing
  405.  
  406.  
  407. 			#region Set Localized Captions
  408.  
  409. 			if ( localizedcaptionset )
  410. 			{
  411. 				cancelcaption = Load( "user32.dll", 801, cancelcaption );
  412. 				okcaption = Load( "user32.dll", 800, okcaption );
  413.  
  414. 				if ( !string.IsNullOrWhiteSpace( localizationstring ) )
  415. 				{
  416. 					string[] locstrings = localizationstring.Split( ";".ToCharArray( ) );
  417. 					foreach ( string locstring in locstrings )
  418. 					{
  419. 						string key = locstring.Substring( 0, locstring.IndexOf( '=' ) );
  420. 						string val = locstring.Substring( Math.Min( locstring.IndexOf( '=' ) + 1, locstring.Length - 1 ) );
  421. 						if ( !string.IsNullOrWhiteSpace( val ) )
  422. 						{
  423. 							switch ( key.ToUpper( ) )
  424. 							{
  425. 								case "OK":
  426. 									okcaption = val;
  427. 									break;
  428. 								case "CANCEL":
  429. 									cancelcaption = val;
  430. 									break;
  431. 								default:
  432. 									return ShowHelp( "Invalid localization key \"{0}\"", key );
  433. 							}
  434. 						}
  435. 					}
  436. 				}
  437. 			}
  438.  
  439. 			#endregion Set Localized Captions
  440.  
  441.  
  442. 			#region Build Form
  443.  
  444. 			// Inspired by code by Gorkem Gencay on StackOverflow.com:
  445. 			// http://stackoverflow.com/questions/97097/what-is-the-c-sharp-version-of-vb-nets-inputdialog#17546909
  446.  
  447. 			Form dropdownForm = new Form( );
  448. 			Size size = new Size( width, height );
  449. 			dropdownForm.FormBorderStyle = FormBorderStyle.FixedDialog;
  450. 			dropdownForm.MaximizeBox = false;
  451. 			dropdownForm.MinimizeBox = false;
  452. 			dropdownForm.StartPosition = FormStartPosition.CenterParent;
  453. 			dropdownForm.ClientSize = size;
  454. 			dropdownForm.Text = title;
  455. 			dropdownForm.Icon = IconExtractor.Extract( "shell32.dll", icon, true );
  456.  
  457. 			if ( !string.IsNullOrWhiteSpace( prompt ) )
  458. 			{
  459. 				Label labelPrompt = new Label( );
  460. 				labelPrompt.Size = new Size( size.Width - 20, 20 );
  461. 				labelPrompt.Location = new Point( 10, 10 );
  462. 				// Replace tabs with spaces
  463. 				if ( prompt.IndexOf( "\\t", StringComparison.Ordinal ) > -1 )
  464. 				{
  465. 					string tab = new string( ' ', tablength );
  466. 					// First split the prompt on newlines
  467. 					string[] prompt2 = prompt.Split( new string[] { "\\n" }, StringSplitOptions.None );
  468. 					for ( int i = 0; i < prompt2.Length; i++ )
  469. 					{
  470. 						if ( prompt2[i].IndexOf( "\\t", StringComparison.Ordinal ) > -1 )
  471. 						{
  472. 							// Slit each "sub-line" of the prompt on tabs
  473. 							string[] prompt3 = prompt2[i].Split( new string[] { "\\t" }, StringSplitOptions.None );
  474. 							// Each substring before a tab gets n spaces attached, and then is cut off at the highest possible length which is a multiple of n
  475. 							for ( int j = 0; j < prompt3.Length - 1; j++ )
  476. 							{
  477. 								prompt3[j] += tab;
  478. 								int length = prompt3[j].Length;
  479. 								length /= tablength;
  480. 								length *= tablength;
  481. 								prompt3[j] = prompt3[j].Substring( 0, length );
  482. 							}
  483. 							prompt2[i] = string.Join( "", prompt3 );
  484. 						}
  485. 					}
  486. 					prompt = string.Join( "\n", prompt2 );
  487. 				}
  488. 				labelPrompt.Text = prompt.Replace( "\\n", "\n" ).Replace( "\\r", "\r" );
  489. 				if ( !heightset )
  490. 				{
  491. 					// Add 20 to window height to allow space for prompt
  492. 					size = new Size( size.Width, size.Height + 20 );
  493. 					dropdownForm.ClientSize = size;
  494. 				}
  495. 				labelPrompt.Size = new Size( size.Width - 20, size.Height - 90 );
  496. 				if ( monospaced )
  497. 				{
  498. 					labelPrompt.Font = new Font( FontFamily.GenericMonospace, labelPrompt.Font.Size );
  499. 				}
  500. 				dropdownForm.Controls.Add( labelPrompt );
  501. 			}
  502.  
  503. 			ComboBox combobox;
  504. 			combobox = new ComboBox( );
  505. 			combobox.Size = new Size( size.Width - 20, 25 );
  506. 			combobox.Location = new Point( 10, size.Height - 70 );
  507. 			combobox.AutoCompleteMode = AutoCompleteMode.Append;
  508. 			combobox.AutoCompleteSource = AutoCompleteSource.ListItems;
  509. 			combobox.DropDownStyle = ComboBoxStyle.DropDownList;
  510. 			dropdownForm.Controls.Add( combobox );
  511.  
  512. 			Button okButton = new Button( );
  513. 			okButton.DialogResult = DialogResult.OK;
  514. 			okButton.Name = "okButton";
  515. 			okButton.Size = new Size( 80, 25 );
  516. 			okButton.Text = okcaption;
  517. 			okButton.Location = new Point( size.Width / 2 - 10 - 80, size.Height - 35 );
  518. 			dropdownForm.Controls.Add( okButton );
  519.  
  520. 			Button cancelButton = new Button( );
  521. 			cancelButton.DialogResult = DialogResult.Cancel;
  522. 			cancelButton.Name = "cancelButton";
  523. 			cancelButton.Size = new Size( 80, 25 );
  524. 			cancelButton.Text = cancelcaption;
  525. 			cancelButton.Location = new Point( size.Width / 2 + 10, size.Height - 35 );
  526. 			dropdownForm.Controls.Add( cancelButton );
  527.  
  528. 			dropdownForm.AcceptButton = okButton;  // OK on Enter
  529. 			dropdownForm.CancelButton = cancelButton; // Cancel on Esc
  530. 			dropdownForm.Activate( );
  531.  
  532. 			#endregion Build Form
  533.  
  534.  
  535. 			#region Populate List
  536.  
  537. 			// Populate the dropdown list
  538. 			List<string> listitems = list.Split( delimiter ).ToList<string>( );
  539. 			if ( skipfirstitem )
  540. 			{
  541. 				listitems.RemoveAt( 0 );
  542. 			}
  543. 			if ( sortlist )
  544. 			{
  545. 				listitems.Sort( );
  546. 			}
  547. 			foreach ( string item in listitems )
  548. 			{
  549. 				combobox.Items.Add( item );
  550. 			}
  551. 			// Preselect an item
  552. 			combobox.SelectedIndex = selectedindex;
  553.  
  554. 			#endregion Populate List
  555.  
  556.  
  557. 			dropdownForm.TopMost = topmost;
  558. 			DialogResult result = dropdownForm.ShowDialog( );
  559. 			if ( result == DialogResult.OK )
  560. 			{
  561. 				selectedText = combobox.SelectedItem.ToString( );
  562. 				Console.WriteLine( selectedText );
  563. 				if ( returnindex0 )
  564. 				{
  565. 					// With /RO: return code equals selected index for "OK", or -1 for (command line) errors or "Cancel".
  566. 					return combobox.SelectedIndex;
  567. 				}
  568. 				else if ( returnindex1 )
  569. 				{
  570. 					// With /RI: return code equals selected index + 1 for "OK", or 0 for (command line) errors or "Cancel".
  571. 					return combobox.SelectedIndex + 1;
  572. 				}
  573. 				else
  574. 				{
  575. 					// Default: return code 0 for "OK", 1 for (command line) errors, 2 for "Cancel".
  576. 					return 0;
  577. 				}
  578. 			}
  579. 			else
  580. 			{
  581. 				// Cancelled
  582. 				if ( returnindex0 )
  583. 				{
  584. 					// With /RO: return code equals selected index for "OK", or -1 for (command line) errors or "Cancel".
  585. 					return -1;
  586. 				}
  587. 				else if ( returnindex1 )
  588. 				{
  589. 					// With /RI: return code equals selected index + 1 for "OK", or 0 for (command line) errors or "Cancel".
  590. 					return 0;
  591. 				}
  592. 				else
  593. 				{
  594. 					// Default: return code 0 for "OK", 1 for (command line) errors, 2 for "Cancel".
  595. 					return 2;
  596. 				}
  597. 			}
  598. 		}
  599.  
  600.  
  601. 		#region Error handling
  602.  
  603. 		public static int ShowHelp( params string[] errmsg )
  604. 		{
  605. 			#region Help Text
  606.  
  607. 			/*
  608. 			DropDownBox,  Version 1.15
  609. 			Batch tool to present a DropDown dialog and return the selected item
  610.  
  611. 			Usage:    DROPDOWNBOX     "list"  [ "prompt"  [ "title" ] ]  [ options ]
  612.  
  613. 			   or:    DROPDOWNBOX     /F:"listfile"  [ "prompt"  [ "title" ] ]  [ options ]
  614.  
  615. 			   or:    listcommand  |  DROPDOWNBOX  [ "prompt"  [ "title" ] ]  [ options ]
  616.  
  617. 			Where:    "list"          is the list of items to populate the dropdown control
  618. 			          "listcommand"   is a command whose standard output is used as a list
  619. 			                          of items to populate the dropdown control
  620. 			          "prompt"        is the optional text above the dropdown control
  621. 			                          (default: none)
  622. 			          "title"         is the window title
  623. 			                          (default: "DropDownBox,  Version 1.10")
  624.  
  625. 			Options:  /C:index        use iCon at index from shell32.dll (default: 23)
  626. 			          /D:"delimiter"  sets the Delimiter character for "list"
  627. 			                          (default: semicolon)
  628. 			          /F:"listfile"   use list from text File (one list item per line)
  629. 			          /H:height       sets the Height of the input box
  630. 			                          (default: 90; minimum: 90; maximum: screen height)
  631. 			          /I:index        sets the zero based Index of the preselected item
  632. 			                          (default: 0)
  633. 			          /K              sKip first item of list (e.g. a header line)
  634. 			          /L[:"captions"] Localize or customize button captions
  635. 			                          (e.g. /L:"OK=Why Not?;Cancel=No Way!")
  636. 			          /MF             use Monospaced Font in prompt (default: proportional)
  637. 			          /NM             make dialog Non-Modal (default: Modal, i.e. on top)
  638. 			          /RI or /R1      Return code equals selected Index + 1, or 0 on
  639. 			                          (command line) errors or if "Cancel" was clicked
  640. 			                          (default: 0 on "OK", 1 on error, 2 on "Cancel")
  641. 			          /RO or /R0      Return code equals selected 0-based index, or -1 on
  642. 			                          (command line) errors or if "Cancel" was clicked
  643. 			                          (default: 0 on "OK", 1 on error, 2 on "Cancel")
  644. 			          /S              Sort list (default: unsorted)
  645. 			          /T:tablength    sets the number of spaces for Tabs in prompt
  646. 			                          (4..16; default: 4)
  647. 			          /W:width        sets the Width of the input box
  648. 			                          (default: 200; minimum: 200; maximum: screen width)
  649.  
  650. 			Notes:    The selected item text is written to Standard Out if "OK" is clicked,
  651. 			          otherwise an empty string is returned.
  652. 			          Use either "list" or /F:"listfile" or "listcommand".
  653. 			          Linefeeds (\n), tabs (\t) and doublequotes (\") are allowed in the
  654. 			          prompt text (but not in the title); with tabs, /MF is recommended.
  655. 			          If specified without captions, switch /L forces localized button
  656. 			          captions (e.g. "Cancel" button caption is "Annuleren" on Dutch
  657. 			          systems); if only a single custom caption is specified, the other
  658. 			          one is localized (e.g. with /L:"OK=Gaan" on Dutch systems, "OK"
  659. 			          button caption is "Gaan", "Cancel" button caption is "Annuleren").
  660. 			          Return code 0 for "OK", 1 for (command line) errors, 2 for "Cancel".
  661. 			          With /RI return code equals selected index + 1, or 0 for "Cancel".
  662. 			          With /RO return code equals selected index or -1 for "Cancel".
  663. 			          Command line switches /RI and /RO are mutually exclusive.
  664.  
  665. 			Credits:  On-the-fly form based on code by Gorkem Gencay on StackOverflow:
  666. 			          http://stackoverflow.com/questions/97097#17546909
  667. 			          Code to retrieve localized button captions by Martin Stoeckli:
  668. 			          http://martinstoeckli.ch/csharp/csharp.html#windows_text_resources
  669. 			          Code to extract icons from Shell32.dll by Thomas Levesque:
  670. 			          http://stackoverflow.com/questions/6873026
  671.  
  672. 			Written by Rob van der Woude
  673. 			http://www.robvanderwoude.com
  674. 			*/
  675.  
  676. 			#endregion Help Text
  677.  
  678.  
  679. 			#region Error Message
  680.  
  681. 			if ( errmsg.Length > 0 )
  682. 			{
  683. 				List<string> errargs = new List<string>( errmsg );
  684. 				errargs.RemoveAt( 0 );
  685. 				Console.Error.WriteLine( );
  686. 				Console.ForegroundColor = ConsoleColor.Red;
  687. 				Console.Error.Write( "ERROR:\t" );
  688. 				Console.ForegroundColor = ConsoleColor.White;
  689. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  690. 				Console.ResetColor( );
  691. 			}
  692.  
  693. 			#endregion Error Message
  694.  
  695.  
  696. 			#region Show Help Text
  697.  
  698. 			Console.Error.WriteLine( );
  699.  
  700. 			Console.Error.WriteLine( "DropDownBox,  Version {0}", progver );
  701.  
  702. 			Console.Error.WriteLine( "Batch tool to present a DropDown dialog and return the selected item" );
  703.  
  704. 			Console.Error.WriteLine( );
  705.  
  706. 			Console.Error.Write( "Usage:    " );
  707. 			Console.ForegroundColor = ConsoleColor.White;
  708. 			Console.Error.WriteLine( "DROPDOWNBOX     \"list\"  [ \"prompt\"  [ \"title\" ] ]  [ options ]" );
  709. 			Console.ResetColor( );
  710.  
  711. 			Console.Error.WriteLine( );
  712.  
  713. 			Console.Error.Write( "   or:    " );
  714. 			Console.ForegroundColor = ConsoleColor.White;
  715. 			Console.Error.WriteLine( "DROPDOWNBOX     /F:\"listfile\"  [ \"prompt\"  [ \"title\" ] ]  [ options ]" );
  716. 			Console.ResetColor( );
  717.  
  718. 			Console.Error.WriteLine( );
  719.  
  720. 			Console.Error.Write( "   or:    " );
  721. 			Console.ForegroundColor = ConsoleColor.White;
  722. 			Console.Error.WriteLine( "listcommand  |  DROPDOWNBOX  [ \"prompt\"  [ \"title\" ] ]  [ options ]" );
  723. 			Console.ResetColor( );
  724.  
  725. 			Console.Error.WriteLine( );
  726.  
  727. 			Console.Error.Write( "Where:    " );
  728. 			Console.ForegroundColor = ConsoleColor.White;
  729. 			Console.Error.Write( "\"list\"" );
  730. 			Console.ResetColor( );
  731. 			Console.Error.WriteLine( "          is the list of items to populate the dropdown control" );
  732.  
  733. 			Console.ForegroundColor = ConsoleColor.White;
  734. 			Console.Error.Write( "          \"listcommand\"" );
  735. 			Console.ResetColor( );
  736. 			Console.Error.Write( "   is a " );
  737. 			Console.ForegroundColor = ConsoleColor.White;
  738. 			Console.Error.Write( "command" );
  739. 			Console.ResetColor( );
  740. 			Console.Error.Write( " whose standard output is used as a " );
  741. 			Console.ForegroundColor = ConsoleColor.White;
  742. 			Console.Error.WriteLine( "list" );
  743. 			Console.ResetColor( );
  744.  
  745. 			Console.Error.WriteLine( "                          of items to populate the dropdown control" );
  746.  
  747. 			Console.ForegroundColor = ConsoleColor.White;
  748. 			Console.Error.Write( "          \"prompt\"" );
  749. 			Console.ResetColor( );
  750. 			Console.Error.WriteLine( "        is the optional text above the dropdown control" );
  751.  
  752. 			Console.Error.WriteLine( "                          (default: none)" );
  753.  
  754. 			Console.ForegroundColor = ConsoleColor.White;
  755. 			Console.Error.Write( "          \"title\"" );
  756. 			Console.ResetColor( );
  757. 			Console.Error.WriteLine( "         is the window title" );
  758.  
  759. 			Console.Error.WriteLine( "                          (default: \"DropDownBox,  Version {0}\")", progver );
  760.  
  761. 			Console.Error.WriteLine( );
  762.  
  763. 			Console.Error.Write( "Options:  " );
  764. 			Console.ForegroundColor = ConsoleColor.White;
  765. 			Console.Error.Write( "/C:index" );
  766. 			Console.ResetColor( );
  767. 			Console.Error.Write( "        use i" );
  768. 			Console.ForegroundColor = ConsoleColor.White;
  769. 			Console.Error.Write( "C" );
  770. 			Console.ResetColor( );
  771. 			Console.Error.Write( "on at " );
  772. 			Console.ForegroundColor = ConsoleColor.White;
  773. 			Console.Error.Write( "index" );
  774. 			Console.ResetColor( );
  775. 			Console.Error.WriteLine( " from shell32.dll (default: 23)" );
  776.  
  777. 			Console.ForegroundColor = ConsoleColor.White;
  778. 			Console.Error.Write( "          /D:\"delimiter\"" );
  779. 			Console.ResetColor( );
  780. 			Console.Error.Write( "  sets the " );
  781. 			Console.ForegroundColor = ConsoleColor.White;
  782. 			Console.Error.Write( "D" );
  783. 			Console.ResetColor( );
  784. 			Console.Error.Write( "elimiter character for " );
  785. 			Console.ForegroundColor = ConsoleColor.White;
  786. 			Console.Error.WriteLine( "\"list\"" );
  787. 			Console.ResetColor( );
  788.  
  789. 			Console.Error.WriteLine( "                          (default: semicolon)" );
  790.  
  791. 			Console.ForegroundColor = ConsoleColor.White;
  792. 			Console.Error.Write( "          /F:\"listfile\"" );
  793. 			Console.ResetColor( );
  794. 			Console.Error.Write( "   use list from text " );
  795. 			Console.ForegroundColor = ConsoleColor.White;
  796. 			Console.Error.Write( "F" );
  797. 			Console.ResetColor( );
  798. 			Console.Error.WriteLine( "ile (one list item per line)" );
  799.  
  800. 			Console.ForegroundColor = ConsoleColor.White;
  801. 			Console.Error.Write( "          /H:height" );
  802. 			Console.ResetColor( );
  803. 			Console.Error.Write( "       sets the " );
  804. 			Console.ForegroundColor = ConsoleColor.White;
  805. 			Console.Error.Write( "H" );
  806. 			Console.ResetColor( );
  807. 			Console.Error.WriteLine( "eight of the input box" );
  808.  
  809. 			Console.Error.WriteLine( "                          (default: 90; minimum: 90; maximum: screen height)" );
  810.  
  811. 			Console.ForegroundColor = ConsoleColor.White;
  812. 			Console.Error.Write( "          /I:index" );
  813. 			Console.ResetColor( );
  814. 			Console.Error.Write( "        sets the zero based " );
  815. 			Console.ForegroundColor = ConsoleColor.White;
  816. 			Console.Error.Write( "I" );
  817. 			Console.ResetColor( );
  818. 			Console.Error.WriteLine( "ndex of the preselected item" );
  819.  
  820. 			Console.Error.WriteLine( "                          (default: 0)" );
  821.  
  822. 			Console.ForegroundColor = ConsoleColor.White;
  823. 			Console.Error.Write( "          /K" );
  824. 			Console.ResetColor( );
  825. 			Console.Error.Write( "              s" );
  826. 			Console.ForegroundColor = ConsoleColor.White;
  827. 			Console.Error.Write( "K" );
  828. 			Console.ResetColor( );
  829. 			Console.Error.WriteLine( "ip first item of list (e.g. a header line)" );
  830.  
  831. 			Console.ForegroundColor = ConsoleColor.White;
  832. 			Console.Error.Write( "          /L[:\"captions\"] L" );
  833. 			Console.ResetColor( );
  834. 			Console.Error.Write( "ocalize or customize button " );
  835. 			Console.ForegroundColor = ConsoleColor.White;
  836. 			Console.Error.WriteLine( "captions" );
  837. 			Console.ResetColor( );
  838.  
  839. 			Console.Error.Write( "                          (e.g. " );
  840. 			Console.ForegroundColor = ConsoleColor.White;
  841. 			Console.Error.Write( "/L:\"OK=Why Not?;Cancel=No Way!\"" );
  842. 			Console.ResetColor( );
  843. 			Console.Error.WriteLine( ")" );
  844.  
  845. 			Console.ForegroundColor = ConsoleColor.White;
  846. 			Console.Error.Write( "          /MF" );
  847. 			Console.ResetColor( );
  848. 			Console.Error.Write( "             use " );
  849. 			Console.ForegroundColor = ConsoleColor.White;
  850. 			Console.Error.Write( "M" );
  851. 			Console.ResetColor( );
  852. 			Console.Error.Write( "onospaced " );
  853. 			Console.ForegroundColor = ConsoleColor.White;
  854. 			Console.Error.Write( "F" );
  855. 			Console.ResetColor( );
  856. 			Console.Error.Write( "ont in " );
  857. 			Console.ForegroundColor = ConsoleColor.White;
  858. 			Console.Error.Write( "prompt" );
  859. 			Console.ResetColor( );
  860. 			Console.Error.WriteLine( " (default: proportional)" );
  861.  
  862. 			Console.ForegroundColor = ConsoleColor.White;
  863. 			Console.Error.Write( "          /NM" );
  864. 			Console.ResetColor( );
  865. 			Console.Error.Write( "             make dialog " );
  866. 			Console.ForegroundColor = ConsoleColor.White;
  867. 			Console.Error.Write( "N" );
  868. 			Console.ResetColor( );
  869. 			Console.Error.Write( "on-" );
  870. 			Console.ForegroundColor = ConsoleColor.White;
  871. 			Console.Error.Write( "M" );
  872. 			Console.ResetColor( );
  873. 			Console.Error.WriteLine( "odal (default: modal, i.e. on top)" );
  874.  
  875. 			Console.ForegroundColor = ConsoleColor.White;
  876. 			Console.Error.Write( "          /RI" );
  877. 			Console.ResetColor( );
  878. 			Console.Error.Write( " or " );
  879. 			Console.ForegroundColor = ConsoleColor.White;
  880. 			Console.Error.Write( "/R1      R" );
  881. 			Console.ResetColor( );
  882. 			Console.Error.Write( "eturn code equals selected " );
  883. 			Console.ForegroundColor = ConsoleColor.White;
  884. 			Console.Error.Write( "I" );
  885. 			Console.ResetColor( );
  886. 			Console.Error.WriteLine( "ndex + 1, or 0 on" );
  887.  
  888. 			Console.Error.WriteLine( "                          (command line) errors or if \"Cancel\" was clicked" );
  889.  
  890. 			Console.Error.WriteLine( "                          (default: 0 on \"OK\", 1 on error, 2 on \"Cancel\")" );
  891.  
  892. 			Console.ForegroundColor = ConsoleColor.White;
  893. 			Console.Error.Write( "          /RO" );
  894. 			Console.ResetColor( );
  895. 			Console.Error.Write( " or " );
  896. 			Console.ForegroundColor = ConsoleColor.White;
  897. 			Console.Error.Write( "/R0      R" );
  898. 			Console.ResetColor( );
  899. 			Console.Error.Write( "eturn code equals selected " );
  900. 			Console.ForegroundColor = ConsoleColor.White;
  901. 			Console.Error.Write( "0" );
  902. 			Console.ResetColor( );
  903. 			Console.Error.WriteLine( "-based index, or -1 on" );
  904.  
  905. 			Console.Error.WriteLine( "                          (command line) errors or if \"Cancel\" was clicked" );
  906.  
  907. 			Console.Error.WriteLine( "                          (default: 0 on \"OK\", 1 on error, 2 on \"Cancel\")" );
  908.  
  909. 			Console.ForegroundColor = ConsoleColor.White;
  910. 			Console.Error.Write( "          /S              S" );
  911. 			Console.ResetColor( );
  912. 			Console.Error.WriteLine( "ort list (default: unsorted)" );
  913.  
  914. 			Console.ForegroundColor = ConsoleColor.White;
  915. 			Console.Error.Write( "          /T:tablength" );
  916. 			Console.ResetColor( );
  917. 			Console.Error.Write( "    sets the number of spaces for " );
  918. 			Console.ForegroundColor = ConsoleColor.White;
  919. 			Console.Error.Write( "T" );
  920. 			Console.ResetColor( );
  921. 			Console.Error.Write( "abs in " );
  922. 			Console.ForegroundColor = ConsoleColor.White;
  923. 			Console.Error.WriteLine( "prompt" );
  924. 			Console.ResetColor( );
  925.  
  926. 			Console.Error.WriteLine( "                          (4..16; default: 4)" );
  927.  
  928. 			Console.ForegroundColor = ConsoleColor.White;
  929. 			Console.Error.Write( "          /W:width" );
  930. 			Console.ResetColor( );
  931. 			Console.Error.Write( "        sets the " );
  932. 			Console.ForegroundColor = ConsoleColor.White;
  933. 			Console.Error.Write( "W" );
  934. 			Console.ResetColor( );
  935. 			Console.Error.WriteLine( "idth of the input box" );
  936.  
  937. 			Console.Error.WriteLine( "                          (default: 200; minimum: 200; maximum: screen width)" );
  938.  
  939. 			Console.Error.WriteLine( );
  940.  
  941. 			Console.Error.WriteLine( "Notes:    The selected item text is written to Standard Out if \"OK\" is clicked," );
  942.  
  943. 			Console.Error.WriteLine( "          otherwise an empty string is returned." );
  944.  
  945. 			Console.Error.Write( "          Use either " );
  946. 			Console.ForegroundColor = ConsoleColor.White;
  947. 			Console.Error.Write( "\"list\"" );
  948. 			Console.ResetColor( );
  949. 			Console.Error.Write( " or " );
  950. 			Console.ForegroundColor = ConsoleColor.White;
  951. 			Console.Error.Write( "/F:\"listfile\"" );
  952. 			Console.ResetColor( );
  953. 			Console.Error.Write( " or " );
  954. 			Console.ForegroundColor = ConsoleColor.White;
  955. 			Console.Error.Write( "\"listcommand\"" );
  956. 			Console.ResetColor( );
  957. 			Console.Error.WriteLine( "." );
  958.  
  959. 			Console.Error.WriteLine( "          Linefeeds (\\n), tabs (\\t) and doublequotes (\\\") are allowed in the" );
  960.  
  961. 			Console.ForegroundColor = ConsoleColor.White;
  962. 			Console.Error.Write( "          prompt" );
  963. 			Console.ResetColor( );
  964. 			Console.Error.Write( " text (but not in the " );
  965. 			Console.ForegroundColor = ConsoleColor.White;
  966. 			Console.Error.Write( "title" );
  967. 			Console.ResetColor( );
  968. 			Console.Error.Write( "); with tabs, " );
  969. 			Console.ForegroundColor = ConsoleColor.White;
  970. 			Console.Error.Write( "/MF" );
  971. 			Console.ResetColor( );
  972. 			Console.Error.WriteLine( " is recommended." );
  973.  
  974. 			Console.Error.Write( "          If specified without " );
  975. 			Console.ForegroundColor = ConsoleColor.White;
  976. 			Console.Error.Write( "captions" );
  977. 			Console.ResetColor( );
  978. 			Console.Error.Write( ", switch " );
  979. 			Console.ForegroundColor = ConsoleColor.White;
  980. 			Console.Error.Write( "/L" );
  981. 			Console.ResetColor( );
  982. 			Console.Error.WriteLine( " forces localized button" );
  983.  
  984. 			Console.Error.WriteLine( "          captions (e.g. \"Cancel\" button caption is \"Annuleren\" on Dutch" );
  985.  
  986. 			Console.Error.WriteLine( "          systems); if only a single custom caption is specified, the other" );
  987.  
  988. 			Console.Error.Write( "          one is localized (e.g. with " );
  989. 			Console.ForegroundColor = ConsoleColor.White;
  990. 			Console.Error.Write( "/L:\"OK=Gaan\"" );
  991. 			Console.ResetColor( );
  992. 			Console.Error.WriteLine( " on Dutch systems, \"OK\"" );
  993.  
  994. 			Console.Error.WriteLine( "          button caption is \"Gaan\", \"Cancel\" button caption is \"Annuleren\")." );
  995.  
  996. 			Console.Error.WriteLine( "          Return code 0 for \"OK\", 1 for (command line) errors, 2 for \"Cancel\"." );
  997.  
  998. 			Console.Error.Write( "          With " );
  999. 			Console.ForegroundColor = ConsoleColor.White;
  1000. 			Console.Error.Write( "/RI" );
  1001. 			Console.ResetColor( );
  1002. 			Console.Error.WriteLine( " return code equals selected index + 1, or 0 for \"Cancel\"." );
  1003.  
  1004. 			Console.Error.Write( "          With " );
  1005. 			Console.ForegroundColor = ConsoleColor.White;
  1006. 			Console.Error.Write( "/RO" );
  1007. 			Console.ResetColor( );
  1008. 			Console.Error.WriteLine( " return code equals selected index, or -1 for \"Cancel\"." );
  1009.  
  1010. 			Console.Error.Write( "          Command line switches " );
  1011. 			Console.ForegroundColor = ConsoleColor.White;
  1012. 			Console.Error.Write( "/RI" );
  1013. 			Console.ResetColor( );
  1014. 			Console.Error.Write( " and " );
  1015. 			Console.ForegroundColor = ConsoleColor.White;
  1016. 			Console.Error.Write( "/RO" );
  1017. 			Console.ResetColor( );
  1018. 			Console.Error.WriteLine( " are mutually exclusive." );
  1019.  
  1020. 			Console.Error.WriteLine( );
  1021.  
  1022. 			Console.Error.WriteLine( "Credits:  On-the-fly form based on code by Gorkem Gencay on StackOverflow:" );
  1023.  
  1024. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  1025. 			Console.Error.WriteLine( "          http://stackoverflow.com/questions/17546909" );
  1026. 			Console.ResetColor( );
  1027.  
  1028. 			Console.Error.WriteLine( "          Code to retrieve localized button captions by Martin Stoeckli:" );
  1029.  
  1030. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  1031. 			Console.Error.WriteLine( "          http://martinstoeckli.ch/csharp/csharp.html#windows_text_resources" );
  1032. 			Console.ResetColor( );
  1033.  
  1034. 			Console.Error.WriteLine( "          Code to extract icons from Shell32.dll by Thomas Levesque:" );
  1035.  
  1036. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  1037. 			Console.Error.WriteLine( "          http://stackoverflow.com/questions/6873026" );
  1038. 			Console.ResetColor( );
  1039.  
  1040. 			Console.Error.WriteLine( );
  1041.  
  1042. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  1043.  
  1044. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  1045.  
  1046. 			#endregion Show Help Text
  1047.  
  1048.  
  1049. 			if ( returnindex0 )
  1050. 			{
  1051. 				// With /RO: return code equals selected index for "OK", or -1 for (command line) errors or "Cancel".
  1052. 				return -1;
  1053. 			}
  1054. 			else if ( returnindex1 )
  1055. 			{
  1056. 				// With /RI: return code equals selected index + 1 for "OK", or 0 for (command line) errors or "Cancel".
  1057. 				return 0;
  1058. 			}
  1059. 			else
  1060. 			{
  1061. 				// Default: return code 0 for "OK", 1 for (command line) errors, 2 for "Cancel".
  1062. 				return 1;
  1063. 			}
  1064. 		}
  1065.  
  1066. 		#endregion Error handling
  1067.  
  1068.  
  1069. 		#region Get Localized Captions
  1070.  
  1071. 		// Code to retrieve localized captions by Martin Stoeckli
  1072. 		// http://martinstoeckli.ch/csharp/csharp.html#windows_text_resources
  1073.  
  1074. 		/// <summary>
  1075. 		/// Searches for a text resource in a Windows library.
  1076. 		/// Sometimes, using the existing Windows resources, you can make your code
  1077. 		/// language independent and you don't have to care about translation problems.
  1078. 		/// </summary>
  1079. 		/// <example>
  1080. 		///   btnCancel.Text = Load("user32.dll", 801, "Cancel");
  1081. 		///   btnYes.Text = Load("user32.dll", 805, "Yes");
  1082. 		/// </example>
  1083. 		/// <param name="libraryName">Name of the windows library like "user32.dll"
  1084. 		/// or "shell32.dll"</param>
  1085. 		/// <param name="ident">Id of the string resource.</param>
  1086. 		/// <param name="defaultText">Return this text, if the resource string could
  1087. 		/// not be found.</param>
  1088. 		/// <returns>Requested string if the resource was found,
  1089. 		/// otherwise the <paramref name="defaultText"/></returns>
  1090. 		public static string Load( string libraryName, UInt32 ident, string defaultText )
  1091. 		{
  1092. 			IntPtr libraryHandle = GetModuleHandle( libraryName );
  1093. 			if ( libraryHandle != IntPtr.Zero )
  1094. 			{
  1095. 				StringBuilder sb = new StringBuilder( 1024 );
  1096. 				int size = LoadString( libraryHandle, ident, sb, 1024 );
  1097. 				if ( size > 0 )
  1098. 					return sb.ToString( );
  1099. 			}
  1100. 			return defaultText;
  1101. 		}
  1102.  
  1103. 		[DllImport( "kernel32.dll", CharSet = CharSet.Auto )]
  1104. 		private static extern IntPtr GetModuleHandle( string lpModuleName );
  1105.  
  1106. 		[DllImport( "user32.dll", CharSet = CharSet.Auto )]
  1107. 		private static extern int LoadString( IntPtr hInstance, UInt32 uID, StringBuilder lpBuffer, Int32 nBufferMax );
  1108.  
  1109. 		#endregion Get Localized Captions
  1110.  
  1111.  
  1112. 		#region Extract Icons
  1113.  
  1114. 		// Code to extract icons from Shell32.dll by Thomas Levesque
  1115. 		// http://stackoverflow.com/questions/6873026
  1116.  
  1117. 		public class IconExtractor
  1118. 		{
  1119.  
  1120. 			public static Icon Extract( string file, int number, bool largeIcon )
  1121. 			{
  1122. 				IntPtr large;
  1123. 				IntPtr small;
  1124. 				ExtractIconEx( file, number, out large, out small, 1 );
  1125. 				try
  1126. 				{
  1127. 					return Icon.FromHandle( largeIcon ? large : small );
  1128. 				}
  1129. 				catch
  1130. 				{
  1131. 					return null;
  1132. 				}
  1133.  
  1134. 			}
  1135.  
  1136. 			[DllImport( "Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall )]
  1137. 			private static extern int ExtractIconEx( string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons );
  1138. 		}
  1139.  
  1140. 		#endregion Extract Icons
  1141. 	}
  1142. }
  1143.  

page last uploaded: 2021-01-27, 16:12