วิธีในการสร้าง Path ให้กับ Application (ให้มันถูกต้อง)

Posted by Unknown Friday, September 7, 2012 0 comments
           เราจะใช้้คุณสมบัติ Path ของวัตถุ Application เข้ามาใช้งาน หากแต่ว่าทำไมเมื่อมีการนำชื่อไฟล์มาต่อท้ายเส้นทางที่ได้ จากคุณสมบัติ Path ของออบเจค App บางครั้งก็ปรากฏข้อผิดพลาด แต่บางครั้งก็ไม่ปรากฏข้อผิดพลาด ทั้งนี้ก็เพราะเนื่องจากว่า ถ้าหากเส้นทางที่ได้นั้น ไม่ใช่ไดเรคทอรี่ราก (Root) ชื่อเส้นทางที่ได้จะไม่มีเครื่องหมาย BackSlash "\" รวมอยู่ด้วย แต่ถ้าหากเป็นไดเรคทอรี่ราก ชื่อเส้นทางที่ได้จะมีเครื่องหมาย BackSlash รวมอยู่ด้วย เช่น "C:\" เป็นต้น ดังนั้นเพื่อความถูกต้อง และ ปลอดภัย เราจะอาศัยโค้ด ดังตัวอย่างด้านล่างนี้
Function FilePath(strFileName As String) As String
  If Right$(App.Path, 1) = "\" Then
    FilePath = App.Path & strFileName
  Else
    FilePath = App.Path & "\" & strFileName
  End If
End Function
หรือในกรณีที่นำไปใช้งานจริงกับการเชื่อมต่อไฟล์ฐานข้อมูล (แบบหากินจริงๆ)
Sub OpenDataBase()

Dim Conn As New ADODB.Connection

Dim RS As New ADODB.RecordSet

' หากต้องนำไปใช้ร่วมกับโปรแกรมย่อยอื่่นๆ ควรประกาศ Conn และ RS ในลักษณะของ Global น่ะขอรับ

Dim DB_File As String, SQLStmt 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 Conn = New ADODB.Connection
  Conn.ConnectionString = _
    "Provider = Microsoft.Jet.OLEDB.4.0;" & _
    "Data Source = " & DB_File & ";" & _
    "Persist Security Info = False"
  Conn.Open

  ' ตัวอย่างนำไปใช้งานกับการสร้าง RecordSet

  SQLStmt = "SELECT * FROM tblSample"
  Set RS = Conn.Execute(SQLStmt, , adCmdText)
End Sub 

การค้นหาข้อความที่มีอยู่ใน ListBox อย่างรวดเร็ว (API)

Posted by Unknown 0 comments

ตอนนี้ก็จะขอกล่าวถึง Control พื้นฐานที่ยอดนิยมอีกตัวหนึ่งใน Visual Basic นั่นก็คือ List Box โดยจะแสดงตัวอย่างในการที่ผู้ใช้งานพิมพ์ข้อความใดๆ ลงไปใน TextBox เพื่อค้นหาคำที่ตรงกันกับที่อยู่ใน ListBox หากข้อความตรงกัน ที่ Control ListBox ก็จะแสดงแถบแสงออกมาให้เห็น แต่ทางตรงกันข้าม หากไม่มีข้อความใดตรงกัน ก็จะไม่แสดงผลออกมา

แน่นอนครับว่า ในงานลักษณะแบบนี้ ก็คงหนีไม่พ้นต้องนำเอา Windows API (Application Programming Interface) ที่ถูกบรรจุเอาไว้ใน Visual Basic มาช่วยด้วยอยู่แล้ว โดยอาศัยเทคนิคของฟังค์ชั่น SendMessage (ปกติแล้ว Control หรือ Object แต่ละตัวนั้นมีการพูดคุยหรือติดต่อสื่อสารกันได้ ก็เพราะ SendMessage นี่แหละครับ) ด้วย LB_FINDSTRING (ListBox Find String - &H18F) สำหรับ ListBox เพื่อระบุตำแหน่งในส่วนที่ตรงกันกับตัวอักษรที่เราคีย์เข้าไป ดังนั้น Message ที่เราส่งไปยัง List Box มันก็คือ ค่าเลขจำนวนเต็มคงที่แบบ Global ในที่นี้ก็คือ 18F ฐานสิบหกนั่นเอง โดยที่ฟังค์ชั่น:

