• 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

Tạo chương trình trắc nghiệm nâng cao

Các bài viết hướng dẫn về Visual Basic .NET và C#

Điều hành viên: QUANITGROBEST, tungcan5diop

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » CN 21/02/2010 6:53 pm

Tên bài viết: Tạo chương trình trắc nghiệm nâng cao
Tác giả: Võ Minh Đạt
Cấp độ bài viết: Trung bình
Tóm tắt: Sau khi đã nắm được một số điều căn bản khi tạo một chương trình trắc nghiệm đơn giản tại đây, mình sẽ hướng dẫn các bạn làm một bước tiến mới



Project mẫu:
Trac_Nghiem.rar
(4.08 MiB) Đã tải 5508 lần


I. TỔNG QUAN NHỮNG CHI TIẾT NÂNG CẤP


1. Các nâng cấp:

- Thiết kế câu hỏi nhiều nội dung phức tạp hơn:
  • Thay thế file text bằng file XML.
  • Thêm các chi tiết: câu hỏi nhiều lựa chọn, độ khó câu hỏi, ...
  • Các đáp án để chọn có thể được xáo trộn.
  • ...
- Thiết kế giao diện bắt mắt hơn, đặc biệt với bộ control DotNetBar và tạo màn hình Splash.
Portal.jpg
Portal.jpg (71.14 KiB) Đã xem 12567 lần

- Sử dụng List thay thế cho Array (mảng). Điều này giúp việc quản lí đơn giản hơn rất nhiều!

Thực ra, nhiều chức năng lẽ ra không có trong một phần mềm trắc nghiệm hoàn chỉnh, nhưng mình vẫn hướng dẫn các bạn vì bản chất bài này muốn các bạn biết cách dùng ngôn ngữ lập trình tốt hơn!

2. Tại sao có những nâng cấp này?

  • XML thay thế file text: Rõ ràng, khi độ phức tạp của câu hỏi tăng lên (nhiều chi tiết để lưu trữ hơn) thì việc lưu bằng file text không còn hiệu quả nữa. Hơn nữa, bạn cũng đừng lo lắng nếu không biết gì về XML, mà class XMLSerializer (nếu muốn, bạn có thể tham khảo thêm tại đây) sẽ giải quyết tất cả tương tự như class IO.File vậy!
  • Thiết kế giao diện mới: Đây là điều đương nhiên! Một phần mềm ứng dụng dành cho người dùng phổ thông không những phải hay mà phải có giao diện (GUI) đẹp. Ngoài ra, splash screen còn có tác dụng hiện các thông tin mà lập trình viên muốn khi chương trình đang nạp, thay vì để user chờ đợi, đặc biệt các chương trình làm bởi .NET load khá chậm chạp! Bên cạnh đó, DotNetBar là một công cụ rất hay để tạo giao diện đẹp, mình sẽ hướng dẫn bạn cách sử dụng!
  • Thay thế Array bằng List(Of T): Bạn có thế thấy, việc dùng mảng lưu trữ cũng không thành vấn đề nhưng việc thêm, xoá, ... rất khó khăn. List sẽ giải quyết nó dễ dàng!

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » CN 21/02/2010 7:32 pm

II. THIẾT KẾ GIAO DIỆN


1. Form giao diện Microsoft Office 2007:

Trong bộ DotNetBar (DNB) có 2 "style" form rất đẹp bắt chước Microsoft Office 2007 là form bình thường và form có ribbon. Ở đây ta chỉ mới dùng một form bình thường:

Trước tiên, hãy nhấn nút Show All File ở cửa sổ Solution Explorer (1), bạn sẽ thấy form hiện thêm dấu cộng bên trái, hãy bung ra, vào mục <Tên form>.Designer.vb (2)

Tại đây, bạn sẽ thấy trong những dòng đầu có sẵn dòng:

  1. Inherits System.Windows.Forms.Form


Hãy đổi lại thành (3):

  1. Inherits DevComponents.DotNetBar.Office2007Form


OfficeForm.jpg

(nhấn vào để phóng to ảnh)


Lưu ý: Trước đó bạn đã phải vẽ 1 control nào đó của DNB, hoặc là vào Project\Add Reference và Brown đến DLL của DNB

Làm như vậy cho các form bạn muốn có giao diện Office 2007!

2. Form chính frmMain (hoặc frmPortal):

Portal.jpg
Portal.jpg (71.14 KiB) Đã xem 12566 lần


Mình xin giới thiệu với các bạn control Reflection Image trong bộ DotNetBar. Đúng như tên gọi, nó giống như một control Image, nhưng sẽ có phần ảnh phản chiếu bên dưới, giúp giao diện trông "ấn tượng" hơn! Ngoài ra bạn cũng có thể dùng control Reflection Label, hay Image, Label bình thường cũng được!

