หากมีคำถาม ขอให้ไปโพสต์ลง เว็บบอร์ดจีทูจีเน็ตดอตคอม ตัวใหม่แทนน่ะครับ

หรือติดต่อเข้ามาทาง Inbox ที่ เฟซบุ๊ค ผมครับ

หน้าหลัก
ข่าวสาร - บทความ ทั้งหมด
VB 6/VB.Net
ASP/ASP.Net
จับฉ่ายคอมพิวเตอร์
เรียนรู้ผ่าน Flash Movie
บทความที่มีผู้ตอบล่าสุด  
 RSS Feeds
 ดาวน์โหลดโปรแกรม RSS Reader ได้ที่นี่ ...   Download โปรแกรม RSS Reader

Forum - www.g2gnet.com
Webmaster - www.g2gnet.com
Visitors - Session views
 5 5 9 1 7 3 3

7 ธันวาคม พ.ศ.2549
90 Users On-Line.
Visitors - Page views
 8 9 4 6 7 8 3
1 กุมภาพันธ์ พ.ศ.2551

Google   
เว็บ g2gnet.com
ขนาดตัวอักษร:  

พื้นฐานในการใช้งาน MS FlexGrid ก่อนสร้างความสัมพันธ์แบบ One To Many (ภาค 3)

Category »  VB 6/VB.Net
โดย : Webmaster เมื่อ 7/4/2553   เวลา: 16:31
(อ่าน : 16145) 
ตอนนี้จะเป็นการค้นหาสินค้า (หรืออื่นๆ) เพื่ออำนวยความสะดวกให้กับผู้ใช้งานมากขึ้น การค้นหาจะทำได้นอกจากรหัสสินค้าแล้ว ยังค้นหาด้วยชื่อสินค้า หรืออื่นๆก็ได้อีก กระบวนการขั้นตอนก็ไม่มีอะไรมาก หรือ ยากจนเกินเหตุ เริ่มต้นด้วยการคลิ๊กปุ่มเพื่อเปิดฟอร์มรายการค้นหาสินค้าขึ้นมา จากนั้นผู้ใช้ก็จะทำการค้นหาข้อมูลตามที่ต้องการ กรณีหากหาข้อมูลสินค้าไม่พบ ก็สามารถเพิ่มขึ้นมาใหม่ได้เลยทันที หากหาข้อมูลพบ ก็จะส่ง Primary Key ของสินค้านั้นๆกลับไปยังฟอร์มหลัก (รายละเอียดได้แจ้งไว้ในโค้ดแล้ว) เมื่อกลับมายังหน้าจอหลักการขาย ก็จะทำการค้นหาสินค้าอีกรอบ ... ทำไมต้องใช้การค้นหาถึง 2 รอบ ... หาคำตอบได้จากโค้ดทางด้านล่างเลยครับพี่น้อง ... อิอิอิอิอิ ... แหม การเข้าเรื่องในรอบนี้มันช่างน่าติดตามจังเลย เหอๆๆๆๆ
ดาวน์โหลด
ดาวน์โหลด Source Code สำหรับ MS Visual Basic 6.0 - Service Pack 6
 ดาวน์โหลด Visual Basic 6.0 SP5: Run-Time Redistribution Pack
 ดาวน์โหลด Microsoft Data Access Object (MDAC) และ Jet 4.0 Update
 ดาวน์โหลด Microsoft Visual Basic Service Pack 6
ข้อมูลเพิ่มเติม
ตารางกริด (MS Flex Grid) ธรรมดา ที่ไม่ธรรมดา ... VB 6.0
การอ่านข้อมูลแบบ Text File เข้าสู่ MS FlexGrid ด้วย MS Visual Basic 6.0
ตารางกริด (MS Flex Grid) ธรรมดา ที่ไม่ธรรมดา ... ตอนการจัดเรียงข้อมูลในการแสดงผลให้ MS FlexGrid
ตารางกริด (MS Flex Grid) ธรรมดา ที่ไม่ธรรมดา ... ตอนใช้ Wheel Mouse ใน MS FlexGrid
ตารางกริด (MS Flex Grid) ธรรมดา ที่ไม่ธรรมดา ... ตอนจับยัดข้อมูลเข้าไปใน MS FlexGrid ได้
พื้นฐานในการใช้งาน MS FlexGrid ก่อนสร้างความสัมพันธ์แบบ One To Many (ภาค 1)
พื้นฐานในการใช้งาน MS FlexGrid ก่อนสร้างความสัมพันธ์แบบ One To Many (ภาค 2)
เริ่มต้นกระบวนการทำงาน
modDataBase.bas โมดูลหากิน (มันมาอีกแล้ว) ... 55555+

