|
SharpGrid ActiveX Grid Control จัดเป็น Data Grid ที่ทรงประสิทธิภาพมาก สำหรับเหล่าบรรดา Developer ในกลุ่มของ Visual Studio 98 ทั้งนี้เราต้องใช้ทั้ง Design Time และการลงโค้ดตอน Run Time ผสมผสานกัน ถึงจะดึงขีดความสามารถของ ActiveX ตัวนี้ออกมาใช้งานได้อย่างเต็มที่ ...
ฟรีโค้ดของจริงนี้จะเป็นการนำเสนอ การใช้งาน SharpGrid ในลักษณะของ Bound Data Control หรือการผูกแหล่งข้อมูลเข้ากับตัวตารางกริด โดยการทำ Query เพื่อสร้าง DataSource ให้กับ SharpGrid แต่เป็นลักษณะของการเขียนโค้ดในแบบ Run-Time (สั่งรันจึงจะเห็นผล) โดยไม่ได้ใช้วิธีการที่จับลากมาวางแปะๆเหมือนตามตำรา ซึ่งแอดมินเชื่อว่าหลายๆคน อาจจะไม่ค่อยคุ้นเคยกันมากนักกับวิธีการแบบนี้ แต่เชื่อเถอะครับด้วยวิธีการออกแบบ และเขียนโค้ดในลักษณะนี้ มันจะมีความยืดหยุ่นที่สูงมากกว่า ยิ่งหากเราต้องทำงานในหลายๆโปรเจค ก็เรียกได้ว่าแค่ก็อปไปวางแปะได้เลย (หากเข้าใจแจ่มแจ้งนะขอรับ) ... หลักการทำงานของมัน เราสามารถนำไปเรียนรู้และใช้งานกับ VB.Net อย่างต่อเนื่องได้เลยทันที เพราะใช้หลักการเดียวกันครับผม (แค่คำที่เรียกใช้งานแตกต่างกัน) ...
มารู้จักกับคำว่า Bound Data และ UnBound Data Control
- Bound Data Control คือ การผูก (Bound) ตารางข้อมูล (RecordSet) เข้ากับพวก Component หรือ Control ต่างๆ ผ่านทาง DataSource กรณีที่นำมาใช้แสดงผลลงในตารางกริด มันจะอ่านค่าฟิลด์ต่างๆ เพื่อแสดงผลในแต่ละหลัก เรียงตามลำดับจากการ Query ที่เราเขียนไว้ และ ต้องแสดงทุกๆฟิลด์ออกมาทั้งหมด (หากไม่ต้องการแสดงผล จะต้องทำการซ่อนหลักของตัวกริดเอง) มีข้อดี คือ ทำงานได้เร็ว มักนำไปแสดงผลข้อมูลอย่างเดียว ซึ่งแอดมินจะใช้ในบทความนี้ทั้งหมดครับ
- UnBound Data Control ก็จะไม่มีการผูก (Unbound) ตารางข้อมูลใดๆเข้ากับ Component หรือ Control การนำไปใช้ในตารางกริด ไม่จำเป็นต้องแสดงผลออกมาทุกฟิลด์ และ จะเอาตัวไหนมาแสดงในหลักใดๆก่อนหลังก็ได้ มีข้อดี คือ ยืดหยุ่นมากกว่า และ มักใช้กับการแก้ไขข้อมูลของตารางกริดในแต่ละ Cell ได้นั่นเอง (อันนี้เดี๋ยวเป็นภาค 2 ต่อจากตอนนี้ครับ)
Download SharpGrid ActiveX/COM Grid Control (เฉพาะสมาชิกเท่านั้น)
หน้าตาของการออกแบบฟอร์ม (Design Time) ... ไม่ต้องปรับแต่งค่าคุณสมบัติ (Properties) ใดๆในตัว SharpGrid
ก่อนที่จะทำการลงมือเขียนโปรแกรม จะต้องทำการ Reference หรืออ้างอิงการติดต่อกับฐานข้อมูลก่อน
จากเมนู Project --> References ...
เรียกใช้งาน SharpGrid ActiveX Control ... เพื่อให้ SharpGrid มาปรากฏอยู่ใน ToolBox
จากเมนู Project --> Components ... เลือกแบบ Unicode เพื่อรองรับภาษาไทยได้
มาดูโค้ดกันเถอะ ... ในส่วนของฟอร์มหลัก
- ' / -----------------------------------------------------------------------------------------------
- ' / Developer : Mr.Surapon Yodsanga (Thongkorn Tubtimkrob)
- ' / eMail : thongkorn@hotmail.com
- ' / URL: http://www.g2gnet.com (Khon Kaen - Thailand)
- ' / Facebook: https://www.facebook.com/g2gnet (For Thailand only)
- ' / Facebook: https://www.facebook.com/commonindy (World Wide)
- ' /
- ' / Purpose : Sample to use SharpGrid ActiveX for Bound Data Control.
- ' / Microsoft Visual Basic 6.0 Service Pack 6 + MS Access 2003
- ' / -----------------------------------------------------------------------------------------------
- Option Explicit
- ' / -----------------------------------------------------------------------------------------------
- Private Sub Form_Load()
- ' / -----------------------------------------------------------------------------------------------
- '/ Trap Error
- On Error GoTo ErrorHandler
- '// การตั้งฟอร์มไว้กึ่งกลางจอภาพในแบบ Run Time
- Me.Move (Screen.Width - Me.Width) \ 2, (Screen.Height - Me.Height) \ 2
- '// ทำการติดต่อกับฐานข้อมูลก่อน (modDataBase.bas)
- Call OpenDataBase
- '// เคลียร์ค่า TextBox
- txtSearch.Text = ""
-
- '// ตั้งค่าการแสดงผล SharpGrid
- Call InitSGGrid
- '// ส่งค่า False เพื่อแจ้งโปรแกรมย่อยว่าแสดงผลข้อมูลออกมาทั้งหมด
- Call SGGridEmployeeBound(False)
-
- ExitProc:
- Exit Sub
-
- ErrorHandler:
- MsgBox "Error : " & Err.Number & vbCrLf & Err.Description, vbOKOnly + vbExclamation, "รายงานความผิดพลาด"
- Resume ExitProc
- '
- End Sub
- ' / -----------------------------------------------------------------------------------------------
- Sub InitSGGrid()
- ' / -----------------------------------------------------------------------------------------------
- ' Initialize grid properties
- With SGGridEmployee
- '/ ++++++++++++++++++++++++++++++++++++++++
- '/ กำหนดการแสดงผล GroupHeader หรือไม่
- '/ False คือ ไม่ต้องแสดงผล
- .GroupByBoxVisible = False
- '/ True จะแสดงผล GroupHeader ซึ่งจะทำให้ผู้ใช้งานลาก Column ไปจัดกลุ่มได้
- '/ ++++++++++++++++++++++++++++++++++++++++
-
- .FitLastColumn = True
- .Appearance = sg3D
- .SpecialMode = sgModeListBox
- .CellsBorderVisible = True
- .AutoResize = sgAutoResizeColumns
- .GroupIndentation = 225
-
- .DefaultRowHeight = 390
- .RowHeightMin = 390
- .HeadingColCount = 1
-
- .HeadingGridLinesColor = vbBlack
- .HeadingGridLines = sgGridLineFlat
-
- '/ สลับสีแถว
- .EvenOddStyle = sgEvenOddRows
- .ColorOdd = &HEFEFE0
-
- .CellTips = sgCellTipsFloat
- .CellTipsDelay = 400
- .ScrollBarTips = sgScrollTipsVertical
-
- .CacheAllRecords = True
- .ColumnClickSort = True
-
- '/ การแสดงผลปกติทั่วไป
- With .Styles("Normal")
- .BkgStyle = sgCellBkgSolid
- .Font.Name = "Tahoma"
- .Font.Size = 8
- .Padding = 18
- End With
-
- '/ ส่วนหัวของ Header กรณีการแสดงผลทั่วไป
- With .Styles("Heading")
- .BackColor = RGB(0, 153, 255)
- .ForeColor = vbWhite
- .Font.Name = "Tahoma"
- .Font.Size = 9
- .Font.Bold = True
- .Padding = 75
- End With
-
- '/ ส่วนหัวของ GroupHeader กรณีมีการจัดกลุ่ม
- With .Styles("GroupHeader")
- .Font.Size = 9
- .Font.Bold = True
- .BackColor = RGB(241, 239, 226)
- .BkgStyle = sgCellBkgSolid
- .Padding = 30
- .BorderColor = RGB(241, 207, 0)
- .Borders = sgCellBorderBottom
- .BorderSize = 1
- End With
-
- '/ ส่วนของ GroupFooter กรณีมีการจัดกลุ่ม
- With .Styles("GroupFooter")
- .Font.Size = 9
- .Font.Name = "Tahoma"
- .ForeColor = vbBlue
- .BackColor = RGB(255, 255, 224)
- .BkgStyle = sgCellBkgSolid
- .Padding = 75
- .BorderColor = RGB(255, 207, 0)
- .Borders = sgCellBorderBottom
- .BorderSize = 50
- .TextAlignment = sgAlignLeftCenter
- End With
-
- With .Styles("Tip")
- .Font.Size = 10
- .Padding = 40
- End With
-
- '/ กำหนดสีให้แถบแสงที่เราเลือกแถว
- With .Styles("Selection")
- .BackColor = RGB(0, 170, 0)
- .ForeColor = vbWhite
- .BkgStyle = sgCellBkgSolid
- End With
-
- '/ กำหนดสีให้แถบแสง กรณีที่เราไม่ได้เลือกแถวนั้น
- With .Styles("InactiveSelection")
- .BackColor = RGB(0, 170, 0)
- .ForeColor = vbWhite
- .BkgStyle = sgCellBkgSolid
- End With
- End With
- End Sub
- ' / -----------------------------------------------------------------------------------------------
- ' / อ่านค่า Primary Key จากหลัก 0 ที่ถูกซ่อนเอาไว้ เพื่อนำไปใช้งานอย่างอื่นต่อไป
- Private Sub SGGridEmployee_DblClick()
- ' / -----------------------------------------------------------------------------------------------
- '/ กำหนดให้อยู่ที่หลัก 0 ก่อน
- SGGridEmployee.Col = 0
- ' / อ่านค่าจากหลัก 0 และจากแถวที่เลือก (โดยไม่ต้องระบุแถวเลย)
- MsgBox "EmployeePK = " & Val(SGGridEmployee.Text)
- End Sub
- ' / -----------------------------------------------------------------------------------------------
- ' / ตัวแปร blnSearch เป็นออพชั่น หากไม่มีการส่งค่ามา ให้ถือว่ามันมีค่าเป็น FALSE
- ' / หาก blnSearch = False เป็นการแสดงผลข้อมูลทั้งหมด โดยไม่ต้องทำการค้นหา
- ' / หาก blnSearch = True เป็นการค้นหาข้อมูล ตามเงื่อนไขที่อยู่ใน TextBox
- Sub SGGridEmployeeBound(Optional blnSearch As Boolean = False)
- ' / -----------------------------------------------------------------------------------------------
- With SGGridEmployee
- '.Columns.RemoveAll False
- .DataRowCount = 0
- ' / หลัก 0 นี่คือหลักที่แสดงหมายเลขแถวครับ
- .Rows.At(0).Height = 420
- .ColumnClickSort = True
- .Columns(0).Width = 400
- .Columns(0).AllowSizing = False
- .Columns(0).Hidden = True
- .RowNumbering = False
- End With
-
- '/ สร้าง Instance ขึ้นมาใหม่ พร้อมตัดการเชื่อมต่อเดิมทิ้ง (หากลืม)
- Set RS = New ADODB.Recordset
- '/ blnSearch = True คือการค้นหาข้อมูล
- If blnSearch Then
- '// Bound Data จะแสดงผลโดยจัดเรียงข้อมูลตามฟิลด์ ที่อยู่ใน Query
- '// หากฟิลด์ใดที่เราไม่ต้องการให้แสดงผล ต้องไปตั้งค่าหลักนั้นใน SharpGrid ให้ Hidden = True
- Statement = _
- " SELECT tblEmployee.EmployeePK, tblEmployee.EmployeeID, tblEmployee.EmployeeName, tblPosition.PositionName, " & _
- " tblDepartment.DepartmentName, tblEmployee.DateStart, tblEmployee.Salary " & _
- " FROM (tblEmployee INNER JOIN tblDepartment ON tblEmployee.DepartmentFK = tblDepartment.DepartmentPK) INNER JOIN " & _
- " tblPosition ON tblEmployee.PositionFK = tblPosition.PositionPK " & _
- " WHERE " & _
- " ([EmployeeID] " & " Like '%" & Trim(txtSearch.Text) & "%'" & " OR " & _
- " [EmployeeName] " & " Like '%" & Trim(txtSearch.Text) & "%'" & " OR " & _
- " [PositionName] " & " Like '%" & Trim(txtSearch.Text) & "%'" & " OR " & _
- " [DepartmentName] " & " Like '%" & Trim(txtSearch.Text) & "%'" & ")" & _
- " ORDER BY EmployeeID, EmployeeName "
-
- '// blnSearch = False คือ แสดงผลทั้งหมด
- Else
- Statement = _
- " SELECT tblEmployee.EmployeePK, tblEmployee.EmployeeID, tblEmployee.EmployeeName, tblPosition.PositionName, " & _
- " tblDepartment.DepartmentName, tblEmployee.DateStart, tblEmployee.Salary " & _
- " FROM (tblEmployee INNER JOIN tblDepartment ON tblEmployee.DepartmentFK = tblDepartment.DepartmentPK) INNER JOIN " & _
- " tblPosition ON tblEmployee.PositionFK = tblPosition.PositionPK " & _
- " ORDER BY DepartmentName, EmployeeID "
- End If
-
- ' ============ IMPORTANT ==========
- ' / ระบุให้ทำงานในโหมด BOUND DATA
- SGGridEmployee.DataMode = sgBound
- ' ==================================
- RS.CursorLocation = adUseClient
- '// adOpenForwardOnly และ adLockReadOnly เป็นการอ่านข้อมูลเดินหน้าอย่างเดียว จะมีความเร็วในการนำข้อมูลมาแสดงผล
- RS.Open Statement, ConnDB, adOpenForwardOnly, adLockReadOnly, adCmdText
-
- '/ =============== ผูกเข้ากับตาราง RecordSet ================
- '/ เหมือนการกำหนด DataSource ใน VB.NET
- Set SGGridEmployee.DataSource = RS
- '/ ====================================================
-
- '/ แสดงจำนวนรายการ
- SGGridEmployee.DataRowCount = RS.RecordCount
- If RS.RecordCount >= 0 Then
- lblSearch.Caption = "[จำนวน : " & RS.RecordCount & " รายการ.]"
- Else
- lblSearch.Caption = "[จำนวน : 0" & " รายการ.]"
- End If
- '// จัดรูปแบบหลักใหม่
- Call SetupSGGrid
- ' / Always must be disconnect RecordSet
- RS.Close: Set RS = Nothing
- End Sub
- ' / -----------------------------------------------------------------------------------------------
- ' / การตั้งค่าหลักต่างๆ ต้องให้ตรงกันกับฟิลด์ข้อมูลในการ Query จากโปรแกรมย่อย SGGridEmployeeBound
- Private Sub SetupSGGrid()
- ' / -----------------------------------------------------------------------------------------------
- '/ การกำหนดโหมด Bound Data ทำให้เกิดการนับจำนวนหลักเอาไว้ให้เรียบร้อย
- ' ================ Setup SGGrid ====================
- With SGGridEmployee
- '// Start Columns 1 โดยใช้ค่า Index ที่เรียงมาจาก Query
- With .Columns(1)
- '/ แสดงผลหัวข้อหลัก
- .Caption = "EmployeePK"
- '/ ความกว้างเป็น 0
- .Width = 0
- '/ ไม่ยอมให้ปรับขนาดความกว้างของหลัก
- .AllowSizing = False
- '/ เอาไปซ่อนจากสายตาผู้ใช้ไปเลย กรณีที่เราไม่ต้องการให้หลักนี้มีการแสดงผลให้ผู้ใช้งานเห็น
- .Hidden = True
- End With
- ' 2
- With .Columns(2)
- .Caption = "รหัสพนักงาน"
- '/ ตั้งค่าการแสดงตำแหน่งของข้อมูล
- .Style.TextAlignment = sgAlignLeftCenter
- .HeadingStyle.TextAlignment = sgAlignLeftCenter
- .AllowSizing = True
- End With
- ' 3
- With .Columns(3)
- .Caption = "ชื่อ - นามสกุล"
- .Style.TextAlignment = sgAlignLeftCenter
- .HeadingStyle.TextAlignment = sgAlignLeftCenter
- .AllowSizing = True
- End With
- ' 4
- With .Columns(4)
- .Caption = "ตำแหน่ง"
- .Style.TextAlignment = sgAlignLeftCenter
- .HeadingStyle.TextAlignment = sgAlignLeftCenter
- .AllowSizing = True
- End With
- ' 5
- With .Columns(5)
- .Caption = "แผนก"
- .Style.TextAlignment = sgAlignLeftCenter
- .HeadingStyle.TextAlignment = sgAlignLeftCenter
- .AllowSizing = True
- End With
- ' 6
- With .Columns(6)
- .Caption = "วันที่เริ่มทำงาน"
- .Style.TextAlignment = sgAlignRightCenter
- .HeadingStyle.TextAlignment = sgAlignRightCenter
- .Style.Format = "dd/mm/yyyy"
- .AllowSizing = True
- End With
- ' ใช้ชื่อฟิลด์ข้อมูลแทนหมายเลข Index แทนก็ได้
- With .Columns("Salary")
- .Caption = "เงินเดือน"
- .Style.TextAlignment = sgAlignRightCenter
- .HeadingStyle.TextAlignment = sgAlignRightCenter
- .DataType = sgtCurrency
- .Style.Format = "#,##0.00"
- .AllowSizing = False
- End With
- '
- End With
- End Sub
- ' / -----------------------------------------------------------------------------------------------
- ' / กดปุ่ม Refresh เพื่อทำการแสดงผลข้อมูลทั้งหมด
- Private Sub cmdRefresh_Click()
- ' / -----------------------------------------------------------------------------------------------
- Call SGGridEmployeeBound(False)
- With SGGridEmployee
- .LeftCol = 0
- .SetFocus
- Sendkeys "{RIGHT}"
- End With
- txtSearch.Text = ""
- End Sub
- ' / -----------------------------------------------------------------------------------------------
- ' / เมื่อคลิ๊กที่ปุ่มค้นหา
- Private Sub cmdSearch_Click()
- ' / -----------------------------------------------------------------------------------------------
-
- ' / ตัดคำสงวน (Reserved Word) ที่มีปัญหากับฐานข้อมูลออกไป
- txtSearch.Text = Replace(txtSearch.Text, "'", "")
- txtSearch.Text = Replace(txtSearch.Text, "%", "")
- txtSearch.Text = Replace(txtSearch.Text, "*", "")
- If Trim(txtSearch.Text) = "" Or Len(txtSearch.Text) = 0 Then Exit Sub
-
- '/ ทำการค้นหาข้อมูล
- Call SGGridEmployeeBound(True)
-
- End Sub
- Private Sub txtSearch_KeyDown(KeyCode As Integer, Shift As Integer)
- If KeyCode = vbKeyDown Then Sendkeys "{TAB}"
- If KeyCode = vbKeyUp Then Sendkeys "+{TAB}"
- End Sub
- Private Sub txtSearch_KeyPress(KeyAscii As Integer)
- '// เกิดการกด Enter (ASCII Code มีค่าเท่ากับ 13 ฐาน 10)
- If KeyAscii = 13 Then
- Call cmdSearch_Click
- '// ปิดเสียงด้วยการกำหนดให้ KeyAscii = 0 หรือไม่มีการกดคีย์ใดๆ
- KeyAscii = 0
- End If
- End Sub
- Private Sub cmdRefresh_KeyDown(KeyCode As Integer, Shift As Integer)
- If KeyCode = vbKeyDown Or KeyCode = vbKeyRight Then Sendkeys "{TAB}"
- If KeyCode = vbKeyUp Or KeyCode = vbKeyLeft Then Sendkeys "+{TAB}"
- End Sub
- Private Sub Form_Resize()
- If Me.ScaleWidth < 120 Or Me.ScaleHeight < 120 Then Exit Sub
- fraData.Height = Me.ScaleHeight - 60
- fraData.Move 15, 0, Me.ScaleWidth - 15
- SGGridEmployee.Move 15, 615, fraData.Width - (SGGridEmployee.Left) - 15, fraData.Height - 690
- End Sub
- Private Sub Form_Unload(Cancel As Integer)
- On Error Resume Next
- If Dir$(App.Path & "\*.tmp") <> "" Then Kill App.Path & "\*.tmp"
- '/ ปิดการเชื่อมต่อกับฐานข้อมูล
- Call CloseDataBase
- End
- End Sub
คัดลอกไปที่คลิปบอร์ด
มาดูโค้ดในส่วนของโมดูลหลักที่เชื่อมต่อกับฐานข้อมูล ... (modDataBase.bas หรือ โมดูลหากิน)
- ' / -----------------------------------------------------------------------------------------------
- ' / Developer : Mr.Surapon Yodsanga (Thongkorn Tubtimkrob)
- ' / eMail : thongkorn@hotmail.com
- ' / URL: http://www.g2gnet.com (Khon Kaen - Thailand)
- ' / Facebook: https://www.facebook.com/g2gnet (For Thailand only)
- ' / Facebook: https://www.facebook.com/commonindy (World Wide)
- ' /
- ' / Purpose : Function to connect the MS Access DataBase.
- ' / Microsoft Visual Basic 6.0 Service Pack 6 + MS Access 2003
- ' / -----------------------------------------------------------------------------------------------
- Option Explicit
- '// ก่อนใช้งานต้องเลือก MDAC 2.8 มาจาก Project --> Refernces ก่อน
- Global ConnDB As New ADODB.Connection
- Global RS As New ADODB.Recordset ' / RecordSet หลัก
- Global DS As New ADODB.Recordset ' / RecordSet สำรอง
- Global RstData As New ADODB.Recordset ' / ใช้ในการพิมพ์รายงาน
- Global Statement As String
- Global SQLStmt As String
- ' / -----------------------------------------------------------------------------------------------
- Public Sub OpenDataBase()
- On Error GoTo Err_Handler
- Dim DB_File As String
- DB_File = App.Path
- If Right$(DB_File, 1) <> "" Then DB_File = DB_File & ""
- DB_File = DB_File & "DataBase.MDB"
- ' Open a connection.
- Set ConnDB = New ADODB.Connection
- ConnDB.ConnectionString = _
- "Provider=Microsoft.Jet.OLEDB.4.0;" & _
- "Data Source=" & DB_File & ";" & _
- "Persist Security Info=False"
- '" Jet OLEDB:Database Password=" & "password" & ";" '& _
- '" Engine Type=5;"
- ConnDB.Open
- Exit Sub
- Err_Handler:
- MsgBox "Open Database Error : " & vbCrLf & Err.Number & " " & Err.Description
- End
- End Sub
- Public Sub CloseDataBase()
- ' ตรวจสอบว่ามีการเชื่อมโยง - Connect ข้อมูลหรือไม่
- If ConnDB.State = adStateOpen Then
- ConnDB.Close
- Set ConnDB = Nothing
- End If
- End Sub
- ' / -----------------------------------------------------------------------------------------------
- ' / ฟังค์ชั่นแก้ไขในการ SendKeys ซึ่งใน Windows 8+ 64 บิท จะมีปัญหา
- Public Sub Sendkeys(Text As String, Optional Wait As Boolean = False)
- Dim WshShell As Object
- Set WshShell = CreateObject("Wscript.shell")
- WshShell.Sendkeys Text, Wait
- Set WshShell = Nothing
- End Sub
คัดลอกไปที่คลิปบอร์ด
Conslusion: อย่าเพียงแต่ลอกโค้ดแล้วไปสั่งรันให้ผ่านเท่านั้นนะครับ ต้องพยายามทำความเข้าใจในแต่ละชุดแถวคำสั่งที่สำคัญเอาไว้ให้ดีด้วย ซึ่งแอดมินได้พยายามเขียนคอมเมนท์ อธิบายในส่วนที่สำคัญๆเอาไว้ให้ได้อ่านกัน การใช้ Debugger เข้ามาช่วย จะทำให้เราสามารถเรียนรู้และเข้าใจหลักการทำงานต่างๆของโค้ดได้อย่างไม่ยากเย็น ... ขอให้โชคดี
Download SharpGrid ActiveX/COM Grid Control (เฉพาะสมาชิกเท่านั้น)
ดาวน์โหลดโค้ดต้นฉบับ VB6 ได้ที่นี่ ...
|
ขออภัย! โพสต์นี้มีไฟล์แนบหรือรูปภาพที่ไม่ได้รับอนุญาตให้คุณเข้าถึง
คุณจำเป็นต้อง ลงชื่อเข้าใช้ เพื่อดาวน์โหลดหรือดูไฟล์แนบนี้ คุณยังไม่มีบัญชีใช่ไหม? ลงทะเบียน
x
|