我有一个程序来监视调试消息,我已经尝试使用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");
Run Code Online (Sandbox Code Playgroud)
Ovi*_*rar 11
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;
/// <summary>
/// Initialize the Win32 console for this process.
/// </summary>
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() );
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[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
//--------------------------------------------------------------------------
/// <summary>
/// Functions in Kernel32.dll
/// </summary>
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
//--------------------------------------------------------------------------
/// <summary>
/// Functions in User32.dll
/// </summary>
#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
Run Code Online (Sandbox Code Playgroud)
您不能只是继续将日志项添加到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
}
Run Code Online (Sandbox Code Playgroud)
ListMaxSize应该比ListMinSize大得多,因此剪切不会经常发生.ListMinSize是您通常需要在日志记录列表中查看的最近消息的数量.
这只是伪代码,ListBox项集合上实际上没有RemoveRange(但是List上有).你可以找出确切的代码.
归档时间: |
|
查看次数: |
11012 次 |
最近记录: |