Làm chủ cơ chế MDI (Multiple Document Interface).
Áp dụng Design Pattern Singleton để quản lý cửa sổ duy nhất (About).
Xử lý sự kiện bàn phím nâng cao (Hotkeys, Keyboard Hooking).
Thao tác với sự kiện chuột (Vẽ đồ họa cơ bản và Drag & Drop).
Tương tác hệ thống tập tin (Mở/Lưu file).
Project: Windows Forms App (.NET Framework).
Forms cần tạo:
frmMain: Form cha (IsMdiContainer = True).
frmEditor: Form con soạn thảo văn bản.
frmAbout: Form giới thiệu thông tin (Singleton).
Thiết lập thuộc tính: IsMdiContainer = True, WindowState = Maximized.
Thêm MenuStrip với cấu trúc:
File: New Editor, Open, Save, Exit.
Window: Cascade, Tile Horizontal, Tile Vertical, Close All.
Help: About Us.
Thêm StatusStrip để hiển thị số lượng cửa sổ con đang mở.
Mã nguồn quản lý số lượng con:
private void UpdateStatus() {
lblStatus.Text = $"Số cửa sổ đang mở: {this.MdiChildren.Length}";
}
Đảm bảo khi bấm "About Us", nếu cửa sổ đã mở thì không mở thêm bản sao mới mà chỉ Focus vào bản cũ.
private void aboutUsToolStripMenuItem_Click(object sender, EventArgs e) {
Form frm = this.MdiChildren.FirstOrDefault(f => f is frmAbout);
if (frm == null) {
frmAbout fAbout = new frmAbout { MdiParent = this };
fAbout.Show();
} else {
frm.Activate();
}
}
Kéo một RichTextBox (Dock = Fill) vào frmEditor.
Sự kiện Bàn phím: Chặn người dùng nhập số vào trình soạn thảo (nếu yêu cầu đặc thù).
private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e) {
if (char.IsDigit(e.KeyChar)) {
e.Handled = true; // Chặn không cho nhập số
MessageBox.Show("Vui lòng chỉ nhập chữ!");
}
}
Xử lý File (Open/Save): Viết tại frmMain để tương tác với Form con đang Active.
private void openToolStripMenuItem_Click(object sender, EventArgs e) {
OpenFileDialog ofd = new OpenFileDialog { Filter = "Text Files|*.txt|All Files|*.*" };
if (ofd.ShowDialog() == DialogResult.OK) {
frmEditor child = new frmEditor { MdiParent = this, Text = ofd.SafeFileName };
child.Show();
// Giả sử frmEditor có một public property để gán text
((RichTextBox)child.Controls[0]).Text = File.ReadAllText(ofd.FileName);
}
}
Tại một Form con tên là frmSketch:
Vẽ tự do: Sử dụng MouseDown, MouseMove, MouseUp.
Context Menu: Click chuột phải để đổi màu bút vẽ.
bool isDrawing = false;
Point lastPoint;
private void frmSketch_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
isDrawing = true;
lastPoint = e.Location;
}
}
private void frmSketch_MouseMove(object sender, MouseEventArgs e) {
if (isDrawing) {
using (Graphics g = this.CreateGraphics()) {
g.DrawLine(Pens.Black, lastPoint, e.Location);
}
lastPoint = e.Location;
}
}
private void frmSketch_MouseUp(object sender, MouseEventArgs e) => isDrawing = false;
Tại frmMain, thiết lập KeyPreview = True. Xử lý sự kiện KeyDown để đóng nhanh cửa sổ con đang chọn bằng phím ESC hoặc Ctrl + W.
Khi người dùng gõ phím vào RichTextBox, tiêu đề Form con phải hiện thêm dấu * (ví dụ: Document1*). Khi nhấn Save hoặc đóng Form, ứng dụng phải kiểm tra dấu * này để nhắc nhở lưu file.
Cho phép người dùng kéo một file .txt từ màn hình Desktop thả trực tiếp vào vùng MDI của ứng dụng để mở file đó.