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

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