• Vui lòng đọc nội qui diễn đàn để tránh bị xóa bài viết
  • Tìm kiếm trước khi đặt câu hỏi

Console TextBox

Các thủ thuật liên quan đến ứng dụng, biểu mẫu và control

Moderators: tungcan5diop, QUANITGROBEST

User avatar
alexanderdna
Guru
Guru
Posts: 214
Joined: Tue 14/07/2009 11:13 am
Location: Sài Gòn
Has thanked: 3 times
Been thanked: 15 times

Console TextBox

Postby alexanderdna » Thu 02/09/2010 10:17 pm

Thủ thuật: Console TextBox
Tác giả: Đặng Nhật Anh
Mô tả: Làm một hộp văn bản mô phỏng cửa sổ dòng lệnh (Console)



Do phải làm một chương trình mô phỏng máy ảo nên tôi có chế ra cái hộp văn bản Console này đặng xài, thay cho việc xài Console Application.
Vì khả năng còn thấp kém nên có thể mã lệnh còn nhiều sai và sót. Mong mọi người góp ý.

ConsoleTextBox kế thừa lớp TextBox có sẵn trong System.Windows.Forms. Nó cung cấp thêm 3 hàm thường gặp của cửa sổ dòng lệnh là: ReadLine, WriteWriteLine.

Cửa sổ dòng lệnh có một chức năng đặc biệt là có thể cho hiện lại các chuỗi đã nhập bằng cách bấm nút mũi tên lên xuống. Tôi chưa biết làm cái này, nên có lẽ phải chờ phiên bản sau vậy.