SendMessage(hWnd, LB_FINDSTRING, wParam, lParam)

เื่มื่อ

hWnd - กำหนด Handle Windows ให้ไปอยู่ที่ List box
wParam - ระบุตำแหน่งในการค้นหา ถ้ากำหนดให้มีค่าเป็น -1 แล้วก็จะเป็นการค้นหาำทั้งหมดที่มีอยู่ใน Control

lParam - ข้อความที่ต้องการค้นหา


เอา ล่ะครับ เรามาเริ่มต้นทำงานกันเลยดีกว่า อันดับแรกก็คือ สร้างฟอร์ม Standard EXE ขึ้นมาใหม่ 1 ฟอร์ม (ชื่อ Form1) จากนั้นให้เลือก Control ใน ToolBox มา 2 ตัว ตัวแรกก็คือ
ListBox (ชื่อ List1) และ อีกตัวก็คือ TextBox (ชื่อ Text1) แล้วนำมาวางไว้บน Form1


ต่อไปให้ประกาศโค้ดดังข้างล่างนี้
ใต้ Option Explicit หรือ ส่วนของการประกาศทั่วไป (General
Declarations) ของ Form1:








Option Explicit
Const LB_FINDSTRING = &H18F

Private Declare Function SendMessage Lib "User32" _
Alias "SendMessageA" _
(ByVal hWnd As Long, _
ByVal wMsg As Integer, _
ByVal wParam As Integer, _
lParam As Any) As Long

ส่วนของโค้ดที่จะอยู่ในฟอร์ม - Form1

Private Sub Form_Load()
List1.Clear
' เพิ่มรายการ (Item) เข้าไปไว้ใน ListBox

List1.AddItem "Apples"
List1.AddItem "Banana"
List1.AddItem "Bread"
List1.AddItem "Break"
Text1.Text = ""
End Sub

' เกิดเหตุการณ์เปลี่ยนแปลงใน TextBox

Private Sub Text1_Change()
List1.ListIndex = SendMessage(List1.hWnd, LB_FINDSTRING, -1, ByVal Text1.Text)
End Sub



ก็ จบกระบวนการแล้ว เริ่มกด F5 เพื่อรันโปรแกรมได้เลยทันที จากนั้นให้คีย์ข้อความลงไปใน TextBox จะเห็นได้ว่าหากว่าเราป้อนข้อความลงไปใน TextBox แล้วไปตรงกับข้อความใดๆ ที่แสดงอยู่ใน ListBox ก็จะเกิดแถบแสง (Focus) แสดงให้เห็นบน ListBox

เล่น Application Programming Interface (API) - SendMessage

