Xây dựng ứng dụng từ điển đơn giản trong C#

Mục đích:

xây dựng một ứng dụng từ điển đơn giản ví dụ từ điển Anh – Việt, Việt – Anh, v.v. sử dụng hệ quản trị cơ sở dữ liệu Access để quản lý dữ liệu.


Hướng dẫn:

  1. Tạo giao diện

Trong ứng dụng này, bạn sẽ học cách tạo một từ điển đơn giản Anh – Việt. Người sử dụng sẽ nhập một từ tiếng anh, và mỗi từ đó sẽ được tìm kiếm trong cơ sở dữ liệu của từ điển và trả về nghĩa tiếng việt tương ứng. Một từ tiếng anh sẽ được chọn từ một list các từ mà tồn tại trong CSDL hoặc người sử dụng tự gõ trong hôp search box. Các từ mà được gõ trong hộp search textbox sẽ tìm kiếm và duyệt qua list này. Nếu tìm thấy từ này, từ sẽ được chọn trong list và nghĩa của nó sẽ hiển thị bên phải trong một RichTextbox.

Chúng ta sử dụng hệ quản trị cơ sở dữ liệu Access để lưu trữ các từ tiếng anh và nghĩa tiếng việt của chúng. Khi form ban đầu khởi động, các từ tiếng anh sẽ được lấy trong tệp CSDL và nạp lên một list box (xem hình dưới).

anh4

Trong hộp RichTextbox, các từ tiếng anh sẽ có màu xanh, còn các từ tiếng việt sẽ màu đen.

Bây giờ, bạn đã hiểu toàn bộ ý tưởng của dự án, hãy chuyển sang giai đoạn thiết kế giao diện. Các bạn hoàn thành theo các bước sau:

  • Mở Visual Studio 2008 và tạo một Project bằng cách tới menu File > New và kích trên ..
  • Hộp thoại New Project mở ra
  • Trong hộp thoại New Project, dưới Project Types chọn Visual C#, và chọn Windows Form Application dưới Templates. Trong hộp Name đánh: FITADictionary

anh5

  • Bạn kích vào nút Browse… để chọn nơi lưu trữ dự án của bạn
  • Click OK. Bạn sẽ nhìn thấy một form mặc định tên là Form1
  • Kích chuột phải trên form này và chọn Properties để hiển thị cửa sổ Properties của form.
  • Trên cửa sổ Properties, thiết lập thuộc tính của form như sau:
    • Text = FITA Dictionary
    • Name = frmDic
    • Backcolor = InactiveCaption
    • FormBorderStyle = FixedDialog
  • Mở thanh Toolbox ở bên trái của cửa sổ Visual Studio, kéo control ListBox tới form, thiết lập thuộc tính Name = lstTerms
  • Kéo thả Textbox nằm phía trên của list box, thiết lập thuộc tính Name = txtSearch
  • Rồi kéo và thả RichTextbox tới bên phải của list box, thiết lập thuộc tính:
    • Name = rtbResult
    • Forecolor = MenuHighlight
    • ReadOnly = True ( không cho phép người dùng chỉnh sửa text trong RichTextbox)
  • Để thêm được menu vào form, bạn cần kéo và thử MenuStrip từ Toolbox

anh6

  • Đánh &File vào chỗ ô Type Here và trong hộp tiếp theo trong ô Type Here là &Help
  • Đánh &Close vào ô Type Here dưới  menu File và đánh menu  &About… trong ô Type Here dưới menu Help
  1. Tạo CSDL

Bây giờ chúng ta đã kết thúc thiết kế giao diên của ứng dụng từ điển. Tiếp theo chúng ta sẽ chuyển sang giai đoạn tạo CSDL. Bạn mở ứng dụng Microsoft Access và Save dữ liệu vào thư mục bin/debug của ứng dụng của bạn với tên tệp là FITADic.accdb. CSDL này có một bảng, đặt tên là tblAVDic và có 2 cột (field) là EnTermVnMean.

Ví dụ  dữ liệu được nhập như các trường ở dưới:

anh7

  1. Code

Sau khi bạn tạo CSDL xong và nhập dữ liệu mẫu, bạn có thể chuyển sang giai đoạn tạo kết nối và đặt dữ liệu vào listbox.

Đoạn code dưới sẽ giúp bạn kết nối tới tệp CSDL và lấy dữ liệu đặt vào lstTerm:

– Kích đúp trên form để mở cửa sổ code, bạn sẽ nhìn thây đoạn code như sau:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Data.OleDb;

