我有一个程序来监视调试消息,我已经尝试使用TextBox并将消息附加到它但它不能很好地扩展,并在消息数量变大时减慢速度.然后我尝试了一个ListBox,但在添加新消息时,滚动正在捕捉到顶部.它也不允许像文本框那样剪切和粘贴.
有什么更好的方法来实现类似于winforms窗口中嵌入的元素的控制台.
编辑:我仍然希望能够嵌入像visual studio这样的输出窗口,但由于我无法找到一个简单的方法,我使用的是两个解决方案.除了使用有效的RichTextBox之外,你必须时不时地清除它.我使用的是我用的控制台.这是我写的一个小包装类来处理这个问题.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace Con { class Ext_Console { static bool console_on = false; public static void Show(bool on,string title) { console_on = on; if (console_on) { AllocConsole(); Console.Title = title; // use to change color Console.BackgroundColor = System.ConsoleColor.White; Console.ForegroundColor = System.ConsoleColor.Black; } else { FreeConsole(); } } public static void Write(string output) { if (console_on) { Console.Write(output); } } public static void WriteLine(string output) { if (console_on) { Console.WriteLine(output); } } [DllImport("kernel32.dll")] public static extern Boolean AllocConsole(); [DllImport("kernel32.dll")] public static extern Boolean FreeConsole(); } } // example calls Ext_Console.Write("console output "); Ext_Console.WriteLine("console output"); Ext_Console.Show(true,"Title of console");
Ovidiu Pacur.. 11
RichTextBox有一个快速的AppendText方法.它可以很好地处理大文本.
我相信这是你需要的最好的.
RichTextBox有一个快速的AppendText方法.它可以很好地处理大文本.
我相信这是你需要的最好的.
我在使用Win32控制台窗口的C#窗口程序(WInforms或WPF)中执行此操作.我有一个包含一些基本Win32 API的小类,瘦我在程序开始时创建一个控制台.这只是一个例子:在"现实生活中"你会使用一个设置或其他东西来只在你需要时启用控制台.
using System; using System.Windows.Forms; using Microsoft.Win32.SafeHandles; using System.Diagnostics; using MWin32Api; namespace WFConsole { static class Program { static private SafeFileHandle ConsoleHandle; ////// Initialize the Win32 console for this process. /// static private void InitWin32Console() { if ( !K32.AllocConsole() ) { MessageBox.Show( "Cannot allocate console", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); return; } IntPtr handle = K32.CreateFile( "CONOUT$", // name K32.GENERIC_WRITE | K32.GENERIC_READ, // desired access K32.FILE_SHARE_WRITE | K32.FILE_SHARE_READ, // share access null, // no security attributes K32.OPEN_EXISTING, // device already exists 0, // no flags or attributes IntPtr.Zero ); // no template file. ConsoleHandle = new SafeFileHandle( handle, true ); if ( ConsoleHandle.IsInvalid ) { MessageBox.Show( "Cannot create diagnostic console", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); return; } // // Set the console screen buffer and window to a reasonable size // 1) set the screen buffer sizse // 2) Get the maximum window size (in terms of characters) // 3) set the window to be this size // const UInt16 conWidth = 256; const UInt16 conHeight = 5000; K32.Coord dwSize = new K32.Coord( conWidth, conHeight ); if ( !K32.SetConsoleScreenBufferSize( ConsoleHandle.DangerousGetHandle(), dwSize ) ) { MessageBox.Show( "Can't get console screen buffer information.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); return; } K32.Console_Screen_Buffer_Info SBInfo = new K32.Console_Screen_Buffer_Info(); if ( !K32.GetConsoleScreenBufferInfo( ConsoleHandle.DangerousGetHandle(), out SBInfo ) ) { MessageBox.Show( "Can't get console screen buffer information.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } K32.Small_Rect sr; ; sr.Left = 0; sr.Top = 0; sr.Right = 132 - 1; sr.Bottom = 51 - 1; if ( !K32.SetConsoleWindowInfo( ConsoleHandle.DangerousGetHandle(), true, ref sr ) ) { MessageBox.Show( "Can't set console screen buffer information.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); return; } IntPtr conHWND = K32.GetConsoleWindow(); if ( conHWND == IntPtr.Zero ) { MessageBox.Show( "Can't get console window handle.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); return; } if ( !U32.SetForegroundWindow( conHWND ) ) { MessageBox.Show( "Can't set console window as foreground.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); return; } K32.SetConsoleTitle( "Test - Console" ); Trace.Listeners.Add( new ConsoleTraceListener() ); } ////// The main entry point for the application. /// [STAThread] static void Main() { InitWin32Console(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault( false ); Application.Run( new Main() ); } } } using System; using System.Runtime.InteropServices; namespace MWin32Api { #region Kernel32 Functions //-------------------------------------------------------------------------- ////// Functions in Kernel32.dll /// public sealed class K32 { #region Data Structures, Types and Constants //---------------------------------------------------------------------- // Data Structures, Types and Constants // [StructLayout( LayoutKind.Sequential )] public class SecurityAttributes { public UInt32 nLength; public UIntPtr lpSecurityDescriptor; public bool bInheritHandle; } [StructLayout( LayoutKind.Sequential, Pack = 1, Size = 4 )] public struct Coord { public Coord( UInt16 tx, UInt16 ty ) { x = tx; y = ty; } public UInt16 x; public UInt16 y; } [StructLayout( LayoutKind.Sequential, Pack = 1, Size = 8 )] public struct Small_Rect { public Int16 Left; public Int16 Top; public Int16 Right; public Int16 Bottom; public Small_Rect( short tLeft, short tTop, short tRight, short tBottom ) { Left = tLeft; Top = tTop; Right = tRight; Bottom = tBottom; } } [StructLayout( LayoutKind.Sequential, Pack = 1, Size = 24 )] public struct Console_Screen_Buffer_Info { public Coord dwSize; public Coord dwCursorPosition; public UInt32 wAttributes; public Small_Rect srWindow; public Coord dwMaximumWindowSize; } public const int ZERO_HANDLE_VALUE = 0; public const int INVALID_HANDLE_VALUE = -1; #endregion #region Console Functions //---------------------------------------------------------------------- // Console Functions // [DllImport( "kernel32.dll", SetLastError = true )] public static extern bool AllocConsole(); [DllImport( "kernel32.dll", SetLastError = true )] public static extern bool SetConsoleScreenBufferSize( IntPtr hConsoleOutput, Coord dwSize ); [DllImport( "kernel32.dll", SetLastError = true )] public static extern bool GetConsoleScreenBufferInfo( IntPtr hConsoleOutput, out Console_Screen_Buffer_Info lpConsoleScreenBufferInfo ); [DllImport( "kernel32.dll", SetLastError = true )] public static extern bool SetConsoleWindowInfo( IntPtr hConsoleOutput, bool bAbsolute, ref Small_Rect lpConsoleWindow ); [DllImport( "kernel32.dll", SetLastError = true )] public static extern IntPtr GetConsoleWindow(); [DllImport( "kernel32.dll", SetLastError = true )] public static extern bool SetConsoleTitle( string Filename ); #endregion #region Create File //---------------------------------------------------------------------- // Create File // public const UInt32 CREATE_NEW = 1; public const UInt32 CREATE_ALWAYS = 2; public const UInt32 OPEN_EXISTING = 3; public const UInt32 OPEN_ALWAYS = 4; public const UInt32 TRUNCATE_EXISTING = 5; public const UInt32 FILE_SHARE_READ = 1; public const UInt32 FILE_SHARE_WRITE = 2; public const UInt32 GENERIC_WRITE = 0x40000000; public const UInt32 GENERIC_READ = 0x80000000; [DllImport( "kernel32.dll", SetLastError = true )] public static extern IntPtr CreateFile( string Filename, UInt32 DesiredAccess, UInt32 ShareMode, SecurityAttributes SecAttr, UInt32 CreationDisposition, UInt32 FlagsAndAttributes, IntPtr TemplateFile ); #endregion #region Win32 Miscelaneous //---------------------------------------------------------------------- // Miscelaneous // [DllImport( "kernel32.dll" )] public static extern bool CloseHandle( UIntPtr handle ); #endregion //---------------------------------------------------------------------- private K32() { } } #endregion //-------------------------------------------------------------------------- ////// Functions in User32.dll /// #region User32 Functions public sealed class U32 { [StructLayout( LayoutKind.Sequential )] public struct Rect { public Int32 Left; public Int32 Top; public Int32 Right; public Int32 Bottom; public Rect( short tLeft, short tTop, short tRight, short tBottom ) { Left = tLeft; Top = tTop; Right = tRight; Bottom = tBottom; } } [DllImport( "user32.dll" )] public static extern bool GetWindowRect( IntPtr hWnd, [In][MarshalAs( UnmanagedType.LPStruct )]Rect lpRect ); [DllImport( "user32.dll", SetLastError = true )] public static extern bool SetForegroundWindow( IntPtr hWnd ); //---------------------------------------------------------------------- private U32() { } } // U32 class #endregion } // MWin32Api namespace
您不能只是继续将日志项添加到WinForms控件(ListBox或RichTextBox) - 它最终会被阻塞并开始交换到磁盘.
我曾经有过这个确切的错误.我的解决方案是偶尔剪辑显示的消息列表.在伪代码中,这类似于:
void AddLogMessage(String message) { list.Items.Add(message); // DO: Append message to file as needed // Clip the list if (list.count > ListMaxSize) { list.Items.RemoveRange(0, list.Count - listMinSize); } // DO: Focus the last item on the list }
ListMaxSize应该比ListMinSize大得多,因此剪切不会经常发生.ListMinSize是您通常需要在日志记录列表中查看的最近消息的数量.
这只是伪代码,ListBox项集合上实际上没有RemoveRange(但是List上有).你可以找出确切的代码.