Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for mause.cs

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.InteropServices;
  4. using System.Threading;
  5. using static ConsoleLib.NativeMethods;
  6.  
  7.  
  8. namespace RobvanderWoude
  9. {
  10. 	class Mause
  11. 	{
  12. 		static string progver = "1.02";
  13.  
  14. 		const string defaultprompt = "Press any key or mouse button or wheel to continue . . .";
  15. 		const int defaulttimeout = 0;
  16.  
  17. 		static string prompt = defaultprompt;
  18. 		static int timeout = defaulttimeout;
  19. 		static bool flushkeyboardbuffer = true;
  20. 		private static System.Timers.Timer timer;
  21.  
  22.  
  23. 		static void Main( string[] args )
  24. 		{
  25. 			foreach ( string arg in args )
  26. 			{
  27. 				if ( arg == "/?" )
  28. 				{
  29. 					ShowHelp( );
  30. 				}
  31. 				if ( arg.Length > 3 && arg.ToUpper( ).Substring( 0, 3 ) == "/T:" )
  32. 				{
  33. 					if ( timeout != defaulttimeout )
  34. 					{
  35. 						ShowHelp( "Duplicate timeout switch /T" );
  36. 					}
  37. 					try
  38. 					{
  39. 						timeout = Convert.ToInt32( arg.Substring( 3 ) );
  40. 						if ( timeout < 1 || timeout > 3600 )
  41. 						{
  42. 							ShowHelp( "Specified timeout out of 1..3600 seconds range" );
  43. 						}
  44. 					}
  45. 					catch
  46. 					{
  47. 						ShowHelp( "Invalid timeout \"{0}\"", arg );
  48. 					}
  49. 				}
  50. 				else if ( arg.ToUpper( ) == "/N" )
  51. 				{
  52. 					if ( !flushkeyboardbuffer )
  53. 					{
  54. 						ShowHelp( "Duplicate timeout switch /N" );
  55. 					}
  56. 					flushkeyboardbuffer = false;
  57. 				}
  58. 				else
  59. 				{
  60. 					if ( prompt != defaultprompt )
  61. 					{
  62. 						ShowHelp( "Too many command line arguments" );
  63. 					}
  64. 					prompt = arg;
  65. 				}
  66. 			}
  67.  
  68. 			// Flush keyboard buffer unless /N switch is used
  69. 			if ( flushkeyboardbuffer )
  70. 			{
  71. 				FlushKeyboardBuffer( );
  72. 			}
  73.  
  74. 			IntPtr inHandle = GetStdHandle( STD_INPUT_HANDLE );
  75. 			uint mode = 0;
  76. 			GetConsoleMode( inHandle, ref mode );
  77. 			mode &= ~ENABLE_QUICK_EDIT_MODE; //disable
  78. 			mode |= ENABLE_WINDOW_INPUT; //enable (if you want)
  79. 			mode |= ENABLE_MOUSE_INPUT; //enable
  80. 			SetConsoleMode( inHandle, mode );
  81. 			ConsoleLib.ConsoleListener.MouseEvent += ConsoleListener_MouseEvent;
  82. 			ConsoleLib.ConsoleListener.KeyEvent += ConsoleListener_KeyEvent;
  83. 			ConsoleLib.ConsoleListener.Start( );
  84.  
  85. 			if ( timeout > 0 )
  86. 			{
  87. 				timer = new System.Timers.Timer( );
  88. 				timer.Interval = 1000 * timeout;
  89. 				timer.Elapsed += Timer_Elapsed;
  90. 				timer.Start( );
  91. 			}
  92.  
  93. 			if ( !string.IsNullOrWhiteSpace( prompt ) )
  94. 			{
  95. 				Console.Write( prompt );
  96. 			}
  97. 			Console.CursorVisible = false;
  98. 		}
  99.  
  100.  
  101. 		static void FlushKeyboardBuffer( )
  102. 		{
  103. 			// Code to flush keyboard buffer by gandjustas
  104. 			// https://stackoverflow.com/a/3769828
  105. 			bool hidekey = true;
  106. 			while ( Console.KeyAvailable )
  107. 			{
  108. 				Console.ReadKey( hidekey );
  109. 			}
  110. 		}
  111.  
  112.  
  113. 		static void Quit( int rc )
  114. 		{
  115. 			if ( !string.IsNullOrWhiteSpace( prompt ) )
  116. 			{
  117. 				Console.WriteLine( );
  118. 			}
  119. 			if ( timeout > 0 )
  120. 			{
  121. 				timer.Stop( );
  122. 				timer.Dispose( );
  123. 			}
  124. 			Console.CursorVisible = true;
  125. 			Environment.Exit( rc );
  126. 		}
  127.  
  128.  
  129. 		private static void ConsoleListener_KeyEvent( KEY_EVENT_RECORD r )
  130. 		{
  131. 			// Keyboard input
  132. 			Quit( 1 );
  133. 		}
  134.  
  135.  
  136. 		private static void ConsoleListener_MouseEvent( MOUSE_EVENT_RECORD r )
  137. 		{
  138. 			if ( r.dwEventFlags != 1 ) // ignore mouse movement events
  139. 			{
  140. 				// Mouse input
  141. 				Quit( 2 );
  142. 			}
  143. 		}
  144.  
  145.  
  146. 		private static void Timer_Elapsed( object sender, System.Timers.ElapsedEventArgs e )
  147. 		{
  148. 			// timeout elapsed
  149. 			Quit( 3 );
  150. 		}
  151.  
  152.  
  153. 		#region Error handling
  154.  
  155. 		static void ShowHelp( params string[] errmsg )
  156. 		{
  157. 			#region Error Message
  158.  
  159. 			if ( errmsg.Length > 0 )
  160. 			{
  161. 				List<string> errargs = new List<string>( errmsg );
  162. 				errargs.RemoveAt( 0 );
  163. 				Console.Error.WriteLine( );
  164. 				Console.ForegroundColor = ConsoleColor.Red;
  165. 				Console.Error.Write( "ERROR:\t" );
  166. 				Console.ForegroundColor = ConsoleColor.White;
  167. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  168. 				Console.ResetColor( );
  169. 			}
  170.  
  171. 			#endregion Error Message
  172.  
  173.  
  174. 			#region Help Text
  175.  
  176. 			/*
  177. 			Mause.exe,  Version 1.02
  178. 			Mouse enabled pAUSE command
  179.  
  180. 			Usage:    Mause.exe  [ prompt ]  [ /T:seconds ]  [ /N ]
  181.  
  182. 			Where:    prompt      is the prompt to be displayed (default: "Press any key
  183. 			                      or mouse button or wheel to continue . . ."; use "" to
  184. 			                      show no prompt)
  185. 			          /N          do Not flush the keyboard buffer
  186. 			                      (default: flush keyboard buffer when program is started)
  187. 			          /T:seconds  timeout in seconds (1..3600; default: wait forever)
  188.  
  189. 			Note:     Return code 1 for key, 2 for mouse, 3 for timeout or -1 for errors.
  190.  
  191. 			Credits:  ConsoleListener class by SWdV on StackOverflow.com
  192. 			          https://stackoverflow.com/a/29971246
  193. 			          Code to flush keyboard buffer by gandjustas on StackOverflow.com
  194. 			          https://stackoverflow.com/a/3769828
  195.  
  196. 			Written by Rob van der Woude
  197. 			https://www.robvanderwoude.com
  198. 			*/
  199.  
  200. 			#endregion Help Text
  201.  
  202.  
  203. 			#region Display Help Text
  204.  
  205. 			Console.Error.WriteLine( );
  206.  
  207. 			Console.Error.WriteLine( "Mause.exe,  Version {0}", progver );
  208.  
  209. 			Console.ForegroundColor = ConsoleColor.White;
  210. 			Console.Error.Write( "M" );
  211. 			Console.ResetColor( );
  212. 			Console.Error.Write( "ouse enabled p" );
  213. 			Console.ForegroundColor = ConsoleColor.White;
  214. 			Console.Error.Write( "AUSE" );
  215. 			Console.ResetColor( );
  216. 			Console.Error.WriteLine( " command" );
  217.  
  218. 			Console.Error.WriteLine( );
  219.  
  220. 			Console.Error.Write( "Usage:    " );
  221. 			Console.ForegroundColor = ConsoleColor.White;
  222. 			Console.Error.WriteLine( "Mause.exe  [ prompt ]  [ /T:timeout ]  [ /N ]" );
  223. 			Console.ResetColor( );
  224.  
  225. 			Console.Error.WriteLine( );
  226.  
  227. 			Console.Error.Write( "Where:    " );
  228. 			Console.ForegroundColor = ConsoleColor.White;
  229. 			Console.Error.Write( "prompt" );
  230. 			Console.ResetColor( );
  231. 			Console.Error.WriteLine( "      is the prompt to be displayed (default: \"Press any key" );
  232.  
  233. 			Console.Error.WriteLine( "                      or mouse button or wheel to continue . . .\"; use \"\" to" );
  234.  
  235. 			Console.Error.WriteLine( "                      show no prompt)" );
  236.  
  237. 			Console.ForegroundColor = ConsoleColor.White;
  238. 			Console.Error.Write( "          /N" );
  239. 			Console.ResetColor( );
  240. 			Console.Error.Write( "          do " );
  241. 			Console.ForegroundColor = ConsoleColor.White;
  242. 			Console.Error.Write( "N" );
  243. 			Console.ResetColor( );
  244. 			Console.ResetColor( );
  245. 			Console.Error.WriteLine( "ot flush the keyboard buffer" );
  246.  
  247. 			Console.Error.WriteLine( "                      (default: flush keyboard buffer when program is started)" );
  248.  
  249. 			Console.ForegroundColor = ConsoleColor.White;
  250. 			Console.Error.Write( "          /T:seconds" );
  251. 			Console.ResetColor( );
  252. 			Console.Error.WriteLine( "  timeout in seconds (1..3600; default: wait forever)" );
  253.  
  254. 			Console.Error.WriteLine( );
  255.  
  256. 			Console.Error.WriteLine( "Note:     Return code 1 for key, 2 for mouse, 3 for timeout or -1 for errors." );
  257.  
  258. 			Console.Error.WriteLine( );
  259.  
  260. 			Console.Error.WriteLine( "Credits:  ConsoleListener class by SWdV on StackOverflow.com" );
  261.  
  262. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  263. 			Console.Error.WriteLine( "          https://stackoverflow.com/a/29971246" );
  264. 			Console.ResetColor( );
  265.  
  266. 			Console.Error.WriteLine( "          Code to flush keyboard buffer by gandjustas on StackOverflow.com" );
  267.  
  268. 			Console.ForegroundColor = ConsoleColor.DarkGray;
  269. 			Console.Error.WriteLine( "          https://stackoverflow.com/a/3769828" );
  270. 			Console.ResetColor( );
  271.  
  272. 			Console.Error.WriteLine( );
  273.  
  274. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  275.  
  276. 			Console.Error.WriteLine( "https://www.robvanderwoude.com" );
  277.  
  278. 			#endregion Display Help Text
  279.  
  280.  
  281. 			Environment.Exit( -1 );
  282. 		}
  283.  
  284. 		#endregion Error handling
  285. 	}
  286. }
  287.  
  288.  
  289.  
  290. // ConsoleListener class by SWdV on StackOverflow.com
  291. // https://stackoverflow.com/a/29971246
  292. namespace ConsoleLib
  293. {
  294. 	public static class ConsoleListener
  295. 	{
  296. 		public static event ConsoleMouseEvent MouseEvent;
  297.  
  298. 		public static event ConsoleKeyEvent KeyEvent;
  299.  
  300. 		public static event ConsoleWindowBufferSizeEvent WindowBufferSizeEvent;
  301.  
  302. 		private static bool Run = false;
  303.  
  304.  
  305. 		public static void Start( )
  306. 		{
  307. 			if ( !Run )
  308. 			{
  309. 				Run = true;
  310. 				IntPtr handleIn = GetStdHandle( STD_INPUT_HANDLE );
  311. 				new Thread( ( ) =>
  312. 				{
  313. 					while ( true )
  314. 					{
  315. 						uint numRead = 0;
  316. 						INPUT_RECORD[] record = new INPUT_RECORD[1];
  317. 						record[0] = new INPUT_RECORD( );
  318. 						ReadConsoleInput( handleIn, record, 1, ref numRead );
  319. 						if ( Run )
  320. 							switch ( record[0].EventType )
  321. 							{
  322. 								case INPUT_RECORD.MOUSE_EVENT:
  323. 									MouseEvent?.Invoke( record[0].MouseEvent );
  324. 									break;
  325. 								case INPUT_RECORD.KEY_EVENT:
  326. 									KeyEvent?.Invoke( record[0].KeyEvent );
  327. 									break;
  328. 								case INPUT_RECORD.WINDOW_BUFFER_SIZE_EVENT:
  329. 									WindowBufferSizeEvent?.Invoke( record[0].WindowBufferSizeEvent );
  330. 									break;
  331. 							}
  332. 						else
  333. 						{
  334. 							uint numWritten = 0;
  335. 							WriteConsoleInput( handleIn, record, 1, ref numWritten );
  336. 							return;
  337. 						}
  338. 					}
  339. 				} ).Start( );
  340. 			}
  341. 		}
  342.  
  343.  
  344. 		public static void Stop( ) => Run = false;
  345.  
  346.  
  347. 		public delegate void ConsoleMouseEvent( MOUSE_EVENT_RECORD r );
  348.  
  349.  
  350. 		public delegate void ConsoleKeyEvent( KEY_EVENT_RECORD r );
  351.  
  352.  
  353. 		public delegate void ConsoleWindowBufferSizeEvent( WINDOW_BUFFER_SIZE_RECORD r );
  354. 	}
  355.  
  356.  
  357. 	public static class NativeMethods
  358. 	{
  359. 		public struct COORD
  360. 		{
  361. 			public short X;
  362. 			public short Y;
  363.  
  364.  
  365. 			public COORD( short x, short y )
  366. 			{
  367. 				X = x;
  368. 				Y = y;
  369. 			}
  370. 		}
  371.  
  372.  
  373. 		[StructLayout( LayoutKind.Explicit )]
  374. 		public struct INPUT_RECORD
  375. 		{
  376. 			public const ushort KEY_EVENT = 0x0001,
  377. 				MOUSE_EVENT = 0x0002,
  378. 				WINDOW_BUFFER_SIZE_EVENT = 0x0004; //more
  379.  
  380. 			[FieldOffset( 0 )]
  381. 			public ushort EventType;
  382.  
  383. 			[FieldOffset( 4 )]
  384. 			public KEY_EVENT_RECORD KeyEvent;
  385.  
  386. 			[FieldOffset( 4 )]
  387. 			public MOUSE_EVENT_RECORD MouseEvent;
  388.  
  389. 			[FieldOffset( 4 )]
  390. 			public WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
  391. 			/*
  392.             and:
  393.              MENU_EVENT_RECORD MenuEvent;
  394.              FOCUS_EVENT_RECORD FocusEvent;
  395.              */
  396. 		}
  397.  
  398.  
  399. 		public struct MOUSE_EVENT_RECORD
  400. 		{
  401. 			public COORD dwMousePosition;
  402.  
  403. 			public const uint FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001,
  404. 				FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004,
  405. 				FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008,
  406. 				FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010,
  407. 				RIGHTMOST_BUTTON_PRESSED = 0x0002;
  408.  
  409. 			public uint dwButtonState;
  410.  
  411. 			public const int CAPSLOCK_ON = 0x0080,
  412. 				ENHANCED_KEY = 0x0100,
  413. 				LEFT_ALT_PRESSED = 0x0002,
  414. 				LEFT_CTRL_PRESSED = 0x0008,
  415. 				NUMLOCK_ON = 0x0020,
  416. 				RIGHT_ALT_PRESSED = 0x0001,
  417. 				RIGHT_CTRL_PRESSED = 0x0004,
  418. 				SCROLLLOCK_ON = 0x0040,
  419. 				SHIFT_PRESSED = 0x0010;
  420.  
  421. 			public uint dwControlKeyState;
  422.  
  423. 			public const int DOUBLE_CLICK = 0x0002,
  424. 				MOUSE_HWHEELED = 0x0008,
  425. 				MOUSE_MOVED = 0x0001,
  426. 				MOUSE_WHEELED = 0x0004;
  427.  
  428. 			public uint dwEventFlags;
  429. 		}
  430.  
  431. 		[StructLayout( LayoutKind.Explicit, CharSet = CharSet.Unicode )]
  432. 		public struct KEY_EVENT_RECORD
  433. 		{
  434. 			[FieldOffset( 0 )]
  435. 			public bool bKeyDown;
  436.  
  437. 			[FieldOffset( 4 )]
  438. 			public ushort wRepeatCount;
  439.  
  440. 			[FieldOffset( 6 )]
  441. 			public ushort wVirtualKeyCode;
  442.  
  443. 			[FieldOffset( 8 )]
  444. 			public ushort wVirtualScanCode;
  445.  
  446. 			[FieldOffset( 10 )]
  447. 			public char UnicodeChar;
  448.  
  449. 			[FieldOffset( 10 )]
  450. 			public byte AsciiChar;
  451.  
  452. 			public const int CAPSLOCK_ON = 0x0080,
  453. 				ENHANCED_KEY = 0x0100,
  454. 				LEFT_ALT_PRESSED = 0x0002,
  455. 				LEFT_CTRL_PRESSED = 0x0008,
  456. 				NUMLOCK_ON = 0x0020,
  457. 				RIGHT_ALT_PRESSED = 0x0001,
  458. 				RIGHT_CTRL_PRESSED = 0x0004,
  459. 				SCROLLLOCK_ON = 0x0040,
  460. 				SHIFT_PRESSED = 0x0010;
  461.  
  462. 			[FieldOffset( 12 )]
  463. 			public uint dwControlKeyState;
  464. 		}
  465.  
  466. 		public struct WINDOW_BUFFER_SIZE_RECORD
  467. 		{
  468. 			public COORD dwSize;
  469. 		}
  470.  
  471. 		public const uint STD_INPUT_HANDLE = unchecked((uint) -10),
  472. 			STD_OUTPUT_HANDLE = unchecked((uint) -11),
  473. 			STD_ERROR_HANDLE = unchecked((uint) -12);
  474.  
  475. 		[DllImport( "kernel32.dll" )]
  476. 		public static extern IntPtr GetStdHandle( uint nStdHandle );
  477.  
  478. 		public const uint ENABLE_MOUSE_INPUT = 0x0010,
  479. 			ENABLE_QUICK_EDIT_MODE = 0x0040,
  480. 			ENABLE_EXTENDED_FLAGS = 0x0080,
  481. 			ENABLE_ECHO_INPUT = 0x0004,
  482. 			ENABLE_WINDOW_INPUT = 0x0008; //more
  483.  
  484. 		[DllImportAttribute( "kernel32.dll" )]
  485. 		public static extern bool GetConsoleMode( IntPtr hConsoleInput, ref uint lpMode );
  486.  
  487. 		[DllImportAttribute( "kernel32.dll" )]
  488. 		public static extern bool SetConsoleMode( IntPtr hConsoleInput, uint dwMode );
  489.  
  490. 		[DllImportAttribute( "kernel32.dll", CharSet = CharSet.Unicode )]
  491. 		public static extern bool ReadConsoleInput( IntPtr hConsoleInput, [Out] INPUT_RECORD[] lpBuffer, uint nLength, ref uint lpNumberOfEventsRead );
  492.  
  493. 		[DllImportAttribute( "kernel32.dll", CharSet = CharSet.Unicode )]
  494. 		public static extern bool WriteConsoleInput( IntPtr hConsoleInput, INPUT_RECORD[] lpBuffer, uint nLength, ref uint lpNumberOfEventsWritten );
  495. 	}
  496. }

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