代码之家  ›  专栏  ›  技术社区  ›  Rex Logan

如何将类似控制台的元素添加到c#winforms程序中

  •  13
  • Rex Logan  · 技术社区  · 17 年前

    我有一个监控调试消息的程序,我曾尝试使用文本框并将消息附加到其中,但它的伸缩性不太好,当消息数量变大时,速度会减慢。然后,我尝试了一个列表框,但在添加新消息时,滚动条突然出现在顶部。它也不允许像文本框那样进行剪切和粘贴。

    实现winforms窗口中嵌入的类似控制台的元素的更好方法是什么。

    编辑:

    
    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");
    
    
    
    7 回复  |  直到 17 年前
        1
  •  11
  •   Ovidiu Pacurar    17 年前

    而且它可以很好地处理大文本。
    我相信这是最适合你需要的。

        2
  •  6
  •   dbkk    17 年前

    我曾经有过这样的错误。我的解决方案是偶尔剪辑显示的消息列表。在伪代码中,这类似于:

    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
    }
    

    这只是伪代码,在ListBox项集合上实际上并没有RemoveRange(但在列表上有)。你可以算出确切的代码。

        3
  •  5
  •   mloskot    14 年前

    我在使用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
    
        4
  •  3
  •   Corey Trager    17 年前

    我遇到了这个挑战。我用两种不同的方法解决了这个问题,一种是在重负荷下工作,另一种是在重负荷下工作。一种方法是使用ListView。添加一行文本如下所示:

            ListViewItem itm = new ListViewItem();
            itm.Text = txt;
            this.listView1.Items.Add(itm);
            this.listView1.EnsureVisible(listView1.Items.Count - 1);
    

    另一种方法是在虚拟模式下使用DataGridView。我手头没有那个代码。虚拟模式是你的朋友。

        5
  •  2
  •   psamwel    13 年前
    public class ConsoleTextBox: TextBox
    {
        private List<string> contents = new List<string>();
        private const int MAX = 50;
    
        public void WriteLine(string input)
        {
            if (contents.Count == MAX)
                contents.RemoveAt(MAX-1);
            contents.Insert(0, input);
    
            Rewrite();
        }
    
        private void Rewrite()
        {
            var sb = new StringBuilder();
            foreach (var s in contents)
            {
                sb.Append(s);
                sb.Append(Environment.NewLine);
            }
            this.Text = sb.ToString();
        }
    }
    
        6
  •  1
  •   Steven A. Lowe    17 年前

    将列表框的selectedindex设置为最后一个元素,使其滚动到底部

    另外,将列表框中的项目数量限制在合理的范围内(从顶部删除,保留后面的项目),这样就不会占用所有的内存

        7
  •  1
  •   Andy Knight Andy Knight    17 年前

    最后添加以下代码:

        private void AddConsoleComment(string comment)
        {
            textBoxConsole.Text += comment + System.Environment.NewLine;
            textBoxConsole.Select(textBoxConsole.Text.Length,0);
            textBoxConsole.ScrollToCaret();
        }
    

    本质上,它是将您的注释添加到现有文本中,并附加一个换行符。最后选择长度为0的文本的最后一位。ScrollToCaret强制文本框向下滚动到光标所在的位置(最后一行)

    希望这有帮助。

    推荐文章