namespace FITADictionary
{
    public partial class frmDic : Form
    {
        public frmDic()
        {
            InitializeComponent();
        }
        private void frmDic_Load(object sender, EventArgs e)
        {
        }
    }
}

  • Bạn cần thêm câu lệnh usingData.OleDb; ở ngay phần đầu để sử dụng các thư viện kết nối CSDL theo kiểu OLEDB.

– Dưới câu lệnh “public partial class frmDic : Form” bạn gõ thêm các dòng code:


private OleDbConnection cn;//tạo đối tượng kết nối
private OleDbDataReader reader;//tạo đối tượng reader
private OleDbCommand com;//tạo đối tượng command
private DataSet rs;//tạo đối tượng dataset	
private OleDbDataAdapter ad;//tạo đối tượng data adapter 

Đoạn code này sẽ khai báo một biến cn của lớp OleDbConnection, biến reader của lớp OleDbReader, biến com của lớp OleDbCommand, biến rs của lớp DataSet và biến ad của lớp OleDbDataAdapter. Các biến này sẽ được sử dụng để tạo các đối tượng của các kiểu lớp này.

– Tạo một phương thức MyConnect() như đoạn code dưới đây:


private void MyConnect()
{
    try
    {
        //kết nối tới CSDL
        rs = new DataSet();
        //Provider=Microsoft.Jet.OLEDB.4.0;Data Source="\\vmware-host\Shared Folders\Documents\Visual Studio 2008\Projects\FITADictionary\FITADictionary\bin\Debug\FITADic.accdb"
        cn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Application.StartupPath + "\\FITADic.accdb;");
        cn.Open();
        ad = new OleDbDataAdapter("SELECT * FROM tblAVDic ORDER BY EnTerm", cn);
        ad.Fill(rs, "tblAVDic");
        com = new OleDbCommand("SELECT EnTerm FROM tblAVDic ORDER BY EnTerm", cn);
        reader = com.ExecuteReader();
        //xóa trắng listbox
        lstTerms.Items.Clear();
        //xóa trắng ô hiện kết quả
        rtbResult.Text = "";
        //nạp dữ liệu lên listbox
        while (reader.Read())
        {
            lstTerms.Items.Add(reader[0].ToString());
        }
    }
    catch (Exception ex) { }
    txtSearch.Focus();
}

Giải thích code: đoạn code này bắt đầu bởi việc tạo một đối tượng DataSet để lưu trữ các bảng dữ liệu từ CSDL và một đối tượng Connection để kết nối tới tệp CSDL.


//kết nối tới CSDL
rs = new DataSet();
cn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + Application.StartupPath + "\\FITADic.accdb;");
cn.Open();

Đối tượng Adapter được tạo để nhận dữ liệu từ bảng tblAVDic và dữ liệu được điền tới đối tượng rs của DataSet bằng việc dùng phương thức Fill() của Adapter:


ad = new OleDbDataAdapter("SELECT * FROM tblAVDic ORDER BY EnTerm", cn);
ad.Fill(rs, "tblAVDic");

Đối tượng com của Command cũng được tạo để nhận dữ liệu từ bảng dữ liệu và đặt vào trong list box.


com = new OleDbCommand("SELECT EnTerm FROM tblAVDic ORDER BY EnTerm", cn);
reader = com.ExecuteReader();
//xóa trắng listbox
lstTerms.Items.Clear();
//xóa trắng ô hiện kết quả
rtbResult.Text = "";
//nạp dữ liệu lên listbox
while (reader.Read())
{
     lstTerms.Items.Add(reader[0].ToString());
}

Hộp search textbox sẽ được focus (con trỏ sẽ nhấp nháy ở đây) để kích hoạt trong hộp này.


txtSearch.Focus();

Đặt phương thức MyConnect() trong sự kiện form_load, list box lstTerms sẽ được nạp các từ tiếng anh:


private void frmDic_Load(object sender, EventArgs e)
{
   MyConnect();
}

Chú ý: chúng ta dùng khối try … catch để bắt bất kỳ lỗi nào có thể xảy ra. Bây giờ bạn đã gắn được dữ liệu vào listbox lstTerms khi form load. Bước tiếp theo là viết code C# để tạo một chức năng làm việc search của textbox.

Để ô search của textbox làm việc được bạn cần thêm code sau trong sự kiện TextChanged của Textbox:


