⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 consolecontrol.cs

📁 c#源代码
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.ComponentModel;
using System.Text;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;

namespace ICSharpCode.ConsolePad
{
	public class ConsoleControl : UserControl
	{
		#region Declarations
		
		private IntPtr hStdOut;
		private IntPtr hWndConsole;
		private Font font;
		private Process cmdProcess;
		private Timer drawingTimer;
		private VScrollBar scrollbar;
		private ConsoleCursor cursor;
		private TextSelection textSelection;
		private Rectangle rectSelection;
		private Point coordSelOrigin = Point.Empty;
		private Point mouseCursorOffset = Point.Empty;
		private Color selectionColor = Color.FromArgb(120, 228, 230, 238);
		
		private int rows = 50;
		private int cols = 50;
		private int bufferRows = 70;
		private int rowOffset = 0;
		
		private int charHeight = 13;
		private int charWidth = 8;
		
		private Win32Interop.CHAR_INFO[] pScreenBuffer;
		private Win32Interop.COORD maxSize;
		private Color[] consoleColors;
		
		private static Win32Interop.HandlerRoutine ctrlHandlerDelegate = new Win32Interop.HandlerRoutine(ctrlHandler);
		
		#endregion
		
		#region Startup
		
		public ConsoleControl()
		{
			SetStyle(ControlStyles.DoubleBuffer, true);
			SetStyle(ControlStyles.Selectable, true);
			SetStyle(ControlStyles.AllPaintingInWmPaint, true);
			SetStyle(ControlStyles.UserPaint, true);
			
			TabStop = true;
			
			scrollbar = new VScrollBar();
			scrollbar.Minimum = 0;
			scrollbar.Maximum = bufferRows - rows - 6;
			scrollbar.Dock = DockStyle.Right;
			scrollbar.Scroll += new ScrollEventHandler(vScrolled);
			Controls.Add(scrollbar);
			
			textSelection = TextSelection.None;
			font = new Font(FontFamily.GenericMonospace, 8, FontStyle.Regular);
			cursor = new ConsoleCursor();
			
			#region Colors
			consoleColors = new Color[16];
			consoleColors[0]	= ColorTranslator.FromWin32(0x000000);
			consoleColors[1]	=  ColorTranslator.FromWin32(0x800000);
			consoleColors[2]	=  ColorTranslator.FromWin32(0x008000);
			consoleColors[3]	=  ColorTranslator.FromWin32(0x808000);
			consoleColors[4]	=  ColorTranslator.FromWin32(0x000080);
			consoleColors[5]	=  ColorTranslator.FromWin32(0x800080);
			consoleColors[6]	=  ColorTranslator.FromWin32(0x008080);
			consoleColors[7]	=  ColorTranslator.FromWin32(0xC0C0C0);
			consoleColors[8]	=  ColorTranslator.FromWin32(0x808080);
			consoleColors[9]	=  ColorTranslator.FromWin32(0xFF0000);
			consoleColors[10]	=  ColorTranslator.FromWin32(0x00FF00);
			consoleColors[11]	=  ColorTranslator.FromWin32(0xFFFF00);
			consoleColors[12]	=  ColorTranslator.FromWin32(0x0000FF);
			consoleColors[13]	=  ColorTranslator.FromWin32(0xFF00FF);
			consoleColors[14]	=  ColorTranslator.FromWin32(0x00FFFF);
			consoleColors[15]	=  ColorTranslator.FromWin32(0xFFFFFF);
			#endregion
			
			if(startShellProcess())
			{
				drawingTimer = new Timer();
				drawingTimer.Interval = 1000;
				drawingTimer.Tick += new EventHandler(drawingTimerTick);
				drawingTimer.Enabled = true;
			}
		}
		
		protected override void Dispose(bool dispose)
		{
			drawingTimer.Enabled = false;
			drawingTimer.Dispose();
			
			font.Dispose();
			cursor.Dispose();
			
			Win32Interop.CloseHandle(hStdOut);
			cmdProcess.Kill();
			Win32Interop.FreeConsole();
			
			base.Dispose(dispose);
		}
		
		protected override void OnResize(EventArgs e)
		{
			resizeConsoleWindow();
			base.OnResize(e);
		}
		
		private bool startShellProcess()
		{
			string title = Guid.NewGuid().ToString();
			string command = Environment.GetEnvironmentVariable("COMSPEC");
			
			Win32Interop.AllocConsole();
			hWndConsole = Win32Interop.GetConsoleWindow();
			
			Win32Interop.SetConsoleTitle(title);
			hStdOut = Win32Interop.GetStdHandle(Win32Interop.STD_OUTPUT_HANDLE);
			
			maxSize = Win32Interop.GetLargestConsoleWindowSize(hStdOut);
			Win32Interop.SetConsoleCtrlHandler(ctrlHandlerDelegate, true );
			
			resizeConsoleWindow();
			hideConsole();
			
			Win32Interop.STARTUPINFO si = new Win32Interop.STARTUPINFO();
			si.cb = System.Runtime.InteropServices.Marshal.SizeOf(si);
			Win32Interop.PROCESS_INFORMATION pi = new Win32Interop.PROCESS_INFORMATION();
			
			bool result = Win32Interop.CreateProcess(command, null, IntPtr.Zero, IntPtr.Zero, true, Win32Interop.NORMAL_PRIORITY_CLASS, IntPtr.Zero, null, ref si, ref pi);
			cmdProcess = Process.GetProcessById(pi.dwProcessId);
			
			return true;
		}
		