Form Portal bạn có thể thiết kế tuỳ ý, nhưng chủ yếu có 3 button: butTracNghiem, butBienSoan, butTacGia. Ngoài ra, form này nên có một icon (biểu tượng - xuất hiện góc trên bên trái thanh tiêu đề). Bạn có thể thay đổi thuộc tính Icon của Form dẫn đến 1 file .ico. Đặc biệt nếu dùng form Office 2007 thì cần có một icon kích thước 16x16 đi kèm để hiển thị đầy đủ, bạn có thể dùng phần mềm chỉnh sửa icon nào để tạo thêm!

ProjectProperty.jpg

Cửa sổ Project Properties để thiết lập một số thông số


3. Cửa sổ Splash (frmSplash):

Màn hình Splash thì do tuỳ bạn thiết kế sao cũng được miễn là đẹp mắt. Ngoài ra mình khuyên bạn nên đặt độ trong suốt của form (thuộc tính Opacity) từ 50-75%, dù không đặt cũng không sao.

Để đặt frmSplash là Splash Screen, nghĩa là sẽ tự động mở ở đầu khi chương trình đang nạp, và đóng khi đã nạp xong, bạn vào Project\<Tên Project> Properties..., trong mục Splash Screen, chọn frmSplash (xem hình minh hoạ thiết lập icon).

Splash.jpg

Màn hình Splash


4. Cửa sổ Loading (frmLoading):

Là cửa sổ hiện lên khi chúng ta nạp dữ liệu, có thể trang trí tuỳ thích, nhưng PHẢI đặt TopMost là True và nên đặt độ trong suốt! Nên có câu cho người dùng biết ta đang nạp dữ liệu, hãy kiên nhẫn, nếu không người dùng tưởng phần mềm của chúng ta đã bị treo!

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » T.Hai 22/02/2010 6:25 pm

5. Form biên soạn câu hỏi (frmBienSoan):

frmBienSoan.JPG


Lần này mình đặc biệt giới thiệu các bạn cách dùng control Expandable Splitter (có cả trong bộ DNB và trong bộ control chuẩn). Bạn có thể tham khảo đoạn clip này để biết cách sử dụng (control Panel chuẩn vẫn có thể sử dụng thay vì dùng PanelEX trong DNB!)

Và đặc biệt, mình muốn bạn xử lí các control trong trường hợp kích thước form thay đổi bằng thuộc tính anchor của VB.NET. Anchor là thuộc tính rất hay, cho biết control sẽ xử lí vị trí và kích thước như thế nào nếu control chứa nó (có thể là form hay Panel, GroupBox, ...) thay đổi kích thước. Do bài viết có hạn mình không nói thêm nhiều về Anchor, bạn có thể tham khảo thêm bên ngoài và trong project mẫu!

Hãy tạo các control sau trong Panel1 (khung bên trái):
frmBienSoan_Panel1.jpg


và các control sau trong Panel2 (khung bên phải):
frmBienSoan_Panel2.jpg



Đặc biệt, để chọn độ khó, thay vì dùng NumericUpDown, ta có thể dùng control Rating Star trong bộ DNB. Vẽ một control Rating Star lên Panel2 và đặt tên rtsDoKho, Text là “Độ khó:”. Ngoài ra, bạn cần vẽ thêm 2 button là Cập nhật (butCapNhat) và Huỷ (butHuy).

Vậy là bạn đã thiết kế xong form Biên soạn!

6. Form Trắc nghiệm (frmTracNghiem):

Và đây là phần để người dùng trả lời các câu hỏi trắc nghiệm đã soạn. Bạn có thể trang trí form tuỳ ý, nhưng cần nhất là TextBox hiển thị câu hỏi (txtCauHoi) và 4 checkbox trả lời (chkAx). Trong hình là một gợi ý thiết kế form:

frmTracNghiem.JPG


Vậy là bạn đã làm xong giao diện cho chương trình. Bài viết tiếp theo, mình xin hướng dẫn các bạn làm phần nhân: code!

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » T.Ba 23/02/2010 6:40 pm

III. Code


1. Class câu hỏi (clsCauHoi):

Đây là class lưu các thông tin về một câu hỏi, bao gồm câu hỏi, các đáp án, câu trả lời đúng và độ khó, … của câu hỏi.

Trước tiên, ta khai báo các thuộc tính (Property) để lưu giữ thông tin và lưu vào mảng Variant!

  1.     Dim Variants(5) As Object
  2.  
  3.     Property CauHoi() As String
  4.         Get
  5.             Return Variants(0)
  6.         End Get
  7.         Set(ByVal value As String)
  8.             Variants(0) = value
  9.         End Set
  10.     End Property
  11.  
  12.     Property TraLoi() As String()
  13.         Get
  14.             Return Variants(1)
  15.         End Get
  16.         Set(ByVal value As String())
  17.             Variants(1) = value
  18.         End Set
  19.     End Property
  20.  
  21.     Property CoDinh() As Boolean()
  22.         Get
  23.             Return Variants(2)
  24.         End Get
  25.         Set(ByVal value As Boolean())
  26.             Variants(2) = value
  27.         End Set
  28.     End Property
  29.  
  30.     Property DapAn() As Boolean()
  31.         Get
  32.             Return Variants(3)
  33.         End Get
  34.         Set(ByVal value As Boolean())
  35.             Variants(3) = value
  36.         End Set
  37.     End Property
  38.  
  39.     Property DoKho() As Integer
  40.         Get
  41.             Return Variants(4)
  42.         End Get
  43.         Set(ByVal value As Integer)
  44.             Variants(4) = value
  45.         End Set
  46.     End Property
  47.  
  48.     Property SoCauTraLoi() As Boolean
  49.         Get
  50.             Return Variants(5)
  51.         End Get
  52.         Set(ByVal value As Boolean)
  53.             Variants(5) = value
  54.         End Set
  55.     End Property


