Chương trình Liên Hoa được tách biệt ra 2 phần rõ rệt là Core (phần lõi) và GUI (phần giao diện đồ họa). Nói là GUI vì nó dùng WinForm. Nhưng khi thi hành mã lệnh Sen Trắng thì chúng ta vẫn cần một cửa sổ dòng lệnh.
Làm sao vừa xài WinForm vừa xài Console? Không biết bạn sẽ tính sao, chớ tôi thì định sẽ xài cái ConsoleTextBox mình vừa chế ra. Tất nhiên tôi không bắt ép bạn xài cái hộp console này, vì nói nào ngay, bài viết chỉ tập trung vào công đoạn thông dịch chứ không phải xây dựng giao diện. Tuy nhiên, nếu bạn thực sự muốn xài thử ConsoleTextBox thì mã lệnh của nó được ghi bên dưới. Bạn không nhất thiết phải quan tâm tới cách thức vận hành của nó. Cái bạn cần biết là 3
hàm ReadLine, Write vàWriteLine.
Using csharp Syntax Highlighting 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, 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 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.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 (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 (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() {
string result;
// Bắt đầu tiến trình đọc chuỗi
InReading = true;
// Cập nhật vị trí bắt đầu đọc
StartPos = this.SelectionStart;
// Đặt tiêu điểm vào hộp văn bản
this.Focus();
do
{
Application.DoEvents();
} while (ReadLineFinished == false);
if (Exiting)
return string.Empty;
// Lấy chuỗi ký tự từ vị trí bắt đầu đọc
result = this.Text.Substring(StartPos, 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>
/// 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
InReading = false;
// Cập nhật vị trí dấu nhắc
this.SelectionStart = StartPos + DataLength + 2 /* NewLine.Length */;
this.SelectionLength = 0; ReadLineFinished = false; AllowedMoves = 0; 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 chuỗi
if (InReading == 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
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 OnKeyPress(KeyPressEventArgs e) {
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 }
}
Parsed in 0.069 seconds, using GeSHi 1.0.8.4