Xin xem mã lệnh:
  1. using System;
  2. using System.Drawing;
  3. using System.Windows.Forms;
  4.  
  5. namespace ConsoleTextbox
  6. {
  7.     /// <summary>
  8.     /// Hộp văn bản mô phỏng cửa sổ dòng lệnh
  9.     /// với các hàm ReadLine, Write và WriteLine.
  10.     /// </summary>
  11.     public class ConsoleTextBox : TextBox
  12.     {
  13.         #region Các biến thành viên dùng riêng
  14.  
  15.         // Thông điệp nhấp chuột trái và phải
  16.         private const int WM_LBUTTONDOWN = 0x201;
  17.         private const int WM_RBUTTONDOWN = 0x204;
  18.  
  19.         // Hằng dấu xuống hàng
  20.         private const string NewLine = "\r\n";
  21.  
  22.         // Biến báo hiệu tắt chương trình
  23.         private bool Exiting;
  24.  
  25.         // Biến báo hiệu tiến trình đọc chuỗi
  26.         private bool InReading;
  27.        
  28.         // Biến báo hiệu việc đọc chuỗi đã hoàn tất
  29.         private bool ReadLineFinished;
  30.  
  31.         // Vị trí bắt đầu đọc chuỗi
  32.         private int StartPos;
  33.  
  34.         // Số bước di chuyển của dấu nhắc
  35.         // tính từ vị trí bắt đầu đọc chuỗi
  36.         private int AllowedMoves;
  37.  
  38.         // Độ dài dữ liệu được nhập
  39.         // trong lúc đọc chuỗi
  40.         private int DataLength;
  41.  
  42.         #endregion
  43.  
  44.         #region Các hàm khởi lập
  45.  
  46.         public ConsoleTextBox()
  47.         {
  48.             this.Exiting = false;
  49.  
  50.             this.InReading = false;
  51.             this.ReadLineFinished = false;
  52.             this.StartPos = 0;
  53.             this.AllowedMoves = 0;
  54.             this.DataLength = 0;
  55.  
  56.             this.Multiline = true;
  57.             this.ScrollBars = ScrollBars.Vertical;
  58.             this.Font = new Font("Courier New", 10f, FontStyle.Bold);
  59.             this.ForeColor = Color.Lime;
  60.             this.BackColor = Color.Black;
  61.         }
  62.  
  63.         /// <summary>
  64.         /// Thay đổi diện mạo hộp văn bản.
  65.         /// </summary>
  66.         /// <param name="font">Phông chữ</param>
  67.         /// <param name="fgcolor">Màu chữ</param>
  68.         /// <param name="bgcolor">Màu nền</param>
  69.         public void SetAppearance(Font font, Color fgcolor, Color bgcolor)
  70.         {
  71.             this.Font = font;
  72.             this.ForeColor = fgcolor;
  73.             this.BackColor = bgcolor;
  74.         }
  75.  
  76.         /// <summary>
  77.         /// Thay đổi diện mạo hộp văn bản.
  78.         /// </summary>
  79.         /// <param name="font">Phông chữ</param>
  80.         public void SetAppearance(Font font)
  81.         {
  82.             this.Font = font;
  83.         }
  84.  
  85.         /// <summary>
  86.         /// Thay đổi diện mạo hộp văn bản.
  87.         /// </summary>
  88.         /// <param name="fgcolor">Màu chữ</param>
  89.         /// <param name="bgcolor">Màu nền</param>
  90.         public void SetAppearance(Color fgcolor, Color bgcolor)
  91.         {
  92.             this.ForeColor = fgcolor;
  93.             this.BackColor = bgcolor;
  94.         }
  95.  
  96.         #endregion
  97.  
  98.         #region Các hàm chức năng
  99.  
  100.         /// <summary>
  101.         /// Ghi một chuỗi ký tự.
  102.         /// </summary>
  103.         /// <param name="s">Chuỗi cần ghi</param>
  104.         public void Write(string s)
  105.         {
  106.             if (Exiting == false)
  107.             {
  108.                 this.AppendText(s);
  109.                 this.Focus();
  110.             }
  111.         }
  112.  
  113.         /// <summary>
  114.         /// Ghi một chuỗi ký tự kèm dấu xuống hàng.
  115.         /// </summary>
  116.         /// <param name="s">Chuỗi cần ghi</param>
  117.         public void WriteLine(string s)
  118.         {
  119.             if (Exiting == false)
  120.             {
  121.                 this.AppendText(s + NewLine);
  122.                 this.Focus();
  123.             }
  124.         }
  125.  
  126.         /// <summary>
  127.         /// Đọc một chuỗi ký tự kết thúc bằng thao tác nhấn Enter.
  128.         /// </summary>
  129.         /// <returns>Chuỗi đọc được</returns>
  130.         public string ReadLine()
  131.         {
  132.             string result;
  133.  
  134.             // Bắt đầu tiến trình đọc chuỗi
  135.             InReading = true;
  136.  
  137.             // Cập nhật vị trí bắt đầu đọc
  138.             StartPos = this.SelectionStart;
  139.  
  140.             // Đặt tiêu điểm vào hộp văn bản
  141.             this.Focus();
  142.  
  143.             // Vòng lặp chờ Enter
  144.             do
  145.             {
  146.                 Application.DoEvents();
  147.             } while (ReadLineFinished == false);
  148.  
  149.             if (Exiting)
  150.                 return string.Empty;
  151.  
  152.             // Lấy chuỗi ký tự từ vị trí bắt đầu đọc
  153.             result = this.Text.Substring(StartPos, DataLength);
  154.  
  155.             // Thêm dòng mới (vì thao tác Enter sẽ không thực hiện việc này)
  156.             this.AppendText(NewLine);
  157.  
  158.             // Hoàn nguyên các biến
  159.             this.Reset();
  160.  
  161.             return result;
  162.         }
  163.  
  164.         /// <summary>
  165.         /// Hoàn nguyên các biến cho phiên đọc chuỗi kế tiếp
  166.         /// </summary>
  167.         private void Reset()
  168.         {
  169.             // Dứt tiến trình đọc
  170.             InReading = false;
  171.  
  172.             // Cập nhật vị trí dấu nhắc
  173.             this.SelectionStart = StartPos + DataLength + 2 /* NewLine.Length */;
  174.             this.SelectionLength = 0;
  175.  
  176.             ReadLineFinished = false;
  177.             AllowedMoves = 0;
  178.             DataLength = 0;
  179.  
  180.             this.Focus();
  181.         }
  182.  
  183.         #endregion
  184.  
  185.         #region Thay đổi một số hàm cấp thấp
  186.  
  187.         protected override void OnKeyDown(KeyEventArgs e)
  188.         {
  189.             // Nếu không phải đang trong tiến trình đọc chuỗi
  190.             if (InReading == false)
  191.             {
  192.                 // thì hủy bỏ sự kiện
  193.                 e.SuppressKeyPress = true;
  194.                 return;
  195.             }
  196.  
  197.             switch (e.KeyCode)
  198.             {
  199.                 case Keys.Enter:
  200.                     // Hoàn tất tiến trình đọc chuỗi
  201.                     ReadLineFinished = true;
  202.                     // Bỏ qua sự kiện nhấn Enter
  203.                     e.SuppressKeyPress = true;
  204.                     break;
  205.                 case Keys.Back:
  206.                     // Chỉ khi nào có ít nhất 1 ký tự từ vị trí bắt đầu
  207.                     if (AllowedMoves > 0)
  208.                     {
  209.                         // thì các biến dưới đây mới giảm trị
  210.                         AllowedMoves--;
  211.                         DataLength--;
  212.                     }
  213.                     else
  214.                     {
  215.                         // Không thì hủy bỏ luôn sự kiện
  216.                         e.SuppressKeyPress = true;
  217.                         // (để khỏi xóa lầm dữ liệu trước phiên đọc chuỗi)
  218.                     }
  219.                     break;
  220.                 case Keys.Delete:
  221.                     // Chỉ khi nào dấu nhắc nằm giữa chuỗi đang đọc
  222.                     if (AllowedMoves < DataLength)
  223.                     {
  224.                         // thì độ dài dữ liệu mới bị giảm trị
  225.                         DataLength--;
  226.                     }
  227.                     break;
  228.                 case Keys.Up:
  229.                 case Keys.Down:
  230.                     // Bỏ qua sự kiện này
  231.                     e.SuppressKeyPress = true;
  232.                     break;
  233.                 case Keys.Left:
  234.                     // Giảm AllowedMoves nếu có ít nhất 1 bước di chuyển
  235.                     if (AllowedMoves > 0)
  236.                         AllowedMoves--;
  237.                     else
  238.                         e.SuppressKeyPress = true;
  239.                     break;
  240.                 case Keys.Right:
  241.                     // Nếu dấu nhắc chưa đạt tới cuối dữ liệu nhập
  242.                     // thì tăng lên 1 bước di chuyển
  243.                     if (AllowedMoves < DataLength)
  244.                         AllowedMoves++;
  245.                     else
  246.                         e.SuppressKeyPress = true;
  247.                     break;
  248.             }
  249.         }
  250.  
  251.         protected override void OnKeyPress(KeyPressEventArgs e)
  252.         {
  253.             if (char.IsControl(e.KeyChar) == false)
  254.             {
  255.                 AllowedMoves++;
  256.                 DataLength++;
  257.             }
  258.         }
  259.  
  260.         protected override void Dispose(bool disposing)
  261.         {
  262.             ReadLineFinished = true;
  263.             Exiting = true;
  264.             base.Dispose(disposing);
  265.         }
  266.  
  267.         protected override void WndProc(ref Message m)
  268.         {
  269.             switch (m.Msg)
  270.             {
  271.                 case WM_LBUTTONDOWN:
  272.                 case WM_RBUTTONDOWN:
  273.                     // Bỏ qua các thông điệp nhấp chuột
  274.                     return;
  275.             }
  276.             base.WndProc(ref m);
  277.         }
  278.  
  279.         #endregion
  280.     }
  281. }
  282.  