Posted by Unknown 0 comments
การเรียกใช้งานโปรแกรม API Text Viewer
Windows API แท้จริงแล้วก็คือ แก่นของ Windows หรือ Windows API ก็เปรียบเหมือนกับ MS-DOS.SYS สำหรับระบบปฏิบัติการ (Operating System - OS) ของ MS-DOS นั่นเอง โดยที่มันจะเก็บอยู่ในรูปแบบของ Dynamics Link Libraries อยู่ในไฟล์ที่มีนามสกุล DLL ในขณะที่ Windows กำลังรันอยู่ ไฟล์เหล่านี้จะถูกโหลดขึ้นมาด้วย และคงอยู่ในหน่วยความจำอยู่อย่างนั้น แต่ละโปรแกรมย่อยใน API จะมีตัวตน (Instance) เพียงตัวเดียว ไม่ว่าจะมีกี่โปรแกรมเรียกใช้มันก็ตามที การทำงานในลักษณะนี้เรียกว่า Dynamic Linking ซึ่งแตกต่างจากการเรียกโปรแกรมย่อย ในสภาพแวดล้อมที่ไม่ใช่ Windows ข้อ ดีของการทำ Dynamic Linking ก็คือ ประหยัดทรัพยากรระบบ ซึ่งในที่นี้ก็คือ หน่วยความจำ และ ฮาร์ดดิสต์ เนื่องจากแต่ละโปรแกรม ใช้โค้ดจากโปรแกรมย่อยร่วมกัน ตามที่ได้กล่าวมาแล้ว ข้อดีอีกข้อหนึ่ง คือ มีมาตรฐานการติดต่อผู้ใช้เหมือนกัน เราจะสังเกตได้ว่า เมนูของแต่ละโปรแกรมของ Windows มีลักษณะเหมือนกัน ไดอะล็อกซ์สำหรับจัดเก็บไฟล์ หรือ เปิดไฟล์ก็มีรูปร่างเหมือนกัน ทั้งนี้ก็เพราะการเรียกใช้โปรแกรมย่อย API ชุดเดียวกันนั่นเอง
โปรแกรมที่เราพัฒนาขึ้นจาก Visual Basic ก็เรียกใช้ API เช่นเดียวกัน โดย Visual Basic ช่วยอำนวยความสะดวก ในการเรียกโปรแกรมย่อยของ API แทนด้วยภาษาที่เรียบง่ายของ Visual Basic แต่ทว่าขอบเขตของภาษา Visual Basic ไม่ได้ครอบคลุมไปถึงทุกๆความสามารถของ Windows ในบางครั้งเราอาจต้องเข้าถึงจุดที่อยู่เหนือขอบเขตของ Visual Basic โดยการเรียกใช้ API โดยตรง

การประกาศโปรแกรมย่อย API
สามารถ เขียนไว้ที่ส่วน เช่น Declaration ของโมดูล (Module) ใดโมดูลหนึ่งก็ได้ แต่โดยทั่วไปจะไว้รวมกันที่ใดที่หนึ่งในโมดูล .BAS เราอาจสร้างโมดูลขึ้นมาโมดูลหนึ่ง สำหรับจัดเก็บการประกาศฟังค์ชั่น และ ซับรูทีนของ API โดยเฉพาะก็ได้ ในการทำงานของ Windows นั้น Control หรือ ที่เรียกกันว่า Object แต่ละตัวนั้น มีการสื่อสารกันด้วยเมสเสจ (Message) เมื่อเราใช้ Method Clear กับลิสต์บ็อกซ์ จะเกิด Message "ลบรายการของตัวเองทั้งหมด" ไปให้กับ List Box ตัวนั้น เป็นต้น Microsoft Visual Basic ไม่สามารถส่ง Message เองได้ แต่สามารถใช้ฟังค์ชั่น API เพื่อส่ง Message ให้ได้โดยใช้ฟังค์ชั่น SendMessage ฟังค์ส่งข้อความนี้ จะช่วยเพิ่มเติมขีดความสามารถให้กับ Visual Basic ได้ในหลายๆด้าน

การประกาศฟังค์ชั่นของ SendMessage มีดังนี้คือ

Declare Function SendMessage Lib "User32" Alias "SendMessageA" & _
(ByVal hWnd As Long, & ByVal wMsg As Long, & _
ByVal wParam As Long, lParam As Long)
As Long


เมื่อ :

hWnd
คือ Handle ของคอนโทรลปลายทางที่เราต้องการส่ง Message ไปให้
wMsg คือ ตัวเมสเสจที่การส่ง
wParam และ lParam คือ พารามิเตอร์เสริม ซึ่งมีหน้าที่ และ ความหมายแตกต่างกันไปใน Message แต่ละชนิด

เทคนิคพื้นฐานในการเขียนโปรแกรม Visual Basic

Posted by Unknown 0 comments
แม้ว่า Visual Basic จะเป็นภาษาที่ใช้งานได้ง่ายก็ตาม และ ตัวโปรแกรม Visual Basic เองยังมีขีดความสามารถ ในการทำงานอันเพียบพร้อม ซึ่งช่วยให้เราสามารถเขียนโค้ดได้ง่ายขึ้น และ มีการตรวจสอบโค้ดได้ ในขณะเขียนโดยอัตโนมัติ แต่เราก็ควรจะทำตามกฏเกณฑ์บางอย่าง ซึ่งผมจะแนะนำให้ดังต่อไปนี้ เพื่อให้โปรแกรมเขียนออกมาทำงานได้อย่างถูกต้อง แม่นยำ และ บำรุงรักษาได้ง่าย
เทคนิคที่ 1 ใช้ Option Explicit อยู่เสมอ การใช้ Option Explicit อยู่เสมอ จะช่วยป้องกันการพิมพ์ชื่อตัวแปร หรือ ค่าคงที่ผิดพลาด อันจะช่วยในการกำจัด Bug บางตัวที่ซ่อนอยู่ในโปรแกรม และ อาจรอวันประทุ เมื่อโปรแกรมมีขนาดใหญ่ขึ้น เช่น ถ้าเราไม่ใช้ Option Explicit เราจะไม่ทราบว่า ตัวแปรใดมีการประกาศเอาไว้ หรือ มีข้อมูลเป็นแบบใด ซึ่งอาจก่อให้เกิดการแปลงข้อมูลที่ผิดพลาดในอนาคต
เทคนิคที่ 3 ใช้ฟังค์ชั่น Len เพื่อตรวจสอบว่าข้อความว่างเปล่าหรือไม่
ฟังค์ชั่น Len ทำงานได้เร็วกว่ามาก โดยเฉพาะอย่างยิ่งเมื่อทำงานในลูป
ดังตัวอย่างต่อไปนี้
Dim sTemp As String

แทนที่จะใช้

If sTemp = "" Then DoSomeThing

' Check if sTemp is empty

If sTemp <> "" Then DoSomeThing

' Check if sTemp has a value



เราควรใช้

If Len(sTemp) = 0 Then Do SomeThing

' Check if sTemp is empty

If Len(sTemp) > 0 Then DoSomeThing

' Check if sTemp has a value.

เทคนิคที่ 5 กำหนดชนิดของตัวแปรให้ชัดเจน


การกำหนดชนิดของตัวแปรให้ชัดเจน เช่น เป็นตัวแปรชนิด
Long หรือ Integer จะช่วยให้โปรแกรมทำงานเร็วขึ้น
(ก็เพราะตัวแปลภาษา - Complier ทราบถึงชนิดของตัวแปรเรียบร้อยแล้ว
ไม่จำเป็นต้องมาเสียเวลาหาอีก) และ ง่ายต่อการ Debug
เพราะเราสามารถคาดเดา ได้ว่าตัวแปรนั้น สามารถรับค่าช่วงใดได้บ้าง

Dim sMsg As String

Dim iCounter As Integer

Dim vTemp As Variant



ซึ่งเราอาจประกาศตัวแปรหลายตัวเอาไว้บนบรรทัดเดียวกัน
ดังนี้

Dim sMsg As String, iCounter As Integer, vTemp As
Variant



โดยมีข้อควรระวัง คือ ถ้าเราไม่ได้ระบุชนิดข้อมูล จะเป็นการประกาศให้เป็นชนิด
Variant ดังตัวอย่างต่อไปนี้

Dim iCounter ดังนั้นตัวแปร iCounter จะกลายเป็นชนิด
Variant โดยทันที

เทคนิคที่ 7 จำลองคีย์แท็บ เมื่อกด Enter


ปกติเมื่อเราใส่ TextBox หลายอันเข้าไปในฟอร์ม เพื่อรับข้อมูล
คงไม่เป็นการสะดวกแน่ ถ้าผู้ใช้ต้องกดคีย์แท็บ เพื่อเลื่อนไปยังฟิลด์ถัดไปทุกครั้งที่คีย์ข้อมูลเสร็จ
โค้ดต่อไปนี้จะเลื่อน Cursor ไปยังฟิลด์ถัดไป เมื่อผู้ใช้กดคีย์
Enter ซึ่งจะช่วยให้ใช้โปรแกรมได้ง่ายขึ้น



Private Sub Form_KeyPress(KeyAscii As Integer)

If KeyAscii = vbKeyReturn Then

SendKeys "{TAB}"

KeyAscii = 0

End If

End Sub


  เทคนิคที่ 2 ใช้ NOT แทน <> เมื่อต้องการตรวจสอบความไม่เท่ากัน