Đặc biệt, chúng ta sẽ cần thủ tục New để cho biết các giá trị mặc định khi class được khởi tạo!

  1.     Sub New()
  2.         CauHoi = "Chưa có câu hỏi"
  3.         ReDim DapAn(SoDapAn - 1) : ReDim CoDinh(SoDapAn - 1) : ReDim TraLoi(SoDapAn - 1)
  4.         For i As Integer = 0 To SoDapAn - 1
  5.             TraLoi(i) = "Đáp án " & i + 1
  6.             DapAn(i) = False
  7.             CoDinh(i) = False
  8.         Next
  9.         DoKho = 1
  10.         SoCauTraLoi = False
  11.     End Sub


2. Module dùng đọc XML (mdlXMLSerialize):

Bạn có thể tham khảo bài viết về class XMLSerialize tại đây. Trong module này sẽ có 2 lệnh: ghi file XML (WriteXML) và đọc file XML (ReadXML).

  1. Imports System.Xml.Serialization
  2. Imports System.IO
  3.  
  4. Module mdlXMLSerialize
  5.  
  6.     Const DefaultData As String = "<?xml version=""1.0"" encoding=""utf-8""?><ArrayOfClsCauHoi xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xsi:nil=""true"" />"
  7.  
  8.     Dim XMLSer As New XmlSerializer(GetType(List(Of clsCauHoi)))
  9.  
  10.     Public Sub WriteXML(ByVal Data As List(Of clsCauHoi), ByVal Path As String)
  11.         Dim Writer As New StreamWriter(Path)
  12.         XMLSer.Serialize(Writer, Data)
  13.         'Nhớ phải thêm dòng này!
  14.         'Nếu không sẽ bị báo lỗi
  15.         'Tập tin đang bị sử dụng nếu thao tác sau này
  16.         Writer.Close()
  17.     End Sub
  18.  
  19.     Public Function ReadXML(ByVal Path As String) As List(Of clsCauHoi)
  20.         'Nếu tập tin Data chưa có
  21.         If Not File.Exists(Path) Then _
  22.             File.WriteAllText(Path, DefaultData)
  23.         Dim Reader As New StreamReader(Path)
  24.         'Không được dùng
  25.         'Return XMLSer.Deserialize(Reader)
  26.         'vì sẽ không thực hiện dòng cuối nữa
  27.         ReadXML = XMLSer.Deserialize(Reader)
  28.         'Nhớ phải thêm dòng này!
  29.         'Nếu không sẽ bị báo lỗi
  30.         'Tập tin đang bị sử dụng nếu thao tác sau này
  31.         Reader.Close()
  32.     End Function
  33.  
  34. End Module


3. Module dùng chung (mdlGeneral):

Đây là module chứa các biến toàn cục (AppPath) và một số hằng số để bạn thay đổi phù hợp với chương trình của mình (số câu hỏi, số đáp án, ...). Ngoài ra còn 2 thủ tục nạp câu hỏi (NapCauHoi) và ghi dữ liệu hiện tại ra file (GhiDuLieu) để tiện hơn!

  1. Module mdlGeneral
  2.  
  3.     '====Một số hằng số===='
  4.     'Bạn có thể điều chỉnh cho phù hợp
  5.     'với chương trình của mình
  6.  
  7.     'Số câu hỏi cho 1 lần trắc nghiệm
  8.     Public Const SoCauHoi As Integer = 10
  9.     'Số đáp án của 1 câu
  10.     'Khi sửa số này nhớ thêm các textbox
  11.     'và checkbox tương ứng trong 2 form
  12.     'biên soạn và trắc nghiệm
  13.     Public Const SoDapAn As Integer = 4
  14.     'Số kí tự đầu tiên của câu hỏi
  15.     'khi liệt kê ở form biên soạn
  16.     Public Const SKT = 50
  17.  
  18.     '======================='
  19.     Public Const Title As String = "Trắc nghiệm Câu lạc bộ VB"
  20.     Public AppPath As String = Application.StartupPath
  21.     Public DuLieu As List(Of clsCauHoi)
  22.  
  23.     Public Sub NapCauHoi()
  24.         DuLieu = ReadXML(AppPath & "\Data.xml")
  25.     End Sub
  26.  
  27.     Public Sub GhiDuLieu()
  28.         WriteXML(DuLieu, AppPath & "\Data.xml")
  29.     End Sub
  30.  
  31. End Module
  32.  


4. Form chính (frmMain):

Khi khởi động, nhớ nạp dữ liệu:

  1.     Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  2.         NapCauHoi()
  3.     End Sub



Trước tiên, ta sẽ làm code cho button Tác giả. Bài viết sử dụng câu lệnh gọi cửa sổ Y!M để chat với một nick của tác giả clarkkent:

  1.         Try
  2.             'Đây là code liên hệ nick Y!M vo_minhdat2007
  3.             Process.Start("ymsgr:sendIM?vo_minhdat2007")
  4.         Catch ex As Exception
  5.             'Nếu không liên lạc được Y!M thì sẽ hiện thông báo lỗi
  6.             MsgBox("Không thể liên lạc với Y!M, vui lòng liên hệ tác giả qua Y!M vo_minhdat2007" _
  7.                 , MsgBoxStyle.Critical, "Trắc nghiệm nâng cao")
  8.         End Try


Button biên soạn không có gì đặt biệt, chỉ việc show form Biên soạn, nhưng nhớ ShowDialog!

  1.     Private Sub butBienSoan_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butBienSoan.Click
  2.         frmEdit.ShowDialog()
  3.     End Sub


Riêng lần này với button Trắc nghiệm, ta sẽ kiểm tra xem có đủ số câu hỏi hay chưa, nếu chưa thì sẽ yêu cầu người dùng thêm câu hỏi cho đủ!

  1.     Private Sub butTracNghiem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butTracNghiem.Click
  2.         'Kiểm tra có đủ câu hỏi hay không
  3.         If DuLieu Is Nothing OrElse DuLieu.Count < SoCauHoi Then
  4.             MsgBox("Không đủ câu hỏi để thực hiện, vui lòng thêm câu hỏi!", MsgBoxStyle.Critical, Title)
  5.             Exit Sub
  6.         End If
  7.         Me.Hide()
  8.         frmTracNghiem.Show()
  9.     End Sub

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » T.Tư 24/02/2010 6:59 pm

5. Form biên soạn (frmBienSoan):

Đây là form chứa những đoạn code “phức tạp” nhất chương trình, nhưng cũng có nhiều thủ thuật hay mà mình muốn giới thiệu đến các bạn!

a. Kiến thức:

Trong phần tiếp theo, trong cấu trúc If có 2 điều kiện trở lên, mình dùng OrElse (và AndAlso) thay vì Or (và And). Ý nghĩa của OrElse và AndAlso là nếu có 2 điều kiện trở lên (ở đây giả sử có 2 điều kiện) thì khi xét điều kiện 1 xong, nếu là True thì OrElse không xét điều kiện 2 nữa (vì chắc chắn dù điều kiện 2 False thì kết quả vẫn là True). Tương tự AndAlso nếu điều kiện 1 là False thì sẽ không xét điều kiện 2 nữa! AndAlso và OrElse mang đến 2 lợi ích:
  • Tăng tốc độ tính toán, đặc biệt nếu điều kiện 2 là một hàm cần nhiều thời gian thực hiện.
  • Đôi khi, ta cần có điều kiện 1 để điều kiện 2 không bị lỗi. Ở VB.NET thì phép chia cho 0 vẫn thực hiện được nên mình không lấy ví dụ dễ hiểu này được. Một việc thường dùng đến AndAlso chính là kiểm tra mảng (List) đã có phần tử chưa. Nếu không dùng AndAlso với điều kiện 1 là Not Arr Is Nothing thì hậu quả là khi kiểm tra điều kiện 2, VB.NET sẽ báo lỗi Object not reference…

Thứ hai là việc quản lí control trong VB.NET rất hay! Nếu như bạn có 10 điều khiển trong form đặt tên liên tiếp (chk1, chk2, chk3, …) thì có thể dùng vòng lặp duyệt qua bằng thuộc tính Controls. Ví dụ:

Me.Controls(“txt” & i).Text = “Đây là Textbox số ” & i

Lưu ý là không phải lúc nào cũng là Me.Controls mà là “khung chứa” điều khiển đó (cụ thể trong chương trình của chúng ta là Panel2).

Hi vọng 2 kiến thức trên sẽ giúp bạn nhiều trong việc làm các chương trình sau này!

b. Áp dụng vào form biên soạn:

Trước tiên, khi nạp form chúng ta cần phải liệt kê các câu hỏi vào ListView. Đặc biệt, chúng ta sẽ phân loại thành nhóm (group) theo độ khó của câu hỏi!

  1.     Private Sub frmEdit_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  2.         NapCauHoi()
  3.         lstCauHoi.Items.Clear()
  4.         lstCauHoi.Groups.Clear()
  5.         'Chia nhóm theo độ khó
  6.         For i As Integer = 1 To 5
  7.             Dim grp As New ListViewGroup
  8.             grp.Header = "Độ khó: " & i
  9.             grp.Name = "grp" & i
  10.             lstCauHoi.Groups.Add(grp)
  11.         Next
  12.         'Liệt kê các câu hỏi
  13.         If DuLieu Is Nothing OrElse DuLieu.Count = 0 Then
  14.             Panel2.Enabled = False
  15.         Else
  16.             For i As Integer = 0 To DuLieu.Count - 1
  17.                 Dim item As New ListViewItem
  18.                 item.Name = "lst" & i
  19.                 'Chỉ liệt kê SKT kí tự đầu tiên của câu hỏi
  20.                 'Nếu số kí tự của câu hỏi ít hơn thì liệt kê hết
  21.                 If DuLieu(i).CauHoi.Length < SKT Then
  22.                     item.Text = DuLieu(i).CauHoi
  23.                 Else
  24.                     item.Text = DuLieu(i).CauHoi.Substring(0, SKT) & "..."
  25.                 End If
  26.                 'Đưa vào nhóm độ khó tương ứng
  27.                 item.Group = lstCauHoi.Groups(DuLieu(i).DoKho - 1)
  28.                 lstCauHoi.Items.Add(item)
  29.             Next
  30.         End If
  31.  
  32.     End Sub


Ngoài ra, trong quá trình xử lí, chúng ta chỉ thực hiện trên bộ nhớ, và khi đóng form, chúng ta phải ghi ra file để lần mở sau vẫn còn tác dụng! Phương thức Me.Dispose giúp xoá những thông tin hiện tại của form, lần sau mở lên form sẽ “mới” hoàn toàn!

  1.     Private Sub frmEdit_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
  2.         'Ghi ra file những thay đổi
  3.         GhiDuLieu()
  4.         Me.Dispose()
  5.     End Sub


Một sự kiện vô cùng quan trọng của form Biên soạn chính là khi chọn một mục trong ListView:
  1.         'Nếu không chọn câu nào (có thể do dữ liệu rỗng)
  2.         If lstCauHoi.SelectedItems.Count = 0 Then
  3.             CurrentIndex = -1
  4.             butXoa.Enabled = False
  5.             Panel2.Enabled = False
  6.             Exit Sub
  7.         End If
  8.         'Nếu đang chọn dữ liệu
  9.         'Vì chỉ cho phép chọn 1 dòng dữ liệu
  10.         'nên cứ lấy phần tử 0
  11.         CurrentIndex = lstCauHoi.SelectedItems(0).Index
  12.         Panel2.Enabled = True
  13.         butXoa.Enabled = True
  14.         '======Hiện các dữ liệu======'
  15.         'Cấu trúc With vui lòng
  16.         'tham khảo phần Trắc nghiệm đơn giản
  17.         With DuLieu(CurrentIndex)
  18.             txtQ.Text = .CauHoi
  19.             For i As Integer = 0 To SoDapAn - 1
  20.                 Panel2.Controls("txtA" & i).Text = .TraLoi(i)
  21.                 'Do mình dùng control CheckBox trong bộ DotNetBar
  22.                 'Nếu bạn dùng checkbox chuẩn, chỉ cần khai báo
  23.                 'Dim chk As CheckBox
  24.                 Dim chk As DevComponents.DotNetBar.Controls.CheckBoxX
  25.                 'CheckBox đáp án thứ i
  26.                 chk = Panel2.Controls("chkA" & i)
  27.                 chk.Checked = .DapAn(i)
  28.                 'CheckBox Stick thứ i
  29.                 chk = Panel2.Controls("chkS" & i)
  30.                 chk.Checked = .CoDinh(i)
  31.             Next
  32.             'Có thể thay control này bằng NumericUpDown control
  33.             rtsDoKho.Rating = .DoKho
  34.             chkHienTraLoi.Checked = .SoCauTraLoi
  35.         End With


Các sự kiện khác, mình đã ghi chú khá kĩ trong code, bạn có thể tham khảo dễ dàng!

  1.     Private Sub butThem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butThem.Click
  2.         'Thêm vào dữ liệu
  3.         DuLieu.Add(New clsCauHoi)
  4.         'Thêm 1 item vào ListView
  5.         Dim item As New ListViewItem
  6.         item.Name = "lst" & DuLieu.Count - 1
  7.         item.Text = DuLieu(DuLieu.Count - 1).CauHoi
  8.         item.Group = lstCauHoi.Groups(0)
  9.         lstCauHoi.Items.Add(item)
  10.         lstCauHoi.SelectedItems.Clear()
  11.         item.Selected = True
  12.     End Sub
  13.  
  14.     Private Sub lstCauHoi_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles lstCauHoi.Resize
  15.         lstCauHoi.Columns(0).Width = lstCauHoi.Width
  16.     End Sub
  17.  
  18.     Private Sub butCapNhat_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butCapNhat.Click
  19.         With DuLieu(CurrentIndex)
  20.             'Cập nhật dữ liệu
  21.             .CauHoi = txtQ.Text
  22.             For i As Integer = 0 To SoDapAn - 1
  23.                 .TraLoi(i) = Panel2.Controls("txtA" & i).Text
  24.                 Dim chk As DevComponents.DotNetBar.Controls.CheckBoxX
  25.                 chk = Panel2.Controls("chkA" & i)
  26.                 .DapAn(i) = chk.Checked
  27.                 chk = Panel2.Controls("chkS" & i)
  28.                 .CoDinh(i) = chk.Checked
  29.             Next
  30.             .DoKho = rtsDoKho.Rating
  31.             .SoCauTraLoi = chkHienTraLoi.Checked
  32.             'Hiện lại phần text bên ListView
  33.             If DuLieu(CurrentIndex).CauHoi.Length < SKT Then
  34.                 lstCauHoi.Items(CurrentIndex).Text = DuLieu(CurrentIndex).CauHoi
  35.             Else
  36.                 lstCauHoi.Items(CurrentIndex).Text = DuLieu(CurrentIndex).CauHoi.Substring(0, SKT) & "..."
  37.             End If
  38.             lstCauHoi.Items(CurrentIndex).Group = lstCauHoi.Groups(DuLieu(CurrentIndex).DoKho - 1)
  39.         End With
  40.     End Sub
  41.  
  42.     Private Sub butHuy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butHuy.Click
  43.         'Thực chất giống như chọn lại ListView 1 lần nữa
  44.         lstCauHoi_SelectedIndexChanged(Nothing, Nothing)
  45.     End Sub
  46.  
  47.     Private Sub butXoa_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butXoa.Click
  48.         'Xác nhận trước khi xoá
  49.         If MsgBox("Bạn có chắc muốn xoá mục này?", _
  50.             MsgBoxStyle.Exclamation + MsgBoxStyle.YesNo, Title) _
  51.             = MsgBoxResult.No Then Exit Sub
  52.         'Tuyệt đối không đảo 2 hàng này
  53.         'Vì xoá ListBox trước sẽ ảnh hưởng
  54.         'biến CurrentIndex
  55.         DuLieu.RemoveAt(CurrentIndex)
  56.         lstCauHoi.Items.RemoveAt(CurrentIndex)
  57.     End Sub


Phần cuối cùng của bài viết này, mình sẽ hướng dẫn bạn lập trình cho form Trắc nghiệm. Nhưng sao bạn không thử tự mình làm để thử khả năng?

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » CN 28/02/2010 8:16 am

Xin lỗi, do mình có việc riêng nên không có hướng dẫn chi tiết, nhưng trước đó khi code mình chú thích khá kĩ rồi, các bạn chịu khó vậy nhé, khi nào có dịp (nhưng có lẽ là không...) mình sẽ sửa lại.

6. Form Trắc nghiệm:

  1. Public Class frmTracNghiem
  2.  
  3.     Const HuongDanMacDinh As String = "Chọn (các) đáp án đúng và nhấn Trả lời..."
  4.     Const KhongHien As String = "Câu này không cho phép hiện số đáp án đúng!"
  5.     Const Dung As String = "Xin chúc mừng, bạn đã trả lời đúng!"
  6.     Const Sai As String = "Rất tiếc! Bạn đã trả lời sai!"
  7.  
  8.     Dim DuLieuTN As New List(Of clsCauHoi)
  9.     Dim Diem As Integer = 0, CauHienTai As Integer = 0
  10.     Dim SoCauDung As Integer
  11.  
  12.     Dim DangTraLoi As Boolean
  13.  
  14.     Private Sub frmTracNghiem_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
  15.         frmMain.Show()
  16.     End Sub
  17.  
  18.     Private Sub Nap()
  19.         'Hiện màn hình chờ
  20.         'Tuyệt đối không dùng ShowDialog
  21.         'vì sẽ làm ngưng hoạt động form hiện tại
  22.         'và không load được nũa
  23.         frmLoading.Show()
  24.         Threading.Thread.Sleep(2000)
  25.         'Xoá dữ liệu cũ
  26.         DuLieuTN = New List(Of clsCauHoi)
  27.         Diem = 0 : CauHienTai = -1
  28.         '=====Nạp các câu hỏi sẽ dùng====='
  29.         'Khai báo biến để tạo số random
  30.         Dim Rnd As New Random
  31.         'Mảng Used để kiểm tra có random vào số đã có?
  32.         Dim Used As New List(Of Integer)
  33.         For i As Integer = 0 To SoCauHoi - 1
  34.             '====Chọn ra câu hỏi===='
  35.             Dim Temp As Integer
  36.             Do
  37.                 'Temp ngẫu nhiên từ 0 đến DuLieu.Count - 1
  38.                 'do vậy, phải dùng Rnd như dưới đây (không có -1)
  39.                 Temp = Rnd.Next(0, DuLieu.Count)
  40.             Loop While Used.IndexOf(Temp) > -1
  41.             'Thêm Temp vào phần đã sử dụng
  42.             Used.Add(Temp)
  43.             'Thêm câu hỏi thứ Temp vào CSDL sẽ dùng
  44.             DuLieuTN.Add(DuLieu(Temp))
  45.             '====Xáo trộn các câu trả lời===='
  46.             With DuLieuTN(i)
  47.                 'Tạo mảng tạm lưu các câu trả lời
  48.                 Dim sTemp(SoDapAn - 1) As String, bTemp(SoDapAn - 1) As Boolean
  49.                 Dim DAUsed(3) As Boolean
  50.                 'Kiểm tra các Stick trước
  51.                 Dim Sticky As Integer = 0
  52.                 For j As Integer = 0 To SoDapAn - 1
  53.                     If .CoDinh(j) Then
  54.                         sTemp(j) = .TraLoi(j)
  55.                         bTemp(j) = .DapAn(j)
  56.                         DAUsed(j) = True
  57.                         Sticky += 1
  58.                     End If
  59.                 Next
  60.                 'Đảo các đáp án sau
  61.                 For j As Integer = 0 To SoDapAn - 1 - Sticky
  62.                     Do
  63.                         Temp = Rnd.Next(0, SoDapAn)
  64.                     Loop While DAUsed(Temp)
  65.                     DAUsed(Temp) = True
  66.                     sTemp(j) = .TraLoi(Temp)
  67.                     bTemp(j) = .DapAn(Temp)
  68.                 Next
  69.                 'Lưu các đáp án đã xáo trộn và mảng thật
  70.                 For j As Integer = 0 To SoDapAn - 1
  71.                     .DapAn = bTemp
  72.                     .TraLoi = sTemp
  73.                 Next
  74.             End With
  75.         Next
  76.         'Thoát form chờ
  77.         frmLoading.Close()
  78.     End Sub
  79.  
  80.     Private Sub TiepTheo()
  81.         CauHienTai += 1
  82.         'Nếu đã hết câu hỏi
  83.         If CauHienTai = SoCauHoi Then
  84.             MsgBox("Bạn đã hoàn thành phần trắc nghiệm! Bạn ghi được " _
  85.                 & Diem & " điểm!", MsgBoxStyle.Information, Title)
  86.             Nap()
  87.         End If
  88.         'LabelX trong bộ DotNetBar có thể dùng
  89.         'code tương tự HTML. Nếu dùng Label thường
  90.         'chỉ đơn giản hiển thị thứ bạn muốn!
  91.         lblSoCau.Text = "<div align=""center"">Số câu: " & _
  92.             "<font color=""red""><b>" & CauHienTai & "</b></font>/" & SoCauHoi & "</div>"
  93.         With DuLieuTN(CauHienTai)
  94.             'Đếm số câu đúng
  95.             SoCauDung = 0
  96.             For i As Integer = 0 To SoDapAn - 1
  97.                 If .DapAn(i) Then SoCauDung += 1
  98.             Next
  99.             'Hiển thị
  100.             txtCauHoi.Text = .CauHoi
  101.             rtsDoKho.Rating = .DoKho
  102.             For i As Integer = 0 To SoDapAn - 1
  103.                 Dim chk As DevComponents.DotNetBar.Controls.CheckBoxX
  104.                 chk = Me.Controls("chkA" & i)
  105.                 chk.Text = .TraLoi(i)
  106.                 'Bỏ chọn checkbox
  107.                 chk.Checked = False
  108.             Next
  109.             lblHuongDan.Text = HuongDanMacDinh & vbNewLine
  110.             If .SoCauTraLoi Then
  111.                 lblHuongDan.Text += "Số câu trả lời đúng: " & SoCauDung & "/" & SoDapAn
  112.             Else
  113.                 lblHuongDan.Text += KhongHien
  114.             End If
  115.             butTraLoi.Text = "Trả lời"
  116.             DangTraLoi = True
  117.         End With
  118.     End Sub
  119.  
  120.     Private Sub TraLoi()
  121.         'Biến DA lưu những đáp án đúng
  122.         'Biến Ch lưu những đáp án người chơi chọn
  123.         Dim DA As String = "", Ch As String = ""
  124.         For i As Integer = 0 To SoDapAn - 1
  125.             'Lưu ý đối với chuỗi nên dùng &=, không dùng +=
  126.             Dim chk As DevComponents.DotNetBar.Controls.CheckBoxX
  127.             chk = Me.Controls("chkA" & i)
  128.             If DuLieuTN(CauHienTai).DapAn(i) Then
  129.                 DA &= i
  130.                 'Tô màu đáp án đúng
  131.                 chk.Text = "<font color=""green"">" & chk.Text & "</font>"
  132.             Else
  133.                 'Tô màu đáp án sai
  134.                 chk.Text = "<font color=""red"">" & chk.Text & "</font>"
  135.             End If
  136.             If chk.Checked Then Ch &= i
  137.         Next
  138.         'Hiện đúng/sai
  139.         If DA = Ch Then
  140.             lblHuongDan.Text = "<div align=""center""><font " & _
  141.                 "color=""green"" size=""14"">" & Dung & "</font></div>"
  142.             Diem += 1
  143.             lblDiem.Text = "<div align=""center"">Điểm: <font color=""red""><b>" _
  144.                 & Diem & "</b></font></div>"
  145.         Else
  146.             lblHuongDan.Text = "<div align=""center""><font " & _
  147.                 "color=""red"" size=""14"">" & Sai & "</font></div>"
  148.         End If
  149.         butTraLoi.Text = "Tiếp >"
  150.         DangTraLoi = False
  151.     End Sub
  152.  
  153.     Private Sub butTraLoi_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butTraLoi.Click
  154.         If DangTraLoi Then TraLoi() Else TiepTheo()
  155.     End Sub
  156.  
  157.     Private Sub frmTracNghiem_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
  158.         Nap()
  159.         TiepTheo()
  160.     End Sub
  161.  
  162. End Class


Bạn có thể download Project mẫu ở bài viết đầu tiên! Chúc các bạn thành công!

hoangnamfc
Bài viết: 5
Ngày tham gia: CN 27/06/2010 6:47 pm

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi hoangnamfc » T.Hai 28/06/2010 2:00 pm

Anh ơi giờ em muốn tạo 1 cái là sau khi làm bài xong nó hỏi là "Bạn muốn làm tiếp hay không?" và người sử dụng chọn có hoặc không nếu là có thì làm tiếp về lại câu 1 mà không thì thoát ra ct chính. Mong các anh giúp đỡ

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » T.Hai 28/06/2010 3:56 pm

Bạn xử lí trong phần điều kiện hết câu hỏi trong sub TiepTheo.

hoangnamfc
Bài viết: 5
Ngày tham gia: CN 27/06/2010 6:47 pm

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi hoangnamfc » T.Hai 28/06/2010 6:50 pm

vo_minhdat2007 đã viết:Bạn xử lí trong phần điều kiện hết câu hỏi trong sub TiepTheo.

Bạn có thể cho mình code không?

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » T.Hai 28/06/2010 8:24 pm

Không.

ncandy
Bài viết: 4
Ngày tham gia: T.Hai 30/08/2010 3:48 pm

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi ncandy » T.Hai 30/08/2010 4:41 pm

anh ơi, em có điều muốn hỏi thế này, phần rating star mình thay bằng numericupdown thì thay thế nào? với lại em cũng muốn thử thay phần hiển thị câu hỏi theo rating star bằng hiển thị theo các mục mình tự tạo. như vậy có được ko ạh

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » T.Hai 30/08/2010 5:34 pm

Uh, bình thường thôi mà, bản chất cái Rating Star cũng chỉ là lưu trữ số, từ con số hiển thị giao diện thôi. Bạn dùng NumericUpDown bình thường cũng được.

ncandy
Bài viết: 4
Ngày tham gia: T.Hai 30/08/2010 3:48 pm

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi ncandy » T.Hai 30/08/2010 6:46 pm

anh có thể hướng sẫn sơ sơ cách dùng numericupdown đc ko ạh.

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » T.Hai 30/08/2010 6:56 pm

NUD thì có nhiêu đó thôi, hướng dẫn gì giờ?

ncandy
Bài viết: 4
Ngày tham gia: T.Hai 30/08/2010 3:48 pm

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi ncandy » T.Hai 30/08/2010 7:07 pm

hì, code được không anh. em có thử làm theo cái code của anh (là thế này)


nhưng sao nó hiện lỗi "Value of type 'Integer' cannot be converted to 'System.Windows.Forms.NumericUpDown'"

hic (:|

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » T.Hai 30/08/2010 7:42 pm

  1. NumericUpDown1.Value = .PhanLoai

ncandy
Bài viết: 4
Ngày tham gia: T.Hai 30/08/2010 3:48 pm

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi ncandy » T.Hai 30/08/2010 7:57 pm

hì, gà con tập code phiền anh thêm cái nữa đó là em muốn tự tạo các mục phân loại như thế này

Hình ảnh

nhưng vấn đề là không biết làm sao thêm các mục phân loại mới trong combo box và cả trong file xml, vấn đề nữa là sắp xếp trong list hiển thị. anh có thể hướng dẫn cho em đươc không ạ. có code càng tốt :D

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » T.Hai 30/08/2010 8:32 pm

Trong class, tạo thêm 1 Property nữa tên là Loai chẳng hạn, rồi dựa vào đó phân loại.

nhut2
Thành viên chính thức
Thành viên chính thức
Bài viết: 25
Ngày tham gia: T.Năm 21/01/2010 3:00 pm
Has thanked: 2 time

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi nhut2 » T.Hai 03/01/2011 7:46 pm

còn một lỗi nữa đó. Khi đã hết câu hỏi mà nhấn nút tiếp theo thì sẽ bị lỗi. Nên thêm một biến đếm. Nếu biến đếm = số câu hỏi thì hiện thông báo hay quay về form chính gì đó. Nếu không thì cho nút tiếp theo chuyển thành nút trở lại giao diện chính.

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 85 time
Liên hệ:

Re: Tạo chương trình trắc nghiệm nâng cao

Gửi bàigửi bởi vo_minhdat2007 » T.Hai 03/01/2011 7:56 pm

Mình có tạo biến đếm rồi, nhưng khi kiểm tra thì quên -1 và Exit Sub. Bạn thêm -1 ở điều kiện và Exit Sub (hoặc Close form, ...) vào chỗ kiểm tra hết câu hỏi.


Quay về “[.NET] Bài viết hướng dẫn”

Đang trực tuyến

Đang xem chuyên mục này: Không có thành viên nào trực tuyến.0 khách