- [SQLSERVER] Loại bỏ Restricted User trên database MSSQL
- [C#] Hướng dẫn tạo mã QRcode Style trên winform
- [C#] Hướng dẫn sử dụng temp mail service api trên winform
- [C#] Hướng dẫn tạo mã thanh toán VietQR Pay không sử dụng API trên winform
- [C#] Hướng Dẫn Tạo Windows Service Đơn Giản Bằng Topshelf
- [C#] Chia sẻ source code đọc dữ liệu từ Google Sheet trên winform
- [C#] Chia sẻ source code tạo mã QR MOMO đa năng Winform
- [C#] Chia sẻ source code phần mềm lên lịch tự động chạy ứng dụng Scheduler Task Winform
- [Phần mềm] Tải và cài đặt phần mềm Sublime Text 4180 full version
- [C#] Hướng dẫn download file từ Minio Server Winform
- [C#] Hướng dẫn đăng nhập zalo login sử dụng API v4 trên winform
- [SOFTWARE] Phần mềm gởi tin nhắn Zalo Marketing Pro giá rẻ mềm nhất thị trường
- [C#] Việt hóa Text Button trên MessageBox Dialog Winform
- [DEVEXPRESS] Chia sẻ code các tạo report in nhiều hóa đơn trên XtraReport C#
- [POWER AUTOMATE] Hướng dẫn gởi tin nhắn zalo từ file Excel - No code
- [C#] Chia sẻ code lock và unlock user trong domain Window
- [DEVEXPRESS] Vẽ Biểu Đồ Stock Chứng Khoán - Công Cụ Thiết Yếu Cho Nhà Đầu Tư trên Winform
- [C#] Hướng dẫn bảo mật ứng dụng 2FA (Multi-factor Authentication) trên Winform
- [C#] Hướng dẫn convert HTML code sang PDF File trên NetCore 7 Winform
- [C#] Hướng dẫn viết ứng dụng chat với Gemini AI Google Winform
[MS ACCESS] Chia sẽ source code gởi và nhận tin nhắn SMS sử dụng VBA
Xin chào các bạn, bài viết hôm nay mình sẽ chia sẽ cho các bạn source code gởi và nhận tin nhắn SMS sử dụng DCom 3G.
Để gởi tin nhắn SMS, thì các bạn cần tìm hiểu qua tập lệnh AT Command.
Trong bài viết này, source code gởi và nhận tin nhắn mình viết bằng VBA.
Nay mình share cho các bạn nào đang tìm hiểu có thể phát triển thêm.
Giao diện ứng dụng Form trên Microsoft Access:
1. Đầu tiên, các bạn cần tạo module bên dưới, để kết nối access với cổng COM
Option Compare Database
Option Explicit
Global ComNum As Long 'This variable is used to store the Port number the API understand
Global ReadBytes(255) As Byte 'In this variable are stored the bytes replied from the device
'************************************************************************
'** Start of declaration of variables and Constants that the APIs need **
'************************************************************************
Type COMSTAT
fCtsHold As Long
fDsrHold As Long
fRlsdHold As Long
fXoffHold As Long
fXoffSent As Long
fEof As Long
fTxim As Long
fReserved As Long
cbInQue As Long
cbOutQue As Long
End Type
Type COMMTIMEOUTS
ReadIntervalTimeout As Long
ReadTotalTimeoutMultiplier As Long
ReadTotalTimeoutConstant As Long
WriteTotalTimeoutMultiplier As Long
WriteTotalTimeoutConstant As Long
End Type
Type DCB
DCBlength As Long
BaudRate As Long
fBinary As Long
fParity As Long
fOutxCtsFlow As Long
fOutxDsrFlow As Long
fDtrControl As Long
fDsrSensitivity As Long
fTXContinueOnXoff As Long
fOutX As Long
fInX As Long
fErrorChar As Long
fNull As Long
fRtsControl As Long
fAbortOnError As Long
fDummy2 As Long
wReserved As Integer
XonLim As Integer
XoffLim As Integer
ByteSize As Byte
Parity As Byte
StopBits As Byte
XonChar As Byte
XoffChar As Byte
ErrorChar As Byte
EofChar As Byte
EvtChar As Byte
End Type
Type OVERLAPPED
Internal As Long
InternalHigh As Long
offset As Long
OffsetHigh As Long
hEvent As Long
End Type
Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type
Public Const FILE_SHARE_READ = &H1
Public Const FILE_SHARE_WRITE = &H2
Public Const OPEN_EXISTING = 3
Public Const FILE_ATTRIBUTE_NORMAL = &H80
'**********************************************************************
'** End of declaration of variables and Constants that the APIs need **
'**********************************************************************
'*******************************************
'** Start of declaration of the APIs Used **
'*******************************************
Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Declare PtrSafe Function GetLastError Lib "kernel32" () As Long
Declare PtrSafe Function ReadFile Lib "kernel32" _
(ByVal hFile As Long, _
lpBuffer As Any, _
ByVal nNumberOfBytesToRead As Long, _
lpNumberOfBytesRead As Long, _
lpOverlapped As Long) As Long
Declare PtrSafe Function WriteFile Lib "kernel32" _
(ByVal hFile As Long, _
lpBuffer As Any, _
ByVal nNumberOfBytesToWrite As Long, _
lpNumberOfBytesWritten As Long, _
lpOverlapped As Long) As Long
Declare PtrSafe Function SetCommTimeouts Lib "kernel32" _
(ByVal hFile As Long, _
lpCommTimeouts As COMMTIMEOUTS) As Long
Declare PtrSafe Function GetCommTimeouts Lib "kernel32" _
(ByVal hFile As Long, _
lpCommTimeouts As COMMTIMEOUTS) As Long
Declare PtrSafe Function BuildCommDCB Lib "kernel32" _
Alias "BuildCommDCBA" _
(ByVal lpDef As String, _
lpDCB As DCB) As Long
Declare PtrSafe Function SetCommState Lib "kernel32" (ByVal hCommDev As Long, lpDCB As DCB) As Long
Declare PtrSafe Function CreateFile Lib "kernel32" _
Alias "CreateFileA" _
(ByVal lpFileName As String, _
ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, _
ByVal lpSecurityAttributes As Long, _
ByVal dwCreationDisposition As Long, _
ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As Long
Declare PtrSafe Function FlushFileBuffers Lib "kernel32" (ByVal hFile As Long) As Long
'I had to replicate the fowling API CreateFile because an error
'produced by the CheckPort function that I couldn't understand
Declare PtrSafe Function CreateFile1 Lib "kernel32" _
Alias "CreateFileA" _
(ByVal lpFileName As String, _
ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, _
lpSecurityAttributes As SECURITY_ATTRIBUTES, _
ByVal dwCreationDisposition As Long, _
ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As Long
'*****************************************
'** End of declaration of the APIs Used **
'*****************************************
Function Close_Port()
Close_Port = CloseHandle(ComNum)
End Function
Function FlushComm()
FlushFileBuffers (ComNum)
End Function
Function Port_Initialization(ComNumber As String, Comsettings As String) As Boolean
On Error GoTo handelinitcom
Dim ComSetup As DCB, Answer, STAT As COMSTAT, RetBytes As Long
Dim retval As Long
Dim CtimeOut As COMMTIMEOUTS, BarDCB As DCB
' Open the comport for read/write access (&HC0000000).
' Must specify existing file (3).
ComNum = CreateFile(ComNumber, &HC0000000, 0, 0&, &H3, 0, 0)
If ComNum = -1 Then
MsgBox "Com Port " & ComNumber & " not available.", 48
Port_Initialization = False
Exit Function
End If
'Setup Time Outs for comport
CtimeOut.ReadIntervalTimeout = 20
CtimeOut.ReadTotalTimeoutConstant = 1
CtimeOut.ReadTotalTimeoutMultiplier = 1
CtimeOut.WriteTotalTimeoutConstant = 10
CtimeOut.WriteTotalTimeoutMultiplier = 1
retval = SetCommTimeouts(ComNum, CtimeOut)
If retval = -1 Then
retval = GetLastError()
MsgBox "Unable to set timeouts for port " & ComNumber & " Error: " & retval
retval = CloseHandle(ComNum)
Port_Initialization = False
Exit Function
End If
retval = BuildCommDCB(Comsettings, BarDCB)
If retval = -1 Then
retval = GetLastError()
MsgBox "Unable to build Comm DCB " & Comsettings & " Error: " & retval
retval = CloseHandle(ComNum)
Port_Initialization = False
Exit Function
End If
retval = SetCommState(ComNum, BarDCB)
If retval = -1 Then
retval = GetLastError()
MsgBox "Unable to set Comm DCB " & Comsettings & " Error: " & retval
retval = CloseHandle(ComNum)
Port_Initialization = False
Exit Function
End If
Port_Initialization = True
handelinitcom:
Exit Function
End Function
Function Read_Port() As String
On Error GoTo handelpurecom
Dim RetBytes As Long, I As Integer, ReadStr As String, retval As Long
Dim CheckTotal As Integer, CheckDigitLC As Integer
retval = ReadFile(ComNum, ReadBytes(0), 255, RetBytes, 0)
ReadStr = ""
If (RetBytes > 0) Then
For I = 0 To RetBytes - 1
ReadStr = ReadStr & Chr(ReadBytes(I))
Next I
Else
FlushComm
End If
'Return the bytes replied from serial port
Read_Port = ReadStr
handelpurecom:
Exit Function
End Function
Function Write_Port(COMString As String) As Integer
On Error GoTo handelwritelpt
Dim RetBytes As Long, LenVal As Long
Dim retval As Long
If Len(COMString) > 255 Then
Write_Port Left$(COMString, 255)
Write_Port Right$(COMString, Len(COMString) - 255)
Exit Function
End If
For LenVal = 0 To Len(COMString) - 1
ReadBytes(LenVal) = Asc(Mid$(COMString, LenVal + 1, 1))
Next LenVal
ReadBytes(LenVal) = 0
retval = WriteFile(ComNum, ReadBytes(0), Len(COMString), RetBytes, ByVal CLng(0))
FlushComm
Write_Port = RetBytes
handelwritelpt:
Exit Function
End Function
Function CheckPort(Port As Long) As Boolean
Dim hPort As Long
Dim sPort As String 'In this variable is stored the port's number
Dim sa As SECURITY_ATTRIBUTES
If Val(Port) > 0 Then
sPort = "\.COM" & Port 'The port number should be something like "\.COM1"
'The API that opens the port
'If the CreateFile API succeeds then it close the port again
hPort = CreateFile1(sPort, _
0, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, _
sa, _
OPEN_EXISTING, _
FILE_ATTRIBUTE_NORMAL, 0)
If hPort Then CloseHandle hPort
CheckPort = hPort > 0
Else
CheckPort = False
End If
End Function
2. Source code cho các chức năng gởi, nhận, gọi và check money
Option Compare Database
Dim PortsFound As Integer
Dim PortConfig As String
Dim PortNumber As String
Public ONNER As Boolean
Public RECEIVE_MESSAGE As Boolean
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Function GetPorts(list As ListBox) As Long
Dim Port As Long
For Port = 1 To 100
If CheckPort(Port) Then
list.AddItem "COM" & Port & " available"
PortsFound = PortsFound + 1
End If
Next
NumOfPorts.Caption = PortsFound
End Function
Private Sub btn_ReadMessage_Click()
'Write_Port ("AT+CMGL=" & Chr(34) & "REC UNREAD" & Chr(34))
Write_Port ("ATD 0933913122;")
Write_Port (Chr$(13))
End Sub
Private Sub btn_call_Click()
Write_Port ("ATD " & txt_phone.Value & ";")
Write_Port (Chr$(13))
End Sub
Private Sub btn_ReceiveMessage_Click()
If btn_ReceiveMessage.Caption = "OPEN RECEIVE" Then
RECEIVE_MESSAGE = True
btn_ReceiveMessage.Caption = "CLOSE RECEIVE"
Else
RECEIVE_MESSAGE = False
btn_ReceiveMessage.Caption = "OPEN RECEIVE"
End If
End Sub
Private Sub CMD_checkmoney_Click()
Write_Port ("AT+CUSD=1," & Chr(34) & "*101#" & Chr(34))
Write_Port (Chr$(13))
End Sub
Private Sub CmdClose_Click()
Call Close_Port
ONNER = True
TxtCommand.SetFocus
TxtCommand.SetFocus
CmdClose.Enabled = False
CmdOpen.Enabled = True
CmdGet.Enabled = True
LstPorts.Enabled = True
cboBaubRate.Enabled = True
cboDataBits.Enabled = True
cboParity.Enabled = True
cboStopBits.Enabled = True
End Sub
Private Sub CmdGet_Click()
On Error Resume Next
For I = 1 To 20000
LstPorts.RemoveItem (I)
Next I
LstPorts.Requery
PortsFound = 0
Call GetPorts(LstPorts)
CmdOpen.Enabled = True
End Sub
Private Sub CmdOpen_Click()
PortConfig = cboBaubRate.Value & _
"," & cboParity.Value & _
"," & cboDataBits.Value & _
"," & cboStopBits.Value
If Me.LstPorts = "" Then
MsgBox "Please Select a Port first"
Exit Sub
End If
PortNumber = "\." & Mid(Me.LstPorts, 1, (Len(Me.LstPorts) - 11))
If Not Port_Initialization(PortNumber, PortConfig) Then
MsgBox PortNumber & " Not available!"
Exit Sub
End If
ONNER = True
TxtCommand.SetFocus
CmdClose.Enabled = True
CmdOpen.Enabled = False
CmdGet.Enabled = False
LstPorts.Enabled = False
cboBaubRate.Enabled = False
cboDataBits.Enabled = False
cboParity.Enabled = False
cboStopBits.Enabled = False
End Sub
Private Sub CmdSend_Click()
If Write_Port(Me.TxtCommand) <> Len(Me.TxtCommand) Then
MsgBox "Error writing to comm's"
Exit Sub
End If
Write_Port (Chr$(13))
Me.TxtCommand = ""
End Sub
Private Sub Command3_Click()
'LstPorts.Clear
PortsFound = 0
Call GetPorts(LstPorts)
CmdOpen.Enabled = True
End Sub
Private Sub ReadMessage()
Write_Port ("AT+CMGL=" & Chr(34) & "REC UNREAD" & Chr(34))
Write_Port (Chr$(13))
Dim Reply As String
Reply = Read_Port()
MsgBox Reply
End Sub
Private Sub Command31_Click()
Write_Port ("AT+CMGF=1") 'chedotext, pdu
Write_Port (Chr$(13))
Write_Port ("AT+CMGS=" & Chr(34) & txt_phone.Value & Chr(34))
Write_Port (Chr$(13))
Sleep 1000
Write_Port (txt_message.Value & Chr(26))
Write_Port (Chr$(13))
Dim Reply As String
Reply = Read_Port()
MsgBox Reply
End Sub
Private Sub Command32_Click()
txt_phone.Value = Null
txt_message.Value = Null
TxtReply.Value = Null
TxtCommand.Value = Null
End Sub
Private Sub Form_Open(Cancel As Integer)
ONNER = False
RECEIVE_MESSAGE = False
Page34.SetFocus
Call CmdClose_Click
cboBaubRate.Value = "9600"
cboDataBits.Value = "8"
cboParity.Value = "n"
cboStopBits.Value = "1"
End Sub
Private Sub Form_Timer()
If ONNER = False Then Exit Sub
If RECEIVE_MESSAGE = True Then
Write_Port ("AT+CMGL=" & Chr(34) & "REC UNREAD" & Chr(34))
Write_Port (Chr$(13))
Dim str_receive_message As String
str_receive_message = Read_Port()
If str_receive_message = "" Then Exit Sub
Dim posOf_A As Integer
posOf_A = InStr(1, str_receive_message, "UNREAD", vbTextCompare)
If posOf_A > 0 Then
Debug.Print str_receive_message
txt_receiveMessage.Value = str_receive_message & txt_receiveMessage.Value
FlushComm
End If
End If
Dim Reply As String
Reply = Read_Port()
If Reply = "" Then Exit Sub
Debug.Print Reply
TxtReply.Value = TxtReply.Value & Reply
FlushComm
End Sub
Private Sub Form_Unload(Cancel As Integer)
Call Close_Port
End Sub
HAPPY CODING