Cập nhật Phiên bản 2 ngày 21/10/2010
Phiên bản này có thêm hàm ReadChar và hỗ trợ thao tác dán văn bản bằng tổ hợp phím Ctrl+V.
[csharp]using System;
using System.Drawing;
using System.Windows.Forms;

namespace ConsoleTextbox
{
/// <summary>
/// Hộp văn bản mô phỏng cửa sổ dòng lệnh
/// với các hàm ReadLine, ReadChar, Write và WriteLine.
/// </summary>
public class ConsoleTextBox : TextBox
{
#region Các biến thành viên dùng riêng

// Thông điệp nhấp chuột trái và phải
private const int WM_LBUTTONDOWN = 0x201;
private const int WM_RBUTTONDOWN = 0x204;

// Hằng dấu xuống hàng
private const string NewLine = "\r\n";

// Biến báo hiệu tắt chương trình
private bool Exiting;

// Biến báo hiệu tiến trình đọc chuỗi
private bool InReading;

// Biến báo hiệu việc đọc ký tự
private bool InCharReading;

// Biến lưu ký tự đọc được
private char GottenChar;

// Biến báo hiệu việc đọc chuỗi đã hoàn tất
private bool ReadLineFinished;

// Vị trí bắt đầu đọc chuỗi
private int StartPos;

// Số bước di chuyển của dấu nhắc
// tính từ vị trí bắt đầu đọc chuỗi
private int AllowedMoves;

// Độ dài dữ liệu được nhập
// trong lúc đọc chuỗi
private int DataLength;

#endregion

#region Các hàm khởi lập

public ConsoleTextBox()
{
this.Exiting = false;

this.InReading = false;
this.InCharReading = false;
this.ReadLineFinished = false;
this.StartPos = 0;
this.AllowedMoves = 0;
this.DataLength = 0;

this.Multiline = true;
this.ScrollBars = ScrollBars.Vertical;
this.Font = new Font("Courier New", 10f, FontStyle.Bold);
this.ForeColor = Color.Lime;
this.BackColor = Color.Black;
}

/// <summary>
/// Thay đổi diện mạo hộp văn bản.
/// </summary>
/// <param name="font">Phông chữ</param>
/// <param name="fgcolor">Màu chữ</param>
/// <param name="bgcolor">Màu nền</param>
public void SetAppearance(Font font, Color fgcolor, Color bgcolor)
{
this.Font = font;
this.ForeColor = fgcolor;
this.BackColor = bgcolor;
}

/// <summary>
/// Thay đổi diện mạo hộp văn bản.
/// </summary>
/// <param name="font">Phông chữ</param>
public void SetAppearance(Font font)
{
this.Font = font;
}

/// <summary>
/// Thay đổi diện mạo hộp văn bản.
/// </summary>
/// <param name="fgcolor">Màu chữ</param>
/// <param name="bgcolor">Màu nền</param>
public void SetAppearance(Color fgcolor, Color bgcolor)
{
this.ForeColor = fgcolor;
this.BackColor = bgcolor;
}

#endregion

#region Các hàm chức năng

/// <summary>
/// Ghi một chuỗi ký tự.
/// </summary>
/// <param name="s">Chuỗi cần ghi</param>
public void Write(string s)
{
if (this.Exiting == false)
{
this.AppendText(s);
this.Focus();
}
}

/// <summary>
/// Ghi một chuỗi ký tự kèm dấu xuống hàng.
/// </summary>
/// <param name="s">Chuỗi cần ghi</param>
public void WriteLine(string s)
{
if (this.Exiting == false)
{
this.AppendText(s + NewLine);
this.Focus();
}
}

/// <summary>
/// Đọc một chuỗi ký tự kết thúc bằng thao tác nhấn Enter.
/// </summary>
/// <returns>Chuỗi đọc được</returns>
public string ReadLine()
{
if (this.InCharReading)
return string.Empty;

string result;

// Bắt đầu tiến trình đọc chuỗi
this.InReading = true;

// Cập nhật vị trí bắt đầu đọc
this.StartPos = this.SelectionStart;

// Đặt tiêu điểm vào hộp văn bản
this.Focus();

// Vòng lặp chờ Enter
do
{
Application.DoEvents();
} while (this.ReadLineFinished == false);

if (this.Exiting)
return string.Empty;

// Lấy chuỗi ký tự từ vị trí bắt đầu đọc
result = this.Text.Substring(this.StartPos, this.DataLength);

// Thêm dòng mới (vì thao tác Enter sẽ không thực hiện việc này)
this.AppendText(NewLine);

// Hoàn nguyên các biến
this.Reset();

return result;
}

/// <summary>
/// Đọc một ký tự duy nhất và cho hiện hoặc ẩn ký tự đó tùy theo yêu cầu.
/// </summary>
/// <param name="intercept"><para>True: ẩn ký tự đọc được.</para>
/// <para>False: hiện ký tự đọc được.</para></param>
/// <returns>Ký tự đọc được</returns>
public char ReadChar(bool intercept)
{
if (this.InReading)
return '\0';

char result;

this.InCharReading = true;

this.StartPos = this.SelectionStart;

this.Focus();

do
{
Application.DoEvents();
} while (this.InCharReading);

if (this.Exiting)
return '\0';

result = GottenChar;

if (intercept)
this.Text = this.Text.Remove(this.StartPos);

this.Reset();

return result;
}

/// <summary>
/// Hoàn nguyên các biến cho phiên đọc chuỗi kế tiếp
/// </summary>
private void Reset()
{
// Dứt tiến trình đọc
this.InReading = false;

// Cập nhật vị trí dấu nhắc
this.SelectionStart = StartPos + DataLength + 2 /* NewLine.Length */;
this.SelectionLength = 0;

this.ReadLineFinished = false;
this.AllowedMoves = 0;
this.DataLength = 0;

this.Focus();
}

#endregion

#region Thay đổi một số hàm cấp thấp

protected override void OnKeyDown(KeyEventArgs e)
{
// Nếu không phải đang trong tiến trình đọc
if (this.InReading == false && this.InCharReading == false)
{
// thì hủy bỏ sự kiện
e.SuppressKeyPress = true;
return;
}

switch (e.KeyCode)
{
case Keys.Enter:
// Hoàn tất tiến trình đọc chuỗi
ReadLineFinished = true;
// Bỏ qua sự kiện nhấn Enter
e.SuppressKeyPress = true;
break;
case Keys.Back:
// Chỉ khi nào có ít nhất 1 ký tự từ vị trí bắt đầu
if (AllowedMoves > 0)
{
// thì các biến dưới đây mới giảm trị
AllowedMoves--;
DataLength--;
}
else
{
// Không thì hủy bỏ luôn sự kiện
e.SuppressKeyPress = true;
// (để khỏi xóa lầm dữ liệu trước phiên đọc chuỗi)
}
break;
case Keys.Delete:
// Chỉ khi nào dấu nhắc nằm giữa chuỗi đang đọc
if (AllowedMoves < DataLength)
{
// thì độ dài dữ liệu mới bị giảm trị
DataLength--;
}
break;
case Keys.Up:
case Keys.Down:
// Bỏ qua sự kiện này
e.SuppressKeyPress = true;
break;
case Keys.Left:
// Giảm AllowedMoves nếu có ít nhất 1 bước di chuyển
if (AllowedMoves > 0)
AllowedMoves--;
else
e.SuppressKeyPress = true;
break;
case Keys.Right:
// Nếu dấu nhắc chưa đạt tới cuối dữ liệu nhập
// thì tăng lên 1 bước di chuyển
if (AllowedMoves < DataLength)
AllowedMoves++;
else
e.SuppressKeyPress = true;
break;
}
}

protected override void OnKeyUp(KeyEventArgs e)
{
// Xác minh hành động Ctrl+V (dán văn bản)
if ((e.Modifiers & Keys.Control) != 0 && e.KeyCode == Keys.V)
{
// Nếu đang đọc dòng
if (this.InReading)
{
// Lấy vị trí hiện tại
int currentPos = this.StartPos + this.AllowedMoves;

// Lấy dữ liệu vừa dán
string pasted = this.Text.Substring(currentPos,
this.TextLength - currentPos - this.DataLength + this.AllowedMoves);

// Chỉnh lại độ dài dữ liệu
this.DataLength += pasted.Length;

// Chỉnh lại số bước di chuyển cho phép
this.AllowedMoves += pasted.Length;
}
}
}

protected override void OnKeyPress(KeyPressEventArgs e)
{
// Nếu đang đọc ký tự
if (this.InCharReading)
{
this.GottenChar = e.KeyChar;
this.InCharReading = false;

return;
}

// Nếu đọc được một ký tự thì tăng độ dài dữ liệu và bước di chuyển
if (char.IsControl(e.KeyChar) == false)
{
AllowedMoves++;
DataLength++;
}
}

protected override void Dispose(bool disposing)
{
ReadLineFinished = true;
Exiting = true;
base.Dispose(disposing);
}

protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
// Bỏ qua các thông điệp nhấp chuột
return;
}
base.WndProc(ref m);
}

#endregion
}
}[/csharp]

Tập tin DLL (và bản mô tả XML) có đính kèm trong bài.
Attachments
ascontxt.zip
AnhSoftware ConsoleTextBox
(3.71 KiB) Downloaded 314 times
Last edited by alexanderdna on Thu 21/10/2010 9:32 pm, edited 2 times in total.



User avatar
alexanderdna
Guru
Guru
Posts: 214
Joined: Tue 14/07/2009 11:13 am
Location: Sài Gòn
Has thanked: 3 times
Been thanked: 15 times

Re: Console TextBox

Postby alexanderdna » Thu 21/10/2010 9:40 pm

Đã cập nhật phiên bản 2 với hai điểm mới:
- Hàm ReadChar dùng để đọc ký tự. Có thể cho hiện hoặc ẩn ký tự được đọc.
- Hỗ trợ dán văn bản bằng Ctrl+V.


Return to “[.NET] Ứng dụng - Form và Control”

Who is online

Users browsing this forum: No registered users and 1 guest