การใช้ฟังค์ชั่น NOT จะทำงานได้เร็วกว่า <> เป็นอย่างมาก
โดยเฉพาะอย่างยิ่ง เมื่อทำงานในลูป ดังตัวอย่างต่อไปนี้

Dim i As Integer

แทนที่จะใช้

If i <> 5000 Then DoSomeThing

เราควรใช้

If Not i = 5000 Then DoSomeThing



เทคนิคที่ 4 เมื่อประกาศออปเจกต์ อย่าใช้ Dim ... As New ...


แทนที่จะประกาศออปเจกต์เป็น Instance ตัวใหม่ เราควรประกาศตัวแปรเป็นชนิดออปเจกต์นั้น
แล้วค่อยสร้าง Instance ขึ้นมาใหม่ ทั้งนี้เพื่อให้ทำงานได้เร็วขึ้น
และ รับประกันว่าจะมีการล้างหน่วยความจำที่ใช้โดยออปเจกต์
เมื่อเราไม่ต้องการใช้มันอีกต่อไป ด้วยการกำหนดค่า Nothing
ให้ ดังตัวอย่างต่อไปนี้

แทนที่จะใช้

Dim MyConnect As New Connection

เราควรใช้

Dim MyConnect As Connection

Set MyConnect = New Connection

จากนั้นเมื่อเราใช้เสร็จแล้ว เราควรล้างหน่วยความจำ
ด้วยการกำหนดค่า Nothing ให้กับตัวแปรดังนี้

Set MyConnect = Nothing

เทคนิคที่ 6 ระมัดระวังในการใช้ฟังค์ชั่น String และ Variant ที่อาจให้ผลลัพธ์ต่างกัน


ใน Visual Basic เราจะมีฟังค์ชั่นที่ลงท้ายด้วยเครื่องหมาย Dollar Sign
"$" อยู่กลุ่มหนึ่ง คู่กับฟังค์ชั่นชื่อเดียวกันที่ไม่ได้ลงท้ายด้วย
$ เช่น

MID กับ MID$

Left กับ Left$

Date กับ Date$

ซึ่งฟังค์ชั่น Date นี้เป็นตัวอย่างที่ดี โดยฟังค์ชั่น
Date จะส่งค่าคืนกลับเป็นชนิด Variant ในรูปแบบของ mm/dd/yy
ในขณะที่ฟังค์ชั่น Date$ ส่งค่ากลับคืนเป็นชนิด String
ในรูปแบบ mm/dd/yyyy ซึ่งถ้าใช้ไม่ระมัดระวัง ความแตกต่างนี้
จะก่อให้เกิด Bug ที่ต้องใช้เวลาพอสมควรในการค้นหา



เทคนิคที่ 8 ระวังความแตกต่างของค่าคงที่ vbNullXXX VB มีค่าคงที่ ที่ใช้ระบุถึงค่า
Null หลายตัวดังนี้


vbNull
เป็นข้อมูลชนิด Long มีค่าเท่ากับ 1

vbNullChar
เป็นข้อมูลชนิด String มีค่าเท่ากับ Chr$(0) ซึ่งตรงกับข้อความว่าง
ในภาษา C และค่าที่ส่งกลับคืนมาจากฟังค์ชั่น DLL ส่วนใหญ่
อย่างไรก็ตาม vbNullChar จะไม่ใช่ข้อความว่างใน VB

vbNullString
เป็นข้อมูลชนิด String ใีค่าเท่ากับข้อความว่างใน VB



ซึ่งแต่ละตัวใช้ในสถานการณ์ต่างกันดังนี้



vbNull
ใช้เพื่อตรวจสอบผลลัพธ์ของฟังค์ชั่น VarType() ซึ่งหมายความว่า
ไม่มีข้อมูลที่ถูกต้อง

vbNullChar
ใช้แทน Chr$(0) ซึ่งปกติใช้เพื่อเรียกใช้ Procedure
ภายนอก

vbNullString
ใช้เพื่อเคลียร์ String



โดย vbNullChar มีค่าไม่เท่ากับ vbNullString ดังนั้น
vbNullChar = vbNullString จะได้ค่าเป็น False เสมอ