Option Explicit

Global ConnDB As New ADODB.Connection
Global RS As New ADODB.Recordset
Global DS As New ADODB.Recordset
Global Statement As String
Global SQLStmt As String
'
' กำหนดว่าเป็นการเพิ่ม หรือ แก้ไขข้อมูล
Global blnNewData As Boolean
' ให้เกิดการ Update ในฟอร์มที่มีการเปลี่ยนแปลง
Global FormUpdate As Boolean

' ตัวแปรแบบ Global เพื่อส่งค่า Primary Key ไปมาระหว่างฟอร์มการขาย และ ค้นหาสินค้า
' นอกจากนี้ยังสามารถนำไปใช้กับส่วนอื่นๆเช่น ค้นหาลูกค้า ผู้ขาย หรือ อื่นๆได้อีก ... เอาให้คุ้ม
Global gPK As Long

' เชื่อมเข้าสู่ไฟล์ฐานข้อมูล MS Access
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 & "ProductDB.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"
    ConnDB.Open
    Exit Sub
    
Err_Handler:
    MsgBox "Error : " & 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


การเลือกคลิ๊กที่ปุ่มค้นหา cmdSearchData (จากฟอร์มหลักการขาย frmSearchDB)

Private Sub cmdSearchData_Click()
    ' กำหนดค่า Primary Key แบบ Global ไว้ล่วงหน้า ตัวแปรนี้อยู่ใน modDataBase.bas น่ะครับ
    gPK = -1
    ' vbModal คือการที่ให้ฟอร์มอยู่เหนือฟอร์มอื่นๆทั้งหมด และ โฟกัสมาที่ฟอร์มนี้เท่านั้น
    ' เรียกฟอร์มค้นหาสินค้าขึ้นมา
    frmSearchProduct.Show vbModal
    
    ' เมื่อปิดฟอร์มที่ค้นหาข้อมูลแล้ว จะเกิดการส่งค่า ProductPK มาทาง gPK มี 2 กรณี
    ' 1. gPK = -1 แสดงว่าไม่มีข้อมูลที่ต้องการ จบออกจากโปรแกรมย่อยได้ทันที
    ' 2. gPK <> -1 นั่นคือ ส่งค่า Primary Key กลับมา เราก็ต้องค้นหารายการสินค้าอีกรอบ
    ' ผมใช้ Primary Key กลับมาค้นหาอีกรอบ ซึ่งหากบางคนไม่ชอบวิธีนี้ก็ใช้ตัวแปรกำหนดแทนก็ได้น่ะครับ
    ' แต่มันต้องใช้เยอะทั้งรหัสสินค้า ชื่อสินค้า จำนวน ราคา อื่นๆอีก ซึ่งไม่สะดวก และ ยุ่งยากไปครับ
    ' แล้วทำไมไม่ให้คืนค่ากลับด้วยรหัสสินค้ามาเลย ...
    ' - การค้นหาข้อมูลด้วยตัวเลข จะเข้าถึงข้อมูลได้เร็วกว่าแบบ String
    ' - สำคัญ ... หากเรามีรหัสสินค้า หรือ รหัสบาร์โค้ดหลายชุดในสินค้าตัวเดียวกัน จะยุ่งยากมาก ... แจ่มมั้ยครับ
    
    ' ตรวจสอบรายการสินค้าอีกรอบ
    If gPK <> -1 Then
        ' คราวนี้ต้องส่งค่าไปบอกโปรแกรมย่อยด้วยว่าค้นหาด้วยอะไร
        ' 0 คือ ค้นหาจาก txtSearch
        ' 1 คือ ค้นหาจากปุ่ม cmdSearchData
        Call CheckDataRow(1)
    End If
End Sub

เปิดฟอร์มที่ใช้ค้นหารายการสินค้าขึ้นมา (frmSearchProduct)

โค้ดในการค้นหาข้อมูลในฟอร์ม frmSearchProduct และส่งค่า Primary Key (gPK) ของสินค้ากลับคืนไป

Private Sub Form_Load()
    ' ตั้งค่าฟอร์มกึ่งกลางจอภาพ
    Me.Move (Screen.Width - Width) \ 2, (Screen.Height - Height) \ 2
    
    txtSearch.Text = ""
    
    ' แหมก็หาไอคอนกราฟิคมาใส่ให้สวยงามหน่อยล่ะ
    With Me
        cmdNew.Picture = .i16x16.ListImages(1).Picture
        cmdEdit.Picture = .i16x16.ListImages(2).Picture
        cmdDelete.Picture = .i16x16.ListImages(3).Picture
        cmdRefresh.Picture = .i16x16.ListImages(5).Picture
    End With
    
    ' จัดระเบียบให้ ListView
    With lvwData
        ' หลักแรกให้ซ่อน Primary Key ของสินค้าไว้ (ตลอดเลย)
        .ColumnHeaders.Add 1, , "PK", 0
        .ColumnHeaders.Add 2, , "รหัสสินค้า", 1600
        .ColumnHeaders.Add 3, , "รายการสินค้า", .Width \ 2 + 950
    End With
    
    ' แสดงผลข้อมูลใน ListView
    Call ShowListView(False)
    
End Sub

' ======================================
' ให้ตัวแปร blnSearch เป็นตัวรับค่าที่ใช้ในการแสดงผล
' ======================================
Sub ShowListView(blnSearch As Boolean)
Dim LV As Variant

    
    Set RS = New Recordset
    Select Case blnSearch
        ' จริง คือการค้นหาข้อมูล
        Case True
            SQLStmt = "SELECT tblProduct.ProductPK, tblProduct.ProductCode, tblProduct.Description " & _
                            " FROM tblProduct " & _
                            " WHERE " & _
                            " [ProductCode] " & " Like '%" & Trim(txtSearch.Text) & "%'" & " OR " & _
                            " [Description] " & " Like '%" & Trim(txtSearch.Text) & "%'" & _
                            " ORDER BY ProductPK "

        ' เท็จ คือการสั่งรีเฟรชการแสดงผลข้อมูลใหม่
        ' Case Else ก็ได้น่ะครับ เพราะค่ามันจะส่งมาได้ 2 ค่า คือ จริง กับ เท็จ เท่านั้นเอง
        Case False
            SQLStmt = "SELECT tblProduct.ProductPK, tblProduct.ProductCode, tblProduct.Description " & _
                            " FROM tblProduct " & _
                            " ORDER BY ProductPK "
    End Select

    RS.CursorLocation = adUseClient
    ' การอ่านแบบเดินหน้าอย่างเดียว adOpenForwardOnly เพื่อให้เข้าถึงข้อมูลได้เร็วขึ้น
    RS.Open SQLStmt, ConnDB, adOpenForwardOnly, adLockReadOnly, adCmdText
    lblCount.Caption = "[จำนวน : " & RS.RecordCount & " รายการ]"
    
    lvwData.View = lvwReport
    lvwData.ListItems.Clear
    
    ' ทำลูปเพื่อนำค่าจากตารางย่อย (Detail) มาแสดงผลใน ListView ให้หมด
    Do While Not RS.EOF
        ' ทำโหนด (Node) ให้มันก่อนล่ะ
        Set LV = lvwData.ListItems.Add(, , RS("ProductPK"), 0, 0)
        LV.SubItems(1) = "" & RS("ProductCode")
        LV.SubItems(2) = "" & RS("Description")
        RS.MoveNext
    Loop

RS.Close:   Set RS = Nothing
End Sub

' ======================================
' เลือกรายการสินค้าตามที่ต้องการ
' ======================================
Private Sub lvwData_DblClick()
    
    ' หากมีการเลือกรายการก็ส่งค่า PrimaryKey (ซ่อนเอาไว้ในหลักแรก) ที่ได้กลับไปยังฟอร์มที่เรียกมา
    ' กรณีของการยกเลิก หรือ ไม่เลือกรายการใดๆ ค่า gPK = -1 เหมือนเดิม
    ' จะอ่านค่าจาก Node ตัวมันเองครับ นั่นก็คือหลักแรกที่เรานำค่า Primary Key ไปซ่อนไว้นั่นเอง
    gPK = Val(lvwData.SelectedItem.Text)

    ' หากเป็นข้อมูลในหลักอื่นๆใช้ Method --> lvwData.SelectedItem.SubItems(1)
    
    Unload Me
End Sub

Private Sub cmdExit_Click()
    ' ส่งค่ากลับให้น้อยกว่า 0 เพื่อแจ้งว่าไม่มีการเลือกรายการใด
    gPK = -1
    Unload Me
End Sub

' สั่งแสดงผลรายการสินค้าใหม่ทั้งหมด
Private Sub cmdRefresh_Click()
    txtSearch.Text = ""
    ' ไม่ใช่การค้นหา เลยต้องค่าเท็จไปโปรแกรมย่อย
    Call ShowListView(False)
    lvwData.SetFocus
End Sub

' ======================================
' การค้นหารายการสินค้าได้ทั้งรหัสสินค้า และ ชื่อสินค้า
' ======================================
Private Sub cmdSearch_Click()
    If Trim(txtSearch.Text) = "" Or Len(Trim(txtSearch.Text)) = 0 Then
        txtSearch.SetFocus
        Exit Sub
    End If
    
    ' ต้อง Repace ค่า ' (Single Quote) ออกก่อนน่ะครับ ... มิฉะนั้นมันจะเกิด Error ไม่เชื่อผมก็ลองดูซิครับ ... พี่น้อง
    ' อีกตัวหนึ่งที่ต้องเอาออกด้วยก็คือ ... แอ่น แอ้น ... % ครับ เพราะใน Access มันเสมือนหนึ่งว่าทำการค้นหาข้อมูลทั้งหมด
    txtSearch.Text = Replace(txtSearch.Text, "'", "")
    txtSearch.Text = Replace(txtSearch.Text, "%", "")
    
    ' ส่งค่า True เพื่อไปบอกโปรแกรมย่อย ShowListView ว่าเป็นการค้นหาข้อมูลเด้อ
    Call ShowListView(True)
    lvwData.SetFocus
    
End Sub
กลับมาหน้าฟอร์มการขายหลัก (frmSearchDB) อีกรอบ เพื่อทำการค้นหาสินค้าด้วย Primary Key

การเลือกคลิ๊กที่ปุ่มค้นหา cmdSearchData
Private Sub cmdSearchData_Click()
    ' กำหนดค่า Primary Key แบบ Global ไว้ล่วงหน้า ตัวแปรนี้อยู่ใน modDataBase.bas น่ะครับ
    gPK = -1
    ' vbModal คือการที่ให้ฟอร์มอยู่เหนือฟอร์มอื่นๆทั้งหมด และ โฟกัสมาที่ฟอร์มนี้เท่านั้น
    ' เรียกฟอร์มค้นหาสินค้าขึ้นมา
    frmSearchProduct.Show vbModal
    
    ' เมื่อปิดฟอร์มที่ค้นหาข้อมูลแล้ว จะเกิดการส่งค่า ProductPK มาทาง gPK มี 2 กรณี
    ' 1. gPK = -1 แสดงว่าไม่มีข้อมูลที่ต้องการ จบออกจากโปรแกรมย่อยได้ทันที
    ' 2. gPK <> -1 นั่นคือ ส่งค่า Primary Key กลับมา เราก็ต้องค้นหารายการสินค้าอีกรอบ
    ' ผมใช้ Primary Key กลับมาค้นหาอีกรอบ ซึ่งหากบางคนไม่ชอบวิธีนี้ก็ใช้ตัวแปรกำหนดแทนก็ได้น่ะครับ
    ' แต่มันต้องใช้เยอะทั้งรหัสสินค้า ชื่อสินค้า จำนวน ราคา อื่นๆอีก ซึ่งไม่สะดวก และ ยุ่งยากไปครับ
    ' แล้วทำไมไม่ให้คืนค่ากลับด้วยรหัสสินค้ามาเลย ...
    ' - การค้นหาข้อมูลด้วยตัวเลข จะเข้าถึงข้อมูลได้เร็วกว่าแบบ String
    ' - สำคัญ ... หากเรามีรหัสสินค้า หรือ รหัสบาร์โค้ดหลายชุดในสินค้าตัวเดียวกัน จะยุ่งยากมาก ... แจ่มมั้ยครับ
    
    ' ตรวจสอบรายการสินค้าอีกรอบ
    If gPK <> -1 Then
        ' คราวนี้ต้องส่งค่าไปบอกโปรแกรมย่อยด้วยว่าค้นหาด้วยอะไร
        ' 0 คือ ค้นหาจาก txtSearch
        ' 1 คือ ค้นหาจากปุ่ม cmdSearchData
        Call CheckDataRow(1)
    End If
End Sub

' ======================================================
' การตรวจสอบค่าใน MS FlexGrid ก่อนที่จะแสดงผลรายการใหม่
' แก้ไขจากเดิม เพื่อไม่ให้มีโปรแกรมย่อยคล้ายๆกันทำงานซ้ำซาก โดย
' หากส่งค่า 0 มา ให้เป็นการค้นหาด้วยรหัสสินค้า (ProductCode) จาก txtSearch
' หากส่งค่า 1 มา ให้เป็นการค้นหา Primary Key จากการกดปุ่ม cmdSearchData
' ======================================================
Private Sub CheckDataRow(SearchProduct As Byte)
    Dim CurrentRow As Integer

    ' หากค้นหาข้อมูลรหัสสินค้าจาก txtSearch
    If SearchProduct = 0 Then
        ' ตรวจสอบว่าเป็นค่าว่างหรือไม่ หากใช่ก็ออกจากโปรแกรมย่อย (User ไม่มีการคีย์ข้อมูลใดๆ)
        If Trim(txtSearch.Text) = "" Or Len(Trim(txtSearch.Text)) = 0 Then
            txtSearch.SetFocus
            Exit Sub
        End If
    
        ' ค้นหาข้อมูลรหัสสินค้าในตารางสินค้า (tblProduct) ... ใช้ = (Equal) ได้เท่านั้น
        Set RS = New Recordset
        Statement = "SELECT tblProduct.ProductPK, tblProduct.ProductCode, " & _
                            " tblProduct.Description, tblUnit.UnitName, tblProduct.PriceUnit " & _
                            " FROM tblProduct INNER JOIN tblUnit ON tblProduct.UnitFK = tblUnit.UnitPK " & _
                            " WHERE ProductCode = " & "'" & Trim$(txtSearch.Text) & "'"
        
        ' เคลียร์ค่าไว้รอเลย
        txtSearch.Text = ""
        
    ' หากค้นหาข้อมูลด้วยการเลือกจากปุ่ม cmdSearchData
    Else
    
        ' ค้นหาข้อมูล Primary Key ของสินค้า ในตารางสินค้า (tblProduct) ... ใช้ = (Equal) ได้เท่านั้น
        ' และเป็นการค้นหาด้วยตัวเลขน่ะครับ สังเกตความแตกต่างจากการค้นหาด้วย String
        Set RS = New Recordset
        Statement = "SELECT tblProduct.ProductPK, tblProduct.ProductCode, " & _
                            " tblProduct.Description, tblUnit.UnitName, tblProduct.PriceUnit " & _
                            " FROM tblProduct INNER JOIN tblUnit ON tblProduct.UnitFK = tblUnit.UnitPK " & _
                            " WHERE ProductPK = " & gPK
    
    End If
    
    RS.CursorLocation = adUseClient
    RS.Open Statement, ConnDB, adOpenForwardOnly, adLockReadOnly, adCmdText
    ' ไม่พบข้อมูล ให้ออกจากโปรแกรมย่อยไปได้เลย
    If RS.RecordCount = 0 Then
        RS.Close:   Set RS = Nothing
        Exit Sub
    End If
    
    
    ' เริ่มต้นการค้นหาข้อมูลในตารางกริด
    For CurrentRow = 1 To fgData.Rows - 1
        ' ค้นหารหัสสินค้าที่อยู่ในหลักที่ 1
        If fgData.TextMatrix(CurrentRow, 1) = RS("ProductCode") Then
            
            ' หากพบรายการสินค้าเดิมใส่จำนวนสินค้าเพิ่มเข้าไปอีก 1 ทันที ในแถวที่อยู่ ณ ปัจจุบัน
            fgData.TextMatrix(CurrentRow, 5) = Val(fgData.TextMatrix(CurrentRow, 5)) + 1
            
            ' คูณราคาสินค้า กับจำนวนสินค้าเข้าไปใหม่
            fgData.TextMatrix(CurrentRow, 6) = Format(Val(fgData.TextMatrix(CurrentRow, 4)) * _
                            Val(fgData.TextMatrix(CurrentRow, 5)), "0.00")
                            
            RS.Close:   Set RS = Nothing
            
            ' ไปโปรแกรมย่อยเพื่อคำนวณจำนวนเงินทั้งหมด
            Call CalTotalAmount

            ' จบจากการวนรอบ FOR และ ออกจากโปรแกรมย่อยไปเลยครับ
            Exit Sub
        End If
    Next
    
    ' =================================================
    ' การนำรายละเอียดของสินค้าเข้าสู่ตารางกริดนั่นเอง
    ' =================================================
    ' เพิ่มจำนวนแถวใน MS FlexGrid อีก 1 แถว
    fgData.Rows = fgData.Rows + 1
    
    ' ให้แถวปัจจุบันลดลง 1 (เพื่อไม่ให้นับ Column Header)
    CurrentRow = fgData.Rows - 1
    
    ' แถวใหม่ที่เพิ่มเข้ามา ทำการอ่านข้อมูลจาก RecordSet เข้ามา
    ' ปกติหลักแรก (หลัก 0) ต้องนำเอาค่า Primary Key ไปซ่อนเอาไว้น่ะครับ ... อย่าลืม
    fgData.TextMatrix(CurrentRow, 0) = RS("ProductPK")
    ' แสดงรหัสสินค้า
    fgData.TextMatrix(CurrentRow, 1) = "" & RS("ProductCode")
    ' แสดงชื่อสินค้า
    fgData.TextMatrix(CurrentRow, 2) = "" & RS("Description")
    ' แสดงหน่วยนับสินค้า
    fgData.TextMatrix(CurrentRow, 3) = "" & RS("UnitName")
    ' แสดงราคาสินค้า
    fgData.TextMatrix(CurrentRow, 4) = Format(RS("PriceUnit"), "0.00")
    ' ใส่จำนวนสินค้าครั้งละ 1
    fgData.TextMatrix(CurrentRow, 5) = 1
    ' คำนวณราคาขาย กับ จำนวน
    fgData.TextMatrix(CurrentRow, 6) = Format(fgData.TextMatrix(CurrentRow, 4) * _
                                fgData.TextMatrix(CurrentRow, 5), "0.00")
    
    RS.Close:   Set RS = Nothing
    
    ' ไปโปรแกรมย่อยเพื่อคำนวณจำนวนเงินทั้งหมด
    Call CalTotalAmount
    
End Sub
Conclusion:
มาถึงตอนที่ 3 แล้ว หลายคนที่ว่ามันยาก ก็คงจะได้กระจ่างแจ้งในใจกันแล้ว (มั้ง) น่ะครับ "ไม่เห็นยากสักกะหน่อยเลย" หากเรารู้จักกลวิธีในการออกแบบ และ การจัดเรียงลำดับของงานให้เป็นแล้ว นอกจากนี้ก็ยังได้รู้จักเทคนิคบางอย่างของการเขียนโปรแกรม ตามที่ผมได้บรรยายให้รับรู้กันไปแล้ว แหละนี่คือแนวคิด และ วิธีการที่ผมนำไปใช้กับงานจริงๆของผม และยังใช้เพื่อนำมาสอนคน (เพราะผมไม่ได้สอนหนังสือครับ) ให้กับลูกศิษย์ท้ายกุฏิ (ดื้อ มึน ด้าน) ทั้งหลายของผม แต่เวลาที่เขาทั้งหลายเหล่านี้ พร้อมออกไปเผชิญชีวิตในโลกการทำงานได้เองโดยลำพังแล้ว ... เหงาเหมือนกันครับ เพราะไม่มีม้าเร็วไปซื้อกับแกล้ม โซดา น้ำแข็ง มาให้ผมเลยครับพี่น้อง ... 55555+

จี ทู จี เน็ต ดอต คอม - g2gNet Dot Com
เลขทะเบียนพาณิชย์อิเล็กทรอนิกส์ 0407314800231
CopyLeft © 2004 - 2099 g2gNet.Com All rights reserved.
Email: [email protected] หรือ โทร. 08-6862-6560