(view source code of multiplechoicebox.cs as plain text)
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace RobvanderWoude
{
class MultipleChoiceBox
{
public static string progver = "1.00";
#region Global Variables
public const int defaultwindowheight = 320;
public const int defaultwindowwidth = 480;
public const int minimumwindowheight = 90;
public const int minimumwindowwidth = 200;
public static int screenheight = Screen.PrimaryScreen.WorkingArea.Height;
public static int screenwidth = Screen.PrimaryScreen.WorkingArea.Width;
public static int maximumwindowheight = screenheight;
public static int maximumwindowwidth = screenwidth;
public static int borderX = 0;
public static int borderY = 0;
#endregion Global Variables
[STAThread]
static int Main( string[] args )
{
#region Initialize Variables
char delimiter = ';';
List<string> namedargs = new List<string>( );
List<string> unnamedargs = new List<string>( );
string file = String.Empty;
string list = String.Empty;
string cancelcaption = "&Cancel";
string okcaption = "&OK";
string localizationstring = String.Empty;
string prompt = String.Empty;
string selectedtext = String.Empty;
string title = String.Format( "MultioleChoiceBox, Version {0}", progver );
bool deduplist = false;
bool delimiterset = false;
bool heightset = false;
bool iconset = false;
bool indexset = false;
bool localizedcaptionset = false;
bool monospaced = false;
bool skipfirstitem = false;
bool sortlist = false;
bool tablengthset = false;
bool topmost = true;
bool widthset = false;
double cbsafetyfactor = 1.05;
int columns = 0;
int defaultitems = 0;
int icon = 23;
int promptheight = 20;
int rc = 0;
int rows = 0;
int tablength = 4;
int windowheight = defaultwindowheight;
int windowwidth = defaultwindowwidth;
Label labelPrompt = new Label( );
bool isredirected = Console.IsInputRedirected; // Requires .NET Framework 4.5
bool listset = isredirected;
int redirectnum = ( isredirected ? 1 : 0 );
int arguments = args.Length + redirectnum;
int[] borders = BorderDimensions( );
borderX = borders[0];
borderY = borders[1];
maximumwindowheight = screenheight - borderY;
maximumwindowwidth = screenwidth - borderX;
#endregion Initialize Variables
#region Command Line Parsing
if ( arguments == 0 )
{
return ShowHelp( );
}
if ( arguments > 16 )
{
return ShowHelp( "Too many command line arguments" );
}
// Split up named and unnamed arguments
foreach ( string arg in args )
{
if ( arg[0] == '/' )
{
namedargs.Add( arg );
}
else
{
unnamedargs.Add( arg );
}
}
// Read Standard Input if the list is redirected
if ( isredirected )
{
try
{
string delim = delimiter.ToString( );
list = String.Join( delim, Console.In.ReadToEnd( ).Split( "\n\r".ToCharArray( ), StringSplitOptions.RemoveEmptyEntries ) );
// Trim list items, remove empty ones
string pattern = "\\s*" + delim + "+\\s*";
list = Regex.Replace( list, pattern, delim );
}
catch ( Exception e )
{
return ShowHelp( e.Message );
}
}
// First, validate the named arguments
#region Named Arguments
foreach ( string arg in namedargs )
{
if ( arg.Length > 1 && !arg.Contains( ":" ) && !arg.Contains( "=" ) )
{
#region Boolean Named Arguments
string key = arg.ToUpper( );
switch ( key )
{
case "/?":
case "/HELP":
return ShowHelp( );
case "/??":
case "/???":
case "/A":
case "/ALIAS":
case "/ALIASES":
return ShowAliases( );
case "/DE":
case "/DEDUP":
if ( deduplist )
{
return ShowHelp( "Duplicate command line switch /DE" );
}
deduplist = true;
break;
case "/K":
case "/SKIP":
case "/SKIPFIRST":
case "/SKIPFIRSTITEM":
if ( skipfirstitem )
{
return ShowHelp( "Duplicate command line switch /K" );
}
skipfirstitem = true;
break;
case "/L":
case "/LOCALIZED":
case "/LOCALIZEDCAPTIONS":
if ( localizedcaptionset )
{
return ShowHelp( "Duplicate command line switch /L" );
}
localizedcaptionset = true;
break;
case "/MF":
case "/MONO":
case "/MONOSPACED":
case "/MONOSPACEDFONT":
if ( monospaced )
{
return ShowHelp( "Duplicate command line switch /MF" );
}
monospaced = true;
break;
case "/NM":
case "/NONMODAL":
case "/NON-MODAL":
if ( !topmost )
{
return ShowHelp( "Duplicate command line switch /NM" );
}
topmost = false;
break;
case "/S":
case "/SORT":
case "/SORTLIST":
if ( sortlist )
{
return ShowHelp( "Duplicate command line switch /S" );
}
sortlist = true;
break;
default:
return ShowHelp( "Invalid command line switch {0} or missing value", arg );
}
#endregion Boolean Named Arguments
}
else if ( arg.Length > 3 && ( arg.Contains( ":" ) || arg.Contains( "=" ) ) )
{
#region Key/Value Named Arguments
string key = arg.ToUpper( ).Substring( 0, arg.IndexOfAny( ":=".ToCharArray( ) ) );
string val = arg.Substring( arg.IndexOfAny( ":=".ToCharArray( ) ) + 1 );
switch ( key )
{
case "/C":
case "/COL":
case "/COLS":
case "/COLUMNS":
if ( columns != 0 )
{
return ShowHelp( "Duplicate command line switch /C" );
}
try
{
columns = Convert.ToInt32( val );
if ( columns < 0 )
{
return ShowHelp( "Columns must be a positive integer" );
}
}
catch ( Exception )
{
return ShowHelp( "Invalid columns value \"{0}\"", arg );
}
break;
case "/D":
case "/DELIMITER":
if ( delimiterset )
{
return ShowHelp( "Duplicate command line switch /D" );
}
if ( val.Length == 1 )
{
delimiter = val[0];
}
else if ( val.Length == 3 && ( ( val[0] == '"' && val[2] == '"' ) || ( val[0] == '\'' && val[2] == '\'' ) ) )
{
delimiter = val[1];
}
else
{
return ShowHelp( String.Format( "Invalid delimiter specified \"{0}\"", arg ) );
}
break;
case "/F":
case "/FILE":
if ( listset )
{
return ShowHelp( "Duplicate command line switch /F" );
}
file = val;
if ( String.IsNullOrEmpty( file ) || !File.Exists( file ) )
{
return ShowHelp( "List file not found: \"{0}\"", file );
}
else
{
try
{
string delim = delimiter.ToString( );
list = String.Join( delim, File.ReadLines( file ) );
string pattern = delim + "{2,}";
// Remove empty list items
Regex.Replace( list, pattern, delim );
}
catch ( Exception e )
{
return ShowHelp( e.Message );
}
}
listset = true;
break;
case "/H":
case "/HEIGHT":
if ( heightset )
{
return ShowHelp( "Duplicate command line switch /H" );
}
try
{
windowheight = Convert.ToInt32( val );
if ( windowheight < minimumwindowheight || windowheight > maximumwindowheight )
{
return ShowHelp( String.Format( "Height {0} outside allowed range of {1}..{2}", val, minimumwindowheight, maximumwindowheight ) );
}
}
catch ( Exception e )
{
return ShowHelp( String.Format( "Invalid height \"{0}\": {1}", val, e.Message ) );
}
heightset = true;
break;
case "/I":
case "/ICON":
if ( iconset )
{
return ShowHelp( "Duplicate command line switch /I" );
}
try
{
icon = Convert.ToInt32( val );
}
catch ( Exception )
{
return ShowHelp( "Invalid icon index: {0}", val );
}
iconset = true;
break;
case "/L":
case "/LOCALIZED":
case "/LOCALIZEDCAPTIONS":
if ( localizedcaptionset )
{
return ShowHelp( "Duplicate command line switch /L" );
}
localizedcaptionset = true;
localizationstring = val;
string localizationpattern = "(;|^)(OK|Cancel)=[^\\\"';]+(;|$)";
foreach ( string substring in localizationstring.Split( ";".ToCharArray( ), StringSplitOptions.RemoveEmptyEntries ) )
{
if ( !Regex.IsMatch( substring, localizationpattern, RegexOptions.IgnoreCase ) )
{
return ShowHelp( "Invalid value for /L switch: \"{1}\"", localizationstring );
}
}
break;
case "/P":
case "/DEFAULT":
case "/DEFAULTITEMS":
case "/PRE":
case "/PRESELECTED":
case "/PRESELECTEDITEMS":
if ( indexset )
{
return ShowHelp( "Duplicate command line switch /P" );
}
try
{
defaultitems = Convert.ToInt32( val );
}
catch ( Exception e )
{
return ShowHelp( String.Format( "Invalid preselected items value \"{0}\": {1}", arg, e.Message ) );
}
break;
case "/R":
case "/ROWS":
if ( rows != 0 )
{
return ShowHelp( "Duplicate command line switch /R" );
}
try
{
rows = Convert.ToInt32( val );
if ( rows < 0 )
{
return ShowHelp( "Rows must be a positive integer" );
}
}
catch ( Exception )
{
return ShowHelp( "Invalid rows value \"{0}\"", arg );
}
break;
case "/T:":
case "/TAB":
case "/TABLENGTH":
if ( tablengthset )
{
return ShowHelp( "Duplicate command line switch /T" );
}
try
{
tablength = Convert.ToInt32( val );
if ( tablength < 4 || tablength > 16 )
{
return ShowHelp( String.Format( "Tab length {0} outside allowed range of {1}..{2}", val, 4, 16 ) );
}
}
catch ( Exception e )
{
return ShowHelp( String.Format( "Invalid tab length \"{0}\": {1}", val, e.Message ) );
}
tablengthset = true;
break;
case "/W":
case "/WIDTH":
if ( widthset )
{
return ShowHelp( "Duplicate command line switch /W" );
}
try
{
windowwidth = Convert.ToInt32( val );
if ( windowwidth < minimumwindowwidth || windowwidth > maximumwindowwidth )
{
return ShowHelp( String.Format( "Width {0} outside allowed range of {1}..{2}", val, minimumwindowwidth, maximumwindowwidth ) );
}
}
catch ( Exception e )
{
return ShowHelp( String.Format( "Invalid width \"{0}\": {1}", val, e.Message ) );
}
widthset = true;
break;
default:
return ShowHelp( String.Format( "Invalid command line switch \"{0}\"", arg ) );
}
#endregion Key/Value Named Arguments
}
}
#endregion Named Arguments
// Next, validate unnamed arguments
#region Unnamed Arguments
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
{
switch ( unnamedargs.Count )
{
case 0:
break;
case 1:
prompt = unnamedargs[0];
break;
case 2:
prompt = unnamedargs[0];
title = unnamedargs[1];
break;
case 3:
return ShowHelp( "Invalid command line argument: {0}", unnamedargs[2] );
default:
unnamedargs.RemoveRange( 0, 2 );
return ShowHelp( "Invalid command line arguments: {0}", String.Join( ", ", unnamedargs ) );
}
}
else
{
switch ( unnamedargs.Count )
{
case 0:
break;
case 1:
list = unnamedargs[0];
listset = true;
break;
case 2:
list = unnamedargs[0];
prompt = unnamedargs[1];
listset = true;
break;
case 3:
list = unnamedargs[0];
prompt = unnamedargs[1];
title = unnamedargs[2];
listset = true;
break;
case 4:
return ShowHelp( "Invalid command line argument: {0}", unnamedargs[3] );
default:
unnamedargs.RemoveRange( 0, 3 );
return ShowHelp( "Invalid command line arguments: {0}", String.Join( ", ", unnamedargs ) );
}
}
#endregion Unnamed Arguments
#region Validate Specified Values and Combinations
if ( !listset )
{
return ShowHelp( "Mandatory list not specified" );
}
if ( rows * columns != 0 )
{
return ShowHelp( "You may specify the number of either columns or rows, but not both" );
}
int listrange = ( 1 << ( list.Split( new char[] { delimiter }, StringSplitOptions.RemoveEmptyEntries ).Length ) ) - 1;
if ( defaultitems < 0 || defaultitems > listrange )
{
return ShowHelp( String.Format( "Preselected items ({0}) outside list range (0..{1})", defaultitems, listrange ) );
}
#endregion Validate Specified Values and Combinations
#endregion Command Line Parsing
#region Set Localized Captions
if ( localizedcaptionset )
{
cancelcaption = Load( "user32.dll", 801, cancelcaption );
okcaption = Load( "user32.dll", 800, okcaption );
if ( !String.IsNullOrWhiteSpace( localizationstring ) )
{
string[] locstrings = localizationstring.Split( ";".ToCharArray( ) );
foreach ( string locstring in locstrings )
{
string key = locstring.Substring( 0, locstring.IndexOf( '=' ) );
string val = locstring.Substring( Math.Min( locstring.IndexOf( '=' ) + 1, locstring.Length - 1 ) );
if ( !String.IsNullOrWhiteSpace( val ) )
{
switch ( key.ToUpper( ) )
{
case "OK":
okcaption = val;
break;
case "CANCEL":
cancelcaption = val;
break;
default:
return ShowHelp( "Invalid localization key \"{0}\"", key );
}
}
}
}
}
#endregion Set Localized Captions
#region Parse List
List<string> listitems = new List<string>( list.Split( delimiter.ToString( ).ToCharArray( ), StringSplitOptions.RemoveEmptyEntries ) );
if ( skipfirstitem )
{
listitems.RemoveAt( 0 );
}
for ( int i = 0; i < listitems.Count; i++ )
{
listitems[i] = listitems[i].Trim( );
}
if ( deduplist )
{
List<string> deduped = new List<string>( );
foreach ( string key in listitems )
{
if ( !deduped.Contains( key ) )
{
deduped.Add( key );
}
}
listitems = deduped;
}
if ( sortlist )
{
listitems.Sort( StringComparer.OrdinalIgnoreCase );
}
#endregion Parse List
#region Main Form
Form multiplechoiceform = new Form( );
multiplechoiceform.FormBorderStyle = FormBorderStyle.FixedDialog;
multiplechoiceform.MaximizeBox = false;
multiplechoiceform.MinimizeBox = false;
multiplechoiceform.StartPosition = FormStartPosition.CenterParent;
multiplechoiceform.Text = title;
multiplechoiceform.Icon = IconExtractor.Extract( "shell32.dll", icon, true );
#endregion Main Form
#region Initial Sizes
int horizontalmargin = 10;
int verticalmargin = 10;
int promptwidth = 0;
int cbtextheight = 0; // checkbox text height
int cbtextwidth = 0; // checkbox text width
int cbwidth = 15; // checkbox width without text
int buttonheight = 25;
int buttonwidth = 80;
#endregion Initial Sizes
#region Prompt
if ( String.IsNullOrWhiteSpace( prompt ) )
{
promptheight = -1 * verticalmargin;
}
else
{
if ( monospaced )
{
labelPrompt.Font = new Font( FontFamily.GenericMonospace, labelPrompt.Font.Size );
}
// Calculate required height for single prompt line
promptheight = TextRenderer.MeasureText( "Test", labelPrompt.Font ).Height;
// Replace tabs with spaces
if ( prompt.IndexOf( "\\t", StringComparison.Ordinal ) > -1 )
{
string tab = new String( ' ', tablength );
// First split the prompt on newlines
string[] prompt2 = prompt.Split( new string[] { "\\n" }, StringSplitOptions.None );
for ( int i = 0; i < prompt2.Length; i++ )
{
if ( prompt2[i].IndexOf( "\\t", StringComparison.Ordinal ) > -1 )
{
// Split each "sub-line" of the prompt on tabs
string[] prompt3 = prompt2[i].Split( new string[] { "\\t" }, StringSplitOptions.None );
// Each substring before a tab gets n spaces attached, and then is shortened to the greatest possible multiple of n
for ( int j = 0; j < prompt3.Length - 1; j++ )
{
prompt3[j] += tab;
int length = prompt3[j].Length;
length /= tablength;
length *= tablength;
prompt3[j] = prompt3[j].Substring( 0, length );
}
prompt2[i] = String.Join( "", prompt3 );
}
}
prompt = String.Join( "\n", prompt2 );
}
prompt = prompt.Replace( "\\n", "\n" ).Replace( "\\r", "\r" );
labelPrompt.Text = prompt;
string[] lines = prompt.Split( "\n".ToCharArray( ) );
int promptlines = lines.Length;
foreach ( string line in lines )
{
promptwidth = Math.Max( promptwidth, TextRenderer.MeasureText( line, labelPrompt.Font ).Width );
}
// Calculate required height for multiple line prompt
promptheight = promptlines * promptheight;
}
#endregion Prompt
#region Checkboxes
List<CheckBox> checkboxes = new List<CheckBox>( );
for ( int i = 0; i < listitems.Count; i++ )
{
CheckBox checkbox = new CheckBox( );
checkbox.Text = listitems[i];
checkbox.Checked = ( ( defaultitems & ( 1 << i ) ) > 0 );
cbtextwidth = Math.Max( cbtextwidth, Convert.ToInt32( TextRenderer.MeasureText( listitems[i], checkbox.Font ).Width * cbsafetyfactor ) );
cbtextheight = Math.Max( cbtextheight, Convert.ToInt32( TextRenderer.MeasureText( listitems[i], checkbox.Font ).Height * cbsafetyfactor ) );
checkboxes.Add( checkbox );
}
GroupBox cbgroup = new GroupBox( );
#endregion Checkboxes
#region Buttons
Button okButton = new Button( );
okButton.DialogResult = DialogResult.OK;
okButton.Name = "okButton";
okButton.Text = okcaption;
Button cancelButton = new Button( );
cancelButton.DialogResult = DialogResult.Cancel;
cancelButton.Name = "cancelButton";
cancelButton.Text = cancelcaption;
#endregion Buttons
#region Calculate Window Layout
if ( rows > 0 )
{
rows = Math.Min( rows, listitems.Count );
columns = (int) Math.Floor( (decimal) ( listitems.Count + rows - 1 ) / rows );
}
else if ( columns > 0 )
{
columns = Math.Min( columns, listitems.Count );
rows = (int) Math.Floor( (decimal) ( listitems.Count + columns - 1 ) / columns );
}
else
{
columns = 1;
rows = listitems.Count;
}
int cbgroupwidth = 0;
int cbgroupheight = 0;
int rowheight = 0;
int colwidth = 0;
if ( widthset )
{
cbgroupwidth = windowwidth - 2 * horizontalmargin;
colwidth = (int) Math.Floor( (decimal) ( cbgroupwidth - horizontalmargin - columns * ( cbwidth + horizontalmargin ) ) / columns );
}
else
{
colwidth = cbtextwidth + cbwidth;
cbgroupwidth = Math.Max( minimumwindowwidth - 2 * horizontalmargin, columns * ( colwidth + horizontalmargin ) + 2 * horizontalmargin );
colwidth = Math.Max( colwidth, Convert.ToInt32( ( cbgroupwidth - 2 * horizontalmargin ) / columns ) - horizontalmargin );
windowwidth = Math.Max( minimumwindowwidth, cbgroupwidth + 2 * horizontalmargin );
}
if ( heightset )
{
cbgroupheight = windowheight - promptheight - buttonheight - 4 * verticalmargin;
rowheight = (int) Math.Floor( (decimal) ( cbgroupheight - 2 * verticalmargin ) / rows );
}
else
{
rowheight = cbtextheight + verticalmargin;
windowheight = Math.Max( minimumwindowheight, 6 * verticalmargin + promptheight + buttonheight + rows * rowheight );
cbgroupheight = rows * rowheight + 2 * verticalmargin;
}
#endregion Calculate Window Layout
#region Check Available Group Box Space
if ( cbgroupheight / rows < rowheight || cbgroupwidth / columns < colwidth )
{
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" );
}
#endregion Check Available Group Box Space
#region Build Form
Size windowsize = new Size( windowwidth, windowheight );
multiplechoiceform.ClientSize = windowsize;
if ( !String.IsNullOrWhiteSpace( prompt ) )
{
labelPrompt.Size = new Size( windowwidth - 2 * horizontalmargin, promptheight );
labelPrompt.Location = new Point( horizontalmargin, verticalmargin );
multiplechoiceform.Controls.Add( labelPrompt );
}
cbgroup.Size = new Size( cbgroupwidth, cbgroupheight );
cbgroup.Location = new Point( horizontalmargin, promptheight + 2 * verticalmargin );
foreach ( CheckBox checkbox in checkboxes )
{
cbgroup.Controls.Add( checkbox );
}
multiplechoiceform.Controls.Add( cbgroup );
for ( int row = 0; row < rows; row++ )
{
for ( int column = 0; column < columns; column++ )
{
int index = row * columns + column;
if ( index < checkboxes.Count )
{
int x = Convert.ToInt32( horizontalmargin + column * ( colwidth + horizontalmargin ) );
int y = Convert.ToInt32( verticalmargin + row * rowheight );
checkboxes[index].Size = new Size( colwidth + horizontalmargin, rowheight );
checkboxes[index].Location = new Point( x, y );
}
}
}
okButton.Size = new Size( buttonwidth, buttonheight );
okButton.Location = new Point( windowwidth / 2 - horizontalmargin - buttonwidth, windowheight - buttonheight - verticalmargin );
multiplechoiceform.Controls.Add( okButton );
cancelButton.Size = new Size( buttonwidth, buttonheight );
cancelButton.Location = new Point( windowwidth / 2 + horizontalmargin, windowheight - buttonheight - verticalmargin );
multiplechoiceform.Controls.Add( cancelButton );
multiplechoiceform.AcceptButton = okButton; // OK on Enter
multiplechoiceform.CancelButton = cancelButton; // Cancel on Esc
#endregion Build Form
#region Show Dialog
multiplechoiceform.TopMost = topmost;
DialogResult result = multiplechoiceform.ShowDialog( );
if ( result == DialogResult.OK )
{
rc = 0;
for ( int i = 0; i < cbgroup.Controls.Count; i++ )
{
Control control = cbgroup.Controls[i];
if ( control.GetType( ) == typeof( CheckBox ) )
{
CheckBox cb = (CheckBox) control;
if ( cb.Checked )
{
selectedtext += cb.Text + ";";
rc += ( 1 << i );
}
}
}
// Display selected items
Console.WriteLine( selectedtext );
}
else
{
rc = -1;
}
#endregion Show Dialog
return rc;
}
#region Error handling
public static int ShowAliases()
{
int rc = ShowHelp( );
Console.Error.WriteLine( );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "Switch\tAlias(es)" );
Console.Error.WriteLine( "======\t=========" );
Console.Error.WriteLine( );
Console.Error.Write( "/?\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/HELP" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/A\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/??, /???, /ALIAS or /ALIASES" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/C\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/COL, /COLS or /COLUMNS" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/D\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/DELIMITER" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/DE\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/DEDUP" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/F\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/FILE" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/H\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/HEIGHT" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/I\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/ICON" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/K\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/SKIP, /SKIPFIRST or /SKIPFIRSTITEM" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/L\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/LOCALIZED or /LOCALIZEDCAPTIONS" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/MF\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/MONO, /MONOSPACED or /MONOSPACEDFONT" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/NM\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/NONMODAL or /NON-MODAL" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/P\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/DEFAULT, /DEFAULTITEMS, /PRE, /PRESELECTED or /PRESELECTEDITEMS" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/R\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/ROWS" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/S\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/SORT or /SORTLIST" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/T\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/TAB or /TABLENGTH" );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/W\t" );
Console.ResetColor( );
Console.Error.WriteLine( "/WIDTH" );
Console.Error.WriteLine( );
return rc;
}
public static int ShowHelp( params string[] errmsg )
{
#region Help Text
/*
MultipleChoiceBox, Version 1.00
Batch tool to present a Checkbox dialog and return the selected items
Usage: MULTIPLECHOICEBOX "list" [ "prompt" [ "title" ] ] [ options ]
or: MULTIPLECHOICEBOX /F:"listfile" [ "prompt" [ "title" ] ] [ options ]
or: listcommand | MULTIPLECHOICEBOX [ "prompt" [ "title" ] ] [ options ]
Where: "list" is a list of items to populate the checkbox group
"listcommand" is a command whose standard output is used as a list
of items to populate the checkbox group
"prompt" is the optional text above the checkbox group
(default: none)
"title" is the window title
(default: "MultipleChoiceBox, Version 1.00")
Options: /A show Aliases for command line switches (see Notes)
/C:columns sets then number of Columns for the checkbox group
(default: 1)
/D:"delimiter" sets the Delimiter character for "list"
(default: semicolon)
/DE DEdup: remove duplicates from "list"
/F:"listfile" use list from text File (one list item per line)
/H:height sets the window Height (default: autosized to make
content fit; minimum: 90; maximum: screen height - 68)
/I:index use Icon at index from shell32.dll (default: 23)
/K sKip first item of list (e.g. a header line)
/L[:"captions"] Localize or customize button captions
(e.g. /L:"OK=Why Not?;Cancel=No Way!")
/MF use Monospaced Font in prompt (default: proportional)
/NM make dialog Non-Modal (default: Modal, i.e. on top)
/P:initial Preselect the initial checkboxes' state (see Notes)
/R:rows sets then number of Rows for the checkbox group
(default: one row per list item)
/S Sort list (default: unsorted)
/T:tablength sets the number of spaces for Tabs in prompt
(4..16; default: 4)
/W:width sets the window Width (default: autosized to make
content fit; minimum: 200; maximum: screen width - 16)
Notes: The selected item text is written to Standard Out if "OK" is clicked,
otherwise an empty string is returned.
Most command line switches have one or more aliases, e.g. instead
of /R:5 you can use /ROWS:5 to make your batch files more readable;
use command line switch /A to get a list of all available aliases.
Use either "list" or /F:"listfile" or "listcommand".
Linefeeds (\n), tabs (\t) and doublequotes (\") are allowed in the
prompt text (but not in the title); with tabs, /MF is recommended.
To get a custom title without prompt, use " " for prompt.
If specified without captions, switch /L forces localized button
captions (e.g. "Cancel" button caption is "Annuleren" on Dutch
systems); if only a single custom caption is specified, the other
one is localized (e.g. with /L:"OK=Gaan" on Dutch systems, "OK"
button caption is "Gaan", "Cancel" button caption is "Annuleren").
With /P the inital state of each checkbox can be set; e.g. /P:5
wil set the 1st (1<<0 = 1) and 3rd (1<<2 = 4) checkboxes checked.
Return code is a binary representation of the checked items, e.g. 5
(0101) if only the 1st and 3rd checkboxes were checked, -1 on errors.
Be aware that the return code may be useless after sorting the list.
Credits: On-the-fly form based on code by Gorkem Gencay on StackOverflow:
http://stackoverflow.com/questions/97097#17546909
Code to retrieve localized button captions by Martin Stoeckli:
http://martinstoeckli.ch/csharp/csharp.html#windows_text_resources
Code to extract icons from Shell32.dll by Thomas Levesque:
http://stackoverflow.com/questions/6873026
Written by Rob van der Woude
http://www.robvanderwoude.com
*/
#endregion Help Text
#region Error Message
if ( errmsg.Length > 0 )
{
List<string> errargs = new List<string>( errmsg );
errargs.RemoveAt( 0 );
Console.Error.WriteLine( );
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.Write( "ERROR:\t" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
Console.ResetColor( );
}
#endregion Error Message
#region Show Help Text
Console.Error.WriteLine( );
Console.Error.WriteLine( "RadioButtonBox, Version {0}", progver );
Console.Error.WriteLine( "Batch tool to present a Checkbox dialog and return the selected items" );
Console.Error.WriteLine( );
Console.Error.Write( "Usage: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "MULTIPLECHOICEBOX \"list\" [ \"prompt\" [ \"title\" ] ] [ options ]" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( " or: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "MULTIPLECHOICEBOX /F:\"listfile\" [ \"prompt\" [ \"title\" ] ] [ options ]" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( " or: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "listcommand | MULTIPLECHOICEBOX [ \"prompt\" [ \"title\" ] ] [ options ]" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.Write( "Where: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "\"list\"" );
Console.ResetColor( );
Console.Error.WriteLine( " is a list of items to populate the checkbox group" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " \"listcommand\"" );
Console.ResetColor( );
Console.Error.Write( " is a " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "command" );
Console.ResetColor( );
Console.Error.Write( " whose standard output is used as a " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "list" );
Console.ResetColor( );
Console.Error.WriteLine( " of items to populate the checkbox group" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " \"prompt\"" );
Console.ResetColor( );
Console.Error.WriteLine( " is the optional text above the checkbox group" );
Console.Error.WriteLine( " (default: none)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " \"title\"" );
Console.ResetColor( );
Console.Error.WriteLine( " is the window title" );
Console.Error.WriteLine( " (default: \"MultipleChoiceBox, Version {0}\")", progver );
Console.Error.Write( "Options: " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/A" );
Console.ResetColor( );
Console.Error.Write( " show " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "A" );
Console.ResetColor( );
Console.Error.WriteLine( "liases for command line switches (see Notes)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /C:columns" );
Console.ResetColor( );
Console.Error.Write( " sets the number of " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "C" );
Console.ResetColor( );
Console.Error.WriteLine( "olumns for the checkbox group" );
Console.Error.WriteLine( " (default: 1)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /D:\"delimiter\"" );
Console.ResetColor( );
Console.Error.Write( " sets the " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "D" );
Console.ResetColor( );
Console.Error.Write( "elimiter character for " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "\"list\"" );
Console.ResetColor( );
Console.Error.WriteLine( " (default: semicolon)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /DE DE" );
Console.ResetColor( );
Console.Error.Write( "dup: remove duplicates from " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "\"list\"" );
Console.ResetColor( );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /F:\"listfile\"" );
Console.ResetColor( );
Console.Error.Write( " use list from text " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "F" );
Console.ResetColor( );
Console.Error.WriteLine( "ile (one list item per line)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /H:height" );
Console.ResetColor( );
Console.Error.Write( " sets the window " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "H" );
Console.ResetColor( );
Console.Error.WriteLine( "eight (default: autosized to make" );
Console.Error.WriteLine( " content fit; minimum: {0}; maximum: screen height - {1})", minimumwindowheight, borderY );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /I:index" );
Console.ResetColor( );
Console.Error.Write( " use " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "I" );
Console.ResetColor( );
Console.Error.Write( "con at " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "index" );
Console.ResetColor( );
Console.Error.WriteLine( " from shell32.dll (default: 23)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /K" );
Console.ResetColor( );
Console.Error.Write( " s" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "K" );
Console.ResetColor( );
Console.Error.WriteLine( "ip first item of list (e.g. a header line)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /L[:\"captions\"] L" );
Console.ResetColor( );
Console.Error.Write( "ocalize or customize button " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "captions" );
Console.ResetColor( );
Console.Error.Write( " (e.g. " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/L:\"OK=Why Not?;Cancel=No Way!\"" );
Console.ResetColor( );
Console.Error.WriteLine( ")" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /MF" );
Console.ResetColor( );
Console.Error.Write( " use " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "M" );
Console.ResetColor( );
Console.Error.Write( "onospaced " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "F" );
Console.ResetColor( );
Console.Error.Write( "ont in " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "prompt" );
Console.ResetColor( );
Console.Error.WriteLine( " (default: proportional)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /NM" );
Console.ResetColor( );
Console.Error.Write( " make dialog " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "N" );
Console.ResetColor( );
Console.Error.Write( "on-" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "M" );
Console.ResetColor( );
Console.Error.WriteLine( "odal (default: modal, i.e. on top)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /P:initial P" );
Console.ResetColor( );
Console.Error.Write( "reselect the " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "initial" );
Console.ResetColor( );
Console.Error.WriteLine( " checkboxes' state (see Notes)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /R:rows" );
Console.ResetColor( );
Console.Error.Write( " sets then number of " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "R" );
Console.ResetColor( );
Console.Error.WriteLine( "ows for the checkbox group" );
Console.Error.WriteLine( " (default: one row per list item)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /S S" );
Console.ResetColor( );
Console.Error.WriteLine( "ort list (default: unsorted)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /T:tablength" );
Console.ResetColor( );
Console.Error.Write( " sets the number of spaces for " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "T" );
Console.ResetColor( );
Console.Error.Write( "abs in " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "prompt" );
Console.ResetColor( );
Console.Error.WriteLine( " (4..16; default: 4)" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " /W:width" );
Console.ResetColor( );
Console.Error.Write( " sets the window " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "W" );
Console.ResetColor( );
Console.Error.WriteLine( "idth (default: autosized to make" );
Console.Error.WriteLine( " content fit; minimum: {0}; maximum: screen width - {1})", minimumwindowwidth, borderX );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Notes: The selected item text is written to Standard Out if \"OK\" is clicked," );
Console.Error.WriteLine( " otherwise an empty string is returned." );
Console.Error.WriteLine( " Most command line switches have one or more aliases, e.g. instead" );
Console.Error.Write( " of " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/R:5" );
Console.ResetColor( );
Console.Error.Write( " you can use " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/ROWS:5" );
Console.ResetColor( );
Console.Error.WriteLine( " to make your batch files more readable;" );
Console.Error.Write( " use command line switch " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/A" );
Console.ResetColor( );
Console.Error.WriteLine( " to get a list of all available aliases." );
Console.Error.Write( " Use either " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "\"list\"" );
Console.ResetColor( );
Console.Error.Write( " or " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/F:\"listfile\"" );
Console.ResetColor( );
Console.Error.Write( " or " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "\"listcommand\"" );
Console.ResetColor( );
Console.Error.WriteLine( "." );
Console.Error.WriteLine( " Linefeeds (\\n), tabs (\\t) and doublequotes (\\\") are allowed in the" );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( " prompt" );
Console.ResetColor( );
Console.Error.Write( " text (but not in the " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "title" );
Console.ResetColor( );
Console.Error.Write( "); with tabs, " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/MF" );
Console.ResetColor( );
Console.Error.WriteLine( " is recommended." );
Console.Error.WriteLine( " To get a custom title without prompt, use \" \" for prompt." );
Console.Error.Write( " If specified without " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "captions" );
Console.ResetColor( );
Console.Error.Write( ", switch " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/L" );
Console.ResetColor( );
Console.Error.WriteLine( " forces localized button" );
Console.Error.WriteLine( " captions (e.g. \"Cancel\" button caption is \"Annuleren\" on Dutch" );
Console.Error.WriteLine( " systems); if only a single custom caption is specified, the other" );
Console.Error.Write( " one is localized (e.g. with " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/L:\"OK=Gaan\"" );
Console.ResetColor( );
Console.Error.WriteLine( " on Dutch systems, \"OK\"" );
Console.Error.WriteLine( " button caption is \"Gaan\", \"Cancel\" button caption is \"Annuleren\")." );
Console.Error.WriteLine( " Return code 0 for \"OK\", 1 for (command line) errors, 2 for \"Cancel\"." );
Console.Error.Write( " With " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "/P" );
Console.ResetColor( );
Console.Error.Write( " the " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.Write( "inital" );
Console.ResetColor( );
Console.Error.Write( " state of each checkbox can be set; e.g. " );
Console.ForegroundColor = ConsoleColor.White;
Console.Error.WriteLine( "/P:5" );
Console.ResetColor( );
Console.Error.WriteLine( " wil set the 1st (1<<0 = 1) and 3rd (1<<2 = 4) checkboxes checked." );
Console.Error.WriteLine( " Return code is a binary representation of the checked items, e.g. 5" );
Console.Error.WriteLine( " (0101) if only the 1st and 3rd checkboxes were checked, -1 on errors." );
Console.Error.WriteLine( " Be aware that the return code may be useless after sorting the list." );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Credits: On-the-fly form based on code by Gorkem Gencay on StackOverflow:" );
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Error.WriteLine( " http://stackoverflow.com/questions/17546909" );
Console.ResetColor( );
Console.Error.WriteLine( " Code to retrieve localized button captions by Martin Stoeckli:" );
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Error.WriteLine( " http://martinstoeckli.ch/csharp/csharp.html#windows_text_resources" );
Console.ResetColor( );
Console.Error.WriteLine( " Code to extract icons from Shell32.dll by Thomas Levesque:" );
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Error.WriteLine( " http://stackoverflow.com/questions/6873026" );
Console.ResetColor( );
Console.Error.WriteLine( );
Console.Error.WriteLine( "Written by Rob van der Woude" );
Console.Error.WriteLine( "http://www.robvanderwoude.com" );
#endregion Show Help Text
return -1;
}
#endregion Error handling
#region Get Window Border Dimensions
public static int[] BorderDimensions()
{
Form testform = new Form( );
Size testsize = new Size( 300, 200 );
testform.Size = testsize;
int deltaX = testform.Size.Width - testform.ClientSize.Width + Screen.PrimaryScreen.Bounds.Width - Screen.PrimaryScreen.WorkingArea.Width;
int deltaY = testform.Size.Height - testform.ClientSize.Height + Screen.PrimaryScreen.Bounds.Height - Screen.PrimaryScreen.WorkingArea.Height;
testform.Dispose( );
return new int[] { deltaX, deltaY };
}
#endregion Get Window Border Dimensions
#region Get Localized Captions
// Code to retrieve localized captions by Martin Stoeckli
// http://martinstoeckli.ch/csharp/csharp.html#windows_text_resources
/// <summary>
/// Searches for a text resource in a Windows library.
/// Sometimes, using the existing Windows resources, you can make your code
/// language independent and you don't have to care about translation problems.
/// </summary>
/// <example>
/// btnCancel.Text = Load("user32.dll", 801, "Cancel");
/// btnYes.Text = Load("user32.dll", 805, "Yes");
/// </example>
/// <param name="libraryName">Name of the windows library like "user32.dll"
/// or "shell32.dll"</param>
/// <param name="ident">Id of the string resource.</param>
/// <param name="defaultText">Return this text, if the resource string could
/// not be found.</param>
/// <returns>Requested string if the resource was found,
/// otherwise the <paramref name="defaultText"/></returns>
public static string Load( string libraryName, UInt32 ident, string defaultText )
{
IntPtr libraryHandle = GetModuleHandle( libraryName );
if ( libraryHandle != IntPtr.Zero )
{
StringBuilder sb = new StringBuilder( 1024 );
int size = LoadString( libraryHandle, ident, sb, 1024 );
if ( size > 0 )
return sb.ToString( );
}
return defaultText;
}
[DllImport( "kernel32.dll", CharSet = CharSet.Auto )]
private static extern IntPtr GetModuleHandle( string lpModuleName );
[DllImport( "user32.dll", CharSet = CharSet.Auto )]
private static extern int LoadString( IntPtr hInstance, UInt32 uID, StringBuilder lpBuffer, Int32 nBufferMax );
#endregion Get Localized Captions
#region Extract Icons
// Code to extract icons from Shell32.dll by Thomas Levesque
// http://stackoverflow.com/questions/6873026
public class IconExtractor
{
public static Icon Extract( string file, int number, bool largeIcon )
{
IntPtr large;
IntPtr small;
ExtractIconEx( file, number, out large, out small, 1 );
try
{
return Icon.FromHandle( largeIcon ? large : small );
}
catch
{
return null;
}
}
[DllImport( "Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall )]
private static extern int ExtractIconEx( string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons );
}
#endregion Extract Icons
}
}
page last modified: 2024-04-16; loaded in 0.0314 seconds