		void hideConsole()
		{
			Win32Interop.ShowWindowAsync(hWndConsole, Win32Interop.SW_HIDE);
		}
		
		#endregion
		
		#region Output routines
		
		public void ChangeDirectory(string directory)
		{
			Output("cd \"" + directory + "\"", false, true);
		}
		
		public void Output(string text, bool showText, bool execute)
		{
			Win32Interop.COORD pos = new Win32Interop.COORD();
			
			if(showText && execute) {
				throw new ArgumentException("Only showText or execute allowed");
			}
			
			if(! showText) {
				pos = rememberPosition();
			}
			
			foreach(char c in text)
			{
				outputChar(c);
			}
			
			if(execute) {
				outputChar('\r');
			}
			
			if( !showText ) {
				restorePosition( pos, true );
			}
		}
		
		private void outputChar(char c)
		{
			IntPtr hIn = Win32Interop.GetStdHandle(Win32Interop.STD_INPUT_HANDLE);
			
			int cnt;
			Win32Interop.KEY_INPUT_RECORD r = new Win32Interop.KEY_INPUT_RECORD();
			
			r.bKeyDown = true;
			r.wRepeatCount = 1;
			r.wVirtualKeyCode = 0;
			r.wVirtualScanCode = 0;
			r.UnicodeChar = c;
			r.dwControlKeyState = 0;
			
			Win32Interop.WriteConsoleInput( hIn ,r, 1, out cnt);//key down event
			
			r.bKeyDown = false;
			Win32Interop.WriteConsoleInput( hIn ,r, 1, out cnt);//key up
		}
		
		private Win32Interop.COORD rememberPosition()
		{
			Win32Interop.CONSOLE_SCREEN_BUFFER_INFO csbi = new Win32Interop.CONSOLE_SCREEN_BUFFER_INFO();
			Win32Interop.GetConsoleScreenBufferInfo(hStdOut, ref csbi);
			return csbi.dwCursorPosition;
		}
		
		private void restorePosition(Win32Interop.COORD pos, bool erase)
		{
			Win32Interop.CONSOLE_SCREEN_BUFFER_INFO csbi = new Win32Interop.CONSOLE_SCREEN_BUFFER_INFO();
			Win32Interop.GetConsoleScreenBufferInfo(hStdOut, ref csbi);
			Win32Interop.SetConsoleCursorPosition(hStdOut, pos);
			
			if(erase)
			{
				int written;
				int num = (csbi.dwSize.x) * (csbi.dwCursorPosition.y - pos.y) + pos.x - csbi.dwCursorPosition.x;
				Win32Interop.WriteConsole(hStdOut, new String(' ',num), num, out written, IntPtr.Zero);
				Win32Interop.SetConsoleCursorPosition(hStdOut, pos);
			}
		}
		
		#endregion
		
		#region Input handling
		
		static bool ctrlHandler(Win32Interop.CtrlTypes eventId)
		{
			if(eventId == Win32Interop.CtrlTypes.CTRL_C_EVENT) {
				return true;
			}
			return false;
		}
		
		protected override bool IsInputKey(Keys key)
		{
			switch(key)
			{
				case Keys.Up:
				case Keys.Down:
				case Keys.Right:
				case Keys.Left:
					return true;
			}
			return base.IsInputKey(key);
		}
		
		protected override void WndProc(ref Message msg)
		{
			switch(msg.Msg) {
				case Win32Interop.WM_KEYDOWN:
				case Win32Interop.WM_KEYUP:
					Win32Interop.PostMessage(hWndConsole, (uint)msg.Msg, msg.WParam, msg.LParam);
					Invalidate();
					return;
				case Win32Interop.WM_SYSKEYDOWN:
				case Win32Interop.WM_SYSKEYUP:
					Win32Interop.TranslateMessage(ref msg);
					Win32Interop.PostMessage(hWndConsole, (uint)msg.Msg, msg.WParam, msg.LParam);
					Invalidate();
					return;
					
			}
			base.WndProc(ref msg);
		}
		
		#endregion
		
		#region Window handling and painting
		
		void resizeConsoleWindow()
		{
			Win32Interop.CONSOLE_SCREEN_BUFFER_INFO csbi = new Win32Interop.CONSOLE_SCREEN_BUFFER_INFO();
			Win32Interop.GetConsoleScreenBufferInfo(hStdOut, ref csbi);
			
			cols = Math.Min((this.Width - scrollbar.Width) / charWidth, maxSize.x);
			rows = Math.Min(this.Height / charHeight, maxSize.y);
			
			cols = Math.Max(cols, 1);
			rows = Math.Max(rows, 1);
			
			Win32Interop.COORD coordConsoleSize;
			coordConsoleSize.x = (short)cols;
			coordConsoleSize.y = (short)bufferRows;
			
			Win32Interop.SMALL_RECT srConsoleRect;
			srConsoleRect.Top = 0;
			srConsoleRect.Left = 0;
			srConsoleRect.Right = (short)(cols - 1);
			
			srConsoleRect.Bottom = (short)(rows - 1);
			
			if(csbi.dwSize.x * csbi.dwSize.y >= cols * bufferRows)
			{
				if (csbi.dwSize.y > bufferRows)
				{
					coordConsoleSize.y = (short)csbi.dwSize.y;
					bufferRows = (short)csbi.dwSize.y;
					scrollbar.Maximum = bufferRows - rows - 6;
				}
				Win32Interop.SetConsoleWindowInfo(hStdOut, true, ref srConsoleRect);
				Win32Interop.SetConsoleScreenBufferSize(hStdOut, coordConsoleSize);
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -