[VB.NET] โค้ดประยุกต์ใช้งาน CheckedListBox Control กับข้อมูลเท็กซ์ไฟล์แบบ INI (Initialize File)
http://www.g2gnet.com/webboard/images/VBNet/CheckedListBoxINI.pngสำหรับบทความนี้แอดมินจะแสดงให้เห็นถึงการนำเอา CheckedListBox Control มาประยุกต์ใช้งานกับข้อมูล Initailize File หรือ INI สาระสำคัญคือ การแยก (Parser) ข้อมูลในตัว INI ซึ่งจะประกอบไปด้วย Section ตามด้วย Key และ Value เช่น
Item 1 = True
Item 2 = False
Item 3 = True
default=thai
เมื่อข้อมูลที่อยู่ในเครื่องหมาย Bracket [] คือ Section ส่วน Item 1 คือ Key และ True คือ Value ... โดยทั่วๆไปก็ไม่ค่อยมีปัญหามากมายนักกับการอ่านข้อมูลในแต่ละ Section ที่มีรูปแบบตายตัวเหมือนตัวอย่างด้านบน แต่บางครั้งปัญหาจะเกิดในลักษณะของการจัดเก็บข้อมูลในแบบ Dynamic ที่ทำให้เกิดความยืดหยุ่นของงานโปรแกรมมากกว่าแบบ Static ดังนั้นปัญหาของ INI Parser ก็คือในกรณีเราไม่รู้จุดสิ้นสุดของข้อมูลในแต่ละชุด ...
แอดมินก็พึ่งหัดใช้ CheckedListBox เป็นครั้งแรก ซึ่งการเริ่มต้นฝึกฝนของแอดมิน ก็จะก้าวข้ามส่วนของการ Design Time ไป แล้วมักจะใช้วิธีการเขียนโค้ดแบบ Run Time แทน เช่น โค้ดตัวอย่างนี้เป็นการสร้าง Item ขึ้นมาด้วยโค้ด และสุ่มค่าเลขคู่/คี่เพื่อกำหนด Checked/Unchecked ในแต่ละ Item
' / --------------------------------------------------------------------
' / สร้าง CheckedListBox และสุ่มค่า Check/Uncheck ทำการทดสอบ
Private Sub CreateSample()
Me.CheckedListBox1.Items.Clear()
Dim RndClass As New Random
For i As Integer = 0 To 14
With Me.CheckedListBox1
.Items.Add("Item " & i + 1)
If RndClass.Next(0, 99) Mod 2 = 0 Then
CheckedListBox1.SetItemChecked(i, CheckState.Checked)
End If
End With
Next
End Sub
โค้ดในส่วนของการแยกแยะ Key กับ Value ออกจากกัน
' / --------------------------------------------------------------------
' / แยก Key และ Value เพื่อแสดงผลใน CheckedListBox
Private Sub ParserCheckedListBox(ByVal iniFile As String, ByVal Section As String)
Dim blnMatch As Boolean = False
Dim iRow As Integer = 0
'/ Reads each line from the text file one at a time.
For Each line As String In IO.File.ReadLines(iniFile)
'/ ต้องเช็คก่อนว่าเป็น Section ที่ต้องการหรือไม่? (ใส่ Lower Case หรือให้เป็นอักษรตัวเล็กทั้งหมด)
If LCase(line) = "[" & LCase(Section) & "]" Then
blnMatch = True
'/ เมื่อได้ Section ตามที่ต้องการ (blnMatch = True)
ElseIf blnMatch Then
'/ แยก (Split) Key กับ Value ออกจากกันด้วยเครื่องหมาย =
Dim sArr As String() = line.Split("="c)
'/ เพิ่มไอเทมด้วย sArr(0)
CheckedListBox1.Items.Add(sArr(0))
'/ หากค่าใน sArr(1) มีค่าเป็นจริง (CBool = Convert To Boolean)
If CBool(sArr(1)) Then CheckedListBox1.SetItemChecked(iRow, CheckState.Checked)
'/ เลื่อน Key ไอเทม
iRow += 1
End If
Next
End Subแอดมินเขียนเป็นโปรแกรมย่อย (Sub Program) เอาไว้ให้เพียงเท่านี้ เพราะง่ายต่อการศึกษาโค้ดก่อน แต่ฝากคำถามให้ไปคิดกันต่อในเรื่องของการแยกข้อมูลออกจากกันของ INI ซึ่งมันเป็นงานเหมือนเดิมที่ซ้ำๆกันตลอด แต่ให้สังเกตว่าการนำ Key และ Value ไปใช้ใน Control แต่ละตัวมันจะมี Method ที่ไม่เหมือนกัน ตรงนี้แหละที่เราจะลดรูปคำสั่งลงด้วยวิธีการอย่างไร???
ตัวอย่างของการบันทึกไฟล์ INI ซึ่งในลักษณะไดนามิคแบบนี้ จะทำให้เราลดชุดคำสั่งลงไปในกรณีที่มีไอเทมเป็นจำนวนมากๆได้ Private Sub btnSave_Click(sender As System.Object, e As System.EventArgs) Handles btnSave.Click
For i As Integer = 0 To Me.CheckedListBox1.Items.Count - 1
WriteIni(strFileINI, "test", CheckedListBox1.Items(i), CheckedListBox1.GetItemChecked(i))
Next
MsgBox("Save data initialize complete.")
Me.Close()
End Sub
โค้ดแบบเต็มทั้งหมด
Public Class frmCheckedListBox
Dim strFileINI As String = MyPath(Application.StartupPath) & "config.ini"
Private Sub frmCheckedListBox_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
'// เช็คว่ามีไฟล์ Config.ini อยู่หรือไม่???
If My.Computer.FileSystem.FileExists(strFileINI) Then
Call ParserCheckedListBox(strFileINI, "test")
Else
'/ การสร้างไอเทมและค่าแบบสุ่ม
Call CreateSample()
End If
End Sub
' / --------------------------------------------------------------------
' / แยก Key และ Value เพื่อแสดงผลใน CheckedListBox
Private Sub ParserCheckedListBox(ByVal iniFile As String, ByVal Section As String)
Dim blnMatch As Boolean = False
Dim iRow As Integer = 0
'/ Reads each line from the text file one at a time.
For Each line As String In IO.File.ReadLines(iniFile)
'/ ต้องเช็คก่อนว่าเป็น Section ที่ต้องการหรือไม่? (ใส่ Lower Case หรือให้เป็นอักษรตัวเล็กทั้งหมด)
If LCase(line) = "[" & LCase(Section) & "]" Then
blnMatch = True
'/ เมื่อได้ Section ตามที่ต้องการ (blnMatch = True)
ElseIf blnMatch Then
'/ แยก (Split) Key กับ Value ออกจากกันด้วยเครื่องหมาย =
Dim sArr As String() = line.Split("="c)
'/ เพิ่มไอเทมด้วย sArr(0)
CheckedListBox1.Items.Add(sArr(0))
'/ หากค่าใน sArr(1) มีค่าเป็นจริง (CBool = Convert To Boolean)
If CBool(sArr(1)) Then CheckedListBox1.SetItemChecked(iRow, CheckState.Checked)
'/ เลื่อน Key ไอเทม
iRow += 1
End If
Next
End Sub
' / --------------------------------------------------------------------
Private Sub btnSave_Click(sender As System.Object, e As System.EventArgs) Handles btnSave.Click
For i As Integer = 0 To Me.CheckedListBox1.Items.Count - 1
WriteIni(strFileINI, "test", CheckedListBox1.Items(i), CheckedListBox1.GetItemChecked(i))
Next
MsgBox("Save data initialize complete.")
Me.Close()
End Sub
' / --------------------------------------------------------------------
' / สร้าง CheckedListBox และสุ่มค่า Check/Uncheck ทำการทดสอบ
Private Sub CreateSample()
Me.CheckedListBox1.Items.Clear()
Dim RndClass As New Random
For i As Integer = 0 To 14
With Me.CheckedListBox1
.Items.Add("Item " & i + 1)
If RndClass.Next(0, 99) Mod 2 = 0 Then
CheckedListBox1.SetItemChecked(i, CheckState.Checked)
End If
End With
Next
End Sub
Private Sub frmCheckedListBox_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
Me.Dispose()
Application.Exit()
End Sub
Private Sub btnExit_Click(sender As System.Object, e As System.EventArgs) Handles btnExit.Click
Me.Close()
End Sub
End Class
โค้ดในส่วนของ GetPrivateProfileString/WritePrivateProfileString หรือ Windows API ที่เรานำมาใช้กับ INI File
Module modFunction
' / --------------------------------------------------------------------
' / Initialized Management
Private Declare Unicode Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringW" ( _
ByVal lpApplicationName As String, _
ByVal lpKeyName As String, _
ByVal lpString As String, _
ByVal lpFileName As String _
) As Int32
Private Declare Unicode Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringW" ( _
ByVal lpApplicationName As String, _
ByVal lpKeyName As String, _
ByVal lpDefault As String, _
ByVal lpReturnedString As String, _
ByVal nSize As Int32, _
ByVal lpFileName As String _
) As Int32
' / --------------------------------------------------------------------
' / --------------------------------------------------------------------
Public Function WriteIni(ByVal iniFileName As String, ByVal Section As String, ByVal ParamName As String, ByVal ParamVal As String) As Integer
WriteIni = WritePrivateProfileString(Section, ParamName, ParamVal, iniFileName)
End Function
' / --------------------------------------------------------------------
Public Function ReadIni(ByVal IniFileName As String, ByVal Section As String, ByVal ParamName As String, ByVal ParamDefault As String) As String
Dim ParamVal As String = Space$(1024)
Dim LenParamVal As Long = GetPrivateProfileString(Section, ParamName, ParamDefault, ParamVal, Len(ParamVal), IniFileName)
ReadIni = Left$(ParamVal, LenParamVal)
End Function
' / --------------------------------------------------------------------
' / Get my project path
' / AppPath = C:\My Project\bin\debug
' / Replace "\bin\debug" with "\"
' / Return : C:\My Project\
Function MyPath(ByVal AppPath As String) As String
'/ MessageBox.Show(AppPath);
AppPath = AppPath.ToLower()
'/ Return Value
MyPath = AppPath.Replace("\bin\debug", "\").Replace("\bin\release", "\").Replace("\bin\x86\debug", "\")
'// If not found folder then put the \ (BackSlash) at the end.
If Microsoft.VisualBasic.Right(MyPath, 1) <> "\" Then MyPath = MyPath & "\"
End Function
End Module
ดาวน์โหลดโค้ดฉบับเต็ม VB.NET (2010) ได้ที่นี่
ขอบพระคุณอย่างสูงครับ{:3_41:} ขอบคุณครับ
หน้า:
[1]