private void txtSearch_TextChanged(object sender, EventArgs e)
{
	int i;
      DataRow dr;
      try
      {
         for (i = 0; i <= lstTerms.Items.Count - 1; i++)
         {
           if (txtSearch.Text.Trim().ToUpper() == lstTerms.Items[i].ToString().ToUpper().Substring(0, txtSearch.TextLength))
           {
             //Chọn các item được so khớp với hộp search
             lstTerms.SelectedIndex = i;
             //hiển thị nghĩa của từ tìm thấy
             dr = rs.Tables[0].Rows[i];
             rtbResult.Clear();
             rtbResult.Text = lstTerms.SelectedItem.ToString() + "\n" + dr[1].ToString().Trim();
             HighLight();
             break;
           }
          }
       }
       catch (Exception ex) { }
}

Khi người dùng đánh một từ vào trong textbox txtSearch, từ này sẽ được so sánh với các từ trong listbox. Nếu các từ được so khớp thì từ trong listbox sẽ được chọn và nghĩa của từ đó sẽ được hiển thị ở RichTexbox rtbResult. Thủ tục HightLight() sẽ được gọi để thay đổi màu của từ  tiếng anh trong RichTextbox rtbResult. Thủ tục này sẽ được thảo luận trong bước tiếp theo.

Nếu người sử dụng chọn một từ trong list thay việc đánh vào hộp search, bạn cần viết một code trong sự kiện SelectedIndexChanged của listbox:


private void lstTerms_SelectedIndexChanged(object sender, EventArgs e)
{
   DataRow dr;
   dr = rs.Tables[0].Rows[lstTerms.SelectedIndex];
   rtbResult.Clear(); //xóa kết quả
   rtbResult.Text = lstTerms.SelectedItem.ToString() + "\n" + dr[1].ToString().Trim();
   HighLight();
}

Chú ý: Đối tượng dr của DataRow thường được sử dụng để nhận dữ liệu  của một hàng được chọn của bảng. Thay đổi màu của các từ tiếng anh và các ký tự dịch tiếng việt  trong RichTextbox, bạn cần phương thức HighLight() như ở dưới:


private void HighLight()
{
    try
    {
        //Màu cho các từ tiếng anh
        Regex rex = new Regex(lstTerms.SelectedItem.ToString());
        MatchCollection mc = rex.Matches(rtbResult.Text);
        int StarCursorPosition = rtbResult.SelectionStart;
        foreach (Match m in mc)
        {
            int starIndex = m.Index;
            int StopIndex = m.Length;
            rtbResult.Select(starIndex, StopIndex);
            rtbResult.SelectionColor = Color.Blue;
            rtbResult.SelectionStart = StarCursorPosition;
        }
        //Màu cho phân loại từ tiếng anh
        char[] c = rtbResult.Text.ToString().ToCharArray();
        //màu đỏ cho các loại từ v.,a., and n.
        int i;
        for (i = 1; i <= rtbResult.Text.ToString().Length - 2; i++)
        {
            if ((c[i] == '.' && c[i - 1] == 'v') || (c[i] == '.' && c[i - 1] == 'a') || (c[i] == '.' && c[i - 1] == 'n'))
            {
                rtbResult.SelectionStart = i - 1;
                rtbResult.SelectionLength = 2;
                rtbResult.SelectionColor = Color.Red;

            }
        }
        //màu đỏ cho adj., adv.
        for (i = 3; i <= rtbResult.Text.ToString().Length - 1; i++)
        {
            if ((c[i] == '.' && c[i - 1] == 'j' && c[i - 2] == 'd') || (c[i] == '.' && c[i - 1] == 'g' && c[i - 2] == 'i') || (c[i] == '.' && c[i - 1] == 'v' && c[i - 2] == 'd'))
            {
                rtbResult.SelectionStart = i - 3;
                rtbResult.SelectionLength = 4;
                rtbResult.SelectionColor = Color.Red;
            }
        }
    }
    catch (Exception ex) { }
}

Sử dụng code ở trên, các text tiếng anh như v., a., n., adj., adv. sẽ có màu đỏ và các từ tiếng việt sẽ có màu đen. Giữ text ở trong RichTextox là kiểu màu MenuHighlight.

Làm cho form thân thiện hơn, tức khi các form  thay đổi kích thước thì các item trong form sẽ thay đổi theo kích thước của form. Bạn thực hiện code dưới đây trong sự kiện Resize của form:


private void frmDic_Resize(object sender, EventArgs e)
{
    if (this.WindowState == FormWindowState.Maximized)
    {
        lstTerms.Height = this.Height;
        txtSearch.Height = this.Height;
        rtbResult.Width = this.Width;
    }
}

Chú ý: nếu bạn thử thay thay đổi kích thước của form và đoạn code ở trên sẽ không hoạt động, và bạn cần phải thêm dòng code khác trong sự kiện form_load:


private void frmDic_Load(object sender, EventArgs e)
{
    MyConnect();
    this.Resize += new EventHandler(frmDic_Resize); //thêm code ở đây
}

Khi form load, nhiều đối tượng như: cn, rs, ad, com, và reader, là cũng được tạo trong chương trình cho sử dụng và các đối tượng này sẽ chiếm không gian bộ nhớ máy tính. Khi form đóng, các đối tượng này nên được giải phóng từ bộ nhớ:


private void frmDic_FormClosed(object sender, FormClosedEventArgs e)
{
    cn.Close();
    cn = null;
    com = null;
    reader = null;
    ad = null;
    rs = null;
}

Bạn cũng cần thêm dòng code:

  this.FormClosed += new FormClosedEventHandler(frmDic_FormClosed); 

tới sự kiện form load.


private void frmDic_Load(object sender, EventArgs e)
{
    MyConnect();
    this.Resize += new EventHandler(frmDic_Resize); //thêm code ở đây
    this.FormClosed += new FormClosedEventHandler(frmDic_FormClosed);
}

Khi đóng chương trình, người sử dụng kích trên menu con Close của menu File. Công việc này có thể làm đơn giản bằng cách gắn code trong sự kiện Click của menu Close:


private void mnuFileClose_Click(object sender, EventArgs e)
{
    Close();
}

Bây giờ các bạn chạy chương trình của bạn và thưởng thức thành quả của mình.

  1. Tải mã nguồn tại đây
  1. Những cải tiến

Có thể bạn sẽ thích…

20 phản hồi

  1. Hiếu viết:

    Chào admin, mình đang học c# và thấy project từ điển này rất hay.
    Bạn có thể cho mình xin source code được không ạ? Nếu được thì vui lòng gửi vào mail của mình nha, cảm ơn bạn.

  2. nguyễn anh dũng viết:

    bạn có thể làm hộ mình 1 báo cáo về từ điển này đc k ạ. mình có đề tài chuyên ngành mà thấy cái này đơn giản mà hay quá

  3. Hoàng Văn Phương viết:

    private void HighLight()
    {
    try
    {
    //Màu cho các từ tiếng anh
    Regex rex = new Regex(lstTerms.SelectedItem.ToString());
    MatchCollection mc = rex.Matches(rtbResult.Text);
    int StarCursorPosition = rtbResult.SelectionStart;
    foreach (Match m in mc)
    {
    int starIndex = m.Index;
    int StopIndex = m.Length;
    rtbResult.Select(starIndex, StopIndex);
    rtbResult.SelectionColor = Color.Blue;
    rtbResult.SelectionStart = StarCursorPosition;
    }
    //Màu cho phân loại từ tiếng anh
    char[] c = rtbResult.Text.ToString().ToCharArray();
    //màu đỏ cho các loại từ v.,a., and n.
    int i;
    for (i = 1; i <= rtbResult.Text.ToString().Length – 2; i++)
    {
    if ((c[i] == '.' && c[i – 1] == 'v') || (c[i] == '.' && c[i – 1] == 'a') || (c[i] == '.' && c[i – 1] == 'n'))
    {
    rtbResult.SelectionStart = i – 1;
    rtbResult.SelectionLength = 2;
    rtbResult.SelectionColor = Color.Red;

    }
    }
    //màu đỏ cho adj., adv.
    for (i = 3; i <= rtbResult.Text.ToString().Length – 1; i++)
    {
    if ((c[i] == '.' && c[i – 1] == 'j' && c[i – 2] == 'd') || (c[i] == '.' && c[i – 1] == 'g' && c[i – 2] == 'i') || (c[i] == '.' && c[i – 1] == 'v' && c[i – 2] == 'd'))
    {
    rtbResult.SelectionStart = i – 3;
    rtbResult.SelectionLength = 4;
    rtbResult.SelectionColor = Color.Red;
    }
    }
    }
    catch (Exception ex) { }
    }
    cái phần này chương trình báo chưa khai báo "regex, matchcollection, match , mc "

  4. Vinh viết:

    Sao em tải Solution mẫu của anh về chạy thử mà nó không đọc Data vào ListView anh nhĩ.
    Trong List view trống trơn không có gì cả.
    Em thử Built lại vẫn vậy.

  5. Trung viết:

    Cảm ơn bạn vì bộ code. Mình dân ngoại đạo với lập trình nên vô cùng thích. Mình hỏi thêm một chút nhé. Mình muốn bảo mật CSDL của access của từ điển này để không ai xem được thì làm thế nào? Ý mình muốn làm một bộ cho học sinh của mình nhưng không muốn chúng xem từ mà buộc phải tra từ. Cảm ơn bạn nhiều.

    • Phan Tiến viết:

      Về câu hỏi của bạn đều có phương án cả, có thể thực hiện bảo mật cho Cơ sở dữ liệu hoặc bảo mật trên chương trình (phần mềm) bằng cách phân quyền.
      1. Bảo mật về cơ sở dữ liệu, bạn có thể thiết lập mật khẩu cho CSDL của bạn, và khi kết nối với CDSL, bạn sẽ truyền thêm vào mật khẩu để truy cập
      2. Bảo mật trên phần mềm, sẽ thiết kế thêm phần phân quyền (người sử dụng có quyền A thì chỉ được sử dụng các chức năng được cấp với quyền A), như vậy trong CSDL của bạn tối thiểu cần có thêm bảng dữ liệu tài khoản người dùng và phân quyền. Khi đó người sử dụng cần phải đăng nhập, nếu đăng nhập đúng tài khoản, đúng quyền được cấp thì sẽ được sử dụng các chứng năng tương ứng trên phần mềm.

  6. minhhuy viết:

    cho mik xin link down ứng dụng vs ạ

  7. dangha viết:

    cho em hỏi mình có thể thay ngôn ngữ tiếng anh bằng loại khác được không ạ.em muốn dịch tiếng việt sang tiếng khác ạ.

    • Phan Tiến viết:

      Mình không hiểu ý em lắm? Có phải Em muốn làm ứng dụng đa ngôn ngữ như tiếng việt, tiếng anh …?

      • dangha viết:

        Em muốn tạo 1 từ điển tiếng việt – tiếng dân tộc thiểu số(1 loại ngôn ngữ ) ạ.có thể tra cứu 2 chiều.có cần phải thay đổi dòng code hay điều gì không ạ.
        Và nếu mình tạo trên laptop vậy có thể chuyển lên đt cá nhân để tiện sử dụng không ạ .em muốn học hỏi tý ạ

  8. dangha viết:

    Em muốn tạo 1 từ điển tiếng việt – tiếng dân tộc thiểu số(1 loại ngôn ngữ ) ạ.có thể tra cứu 2 chiều.có cần phải thay đổi dòng code hay điều gì không ạ.
    Và nếu mình tạo trên laptop vậy có thể chuyển lên đt cá nhân để tiện sử dụng không ạ .em muốn học hỏi tý ạ

    • timoday viết:

      Đây là chương trình hiện tại đang là 1 chiều, bạn muốn thiết kế 2 chiều thì đơn giản bạn sẽ tạo 2 bảng dữ liệu của từng ngôn ngữ. Khi kích vào ngôn ngữ nào là gốc thì chọn bảng dữ liệu tương ứng.
      Bạn muốn chạy trên thiết bị di động thì bạn cần phải học lập trình cho thiết bị di động, hoặc lập trình tạo một ứng dụng chạy trên web, rồi sẽ truy cập ứng dụng từ trình duyệt web

  9. Đỗ Việt Hải viết:

    Tớ đang làm theo những hướng dẫn này . Nhưng tớ không hiểu đọan này . Bạn gửi thêm ảnh để giải thích những gì bạn đã là ở đọan này cho tớ nhé .
    Mở thanh Toolbox ở bên trái của cửa sổ Visual Studio, kéo control ListBox tới form, thiết lập thuộc tính Name = lstTerms
    Kéo thả Textbox nằm phía trên của list box, thiết lập thuộc tính Name = txtSearch
    Rồi kéo và thả RichTextbox tới bên phải của list box, thiết lập thuộc tính:
    Name = rtbResult
    Forecolor = MenuHighlight
    ReadOnly = True ( không cho phép người dùng chỉnh sửa text trong RichTextbox)
    Để thêm được menu vào form, bạn cần kéo và thử MenuStrip từ Toolbox
    anh6

    Đánh &File vào chỗ ô Type Here và trong hộp tiếp theo trong ô Type Here là &Help
    Đánh &Close vào ô Type Here dưới menu File và đánh menu &About… trong ô Type Here dưới menu Help

Trả lời Phan Tiến Hủy

EnglishVietnamese