2008-10-31 8 views
13

मैं एक प्रोग्राम है जो डिबग संदेशों की निगरानी करता है और मैं किसी पाठ बॉक्स का उपयोग कर की कोशिश की और यह करने के लिए संदेश संलग्न लेकिन यह बहुत अच्छी तरह से स्केल नहीं करता है और जिस तरह से नीचे जब धीमा कर देती है संदेशों की संख्या बड़ी हो जाती है। मैंने फिर एक सूची बॉक्स की कोशिश की लेकिन स्क्रॉलिंग नए संदेशों को जोड़ते समय शीर्ष पर स्नैप कर रही थी। यह टेक्स्ट बॉक्स की तरह कट और पेस्ट करने की भी अनुमति नहीं देता है।मैं कैसे एसी # WinForms कार्यक्रम के लिए तत्व की तरह एक कंसोल में शामिल कर सकता

एक WinForms विंडो में एम्बेडेड तत्व की तरह एक सांत्वना लागू करने के लिए एक बेहतर तरीका क्या है।

संपादित करें: मैं अभी भी विजुअल स्टूडियो जैसे आउटपुट विंडो को एम्बेड करने में सक्षम होना चाहता हूं लेकिन चूंकि मैं यहां उपयोग करने वाले दो समाधानों का एक आसान तरीका नहीं समझ सकता हूं। 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"); 


उत्तर

10

RichTextBox एक AppendText विधि तेज है कि है ऊपर चबाना नहीं है। और यह बड़े टेक्स्ट को अच्छी तरह से संभाल सकता है।
मेरा मानना ​​है कि आपको जो चाहिए वह सर्वोत्तम है।

+1

बड़ा असीमित नहीं है। यदि लॉगिंग/डीबग संदेशों के लिए उपयोग किया जाता है, तो अंततः यह नीचे गिर जाएगा और थ्रैशिंग शुरू हो जाएगा। – dbkk

+2

कंसोल विंडो असीमित नहीं है। –

+1

यह इस अर्थ में अनंत है कि पुराना पाठ शीर्ष पर "गिरता है" और खिड़की पर आउटपुट धीमा नहीं होता है क्योंकि आउटपुट अधिक होता है। मुझे लगता है कि यह @ ओविडिउ को दिमाग में है। –

1

यह नीचे

को भी स्क्रॉल, उचित कुछ (ऊपर से हटाने के लिए लिस्टबॉक्स में आइटम की संख्या को सीमित, बाद में रखने के बनाने के लिए पिछले तत्व के लिए लिस्टबॉक्स की SelectedIndex सेट आइटम) ताकि आप अपनी स्मृति के सभी

1

Ive पहले टेक्स्टबॉक्स का उपयोग करता था। इसे अपने फॉर्म में जोड़ें, मल्टीप्लाइन संपत्ति को सत्य पर सेट करें, वर्टिकल के लिए स्क्रॉलबार। और अंत में यह निम्न कोड जोड़ें:

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

अनिवार्य रूप से अपनी, मौजूदा पाठ करने के लिए आपकी टिप्पणी जोड़ने यह भी एक linefeed जोड़कर। और अंत में लंबाई के पाठ की अंतिम बिट का चयन = 0. ScrollToCaret (अंतिम पंक्ति पर)

आशा इस मदद करता है पाठ बॉक्स जहां कर्सर स्थिति में है के लिए नीचे स्क्रॉल करने के लिए बाध्य करती है।

+0

मैं प्रत्येक पंक्ति के साथ धीमा हो जाएगा। –

+1

मैंने यह किया है। प्रदर्शन भयानक है। –

+3

जिन लोगों ने इसे वोट दिया है, उन्होंने वास्तव में इसे आजमाया नहीं है। –

2

मुझे यह सटीक चुनौती मिली है। मैंने इसे दो अलग-अलग तरीकों से हल किया है, दोनों काम और प्रदर्शन भारी भार के तहत होगा। एक सूची सूची दृश्य के साथ है। टेक्स्ट की पंक्ति में जोड़ा जा रहा है इस तरह है:

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

दूसरी तरह आभासी मोड में एक DataGridView के साथ है। मेरे पास वह कोड आसान नहीं है। वर्चुअल मोड आपका दोस्त है।

संपादित करें: फिर से पढ़ने, मैं तुम्हें कॉपी/पेस्ट काम करना चाहते हैं देखते हैं। हो सकता है कि RichText नियंत्रण ठीक प्रदर्शन करता है - पता नहीं, लेकिन यदि आप ListView या DataGrid का उपयोग करते हैं, तो आपको कॉपी/पेस्ट को काम करने के लिए और कोडिंग करना होगा।

4

मैं अपने सी # खिड़की प्रोग्राम (WinForms या WPF) एक Win32 कंसोल विंडो का उपयोग करने में यह करते हैं। मेरे पास एक छोटी सी कक्षा है जो कुछ बुनियादी Win32 एपीआई को लपेटती है, जब प्रोग्राम शुरू होता है तो मैं पतला बना देता हूं। यह सिर्फ एक उदाहरण है: 'वास्तविक जीवन' में आप एक सेटिंग या किसी अन्य चीज का उपयोग केवल कंसोल को सक्षम करने के लिए करते हैं जब आपको इसकी आवश्यकता होती है।

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 
5

तुम सिर्फ एक 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 आइटम संग्रह पर कोई निकासी नहीं है (लेकिन सूची में है)। आप सटीक कोड का पता लगा सकते हैं।

1
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(); 
    } 
} 
संबंधित मुद्दे

 संबंधित मुद्दे