Đặt vấn đề :
Hiện nay, thông thường mỗi học sinh cắp sách tới trường sẽ được phát cho một cuốn sổ liên lạc. Nhà trường sẽ sử dụng sổ này để thông báo cho phụ huynh của học sinh biết kết quả học tập của học sinh ở sau mỗi tháng hoặc sau mỗi học kỳ. Trong sổ liên lạc, nhà trường thường chỉ ghi kết quả cuối cùng của mỗi tháng hoặc mỗi học kỳ. Do vậy phụ huynh không thể biết được chi tiết các cột điểm của các môn học trong mỗi tháng. Ngoài ra, những lần nghỉ học cũng như những lần vi phạm nội quy của học sinh sẽ không được ghi vào trong ấy. Vì thế các bậc phụ huynh khó có thể theo dõi chặt chẽ những diễn biến học tập của con mình ở trường như thế nào.
Công việc giáo dục học sinh cần phải có sự phối hợp giữa gia đình và nhà trường. Nhằm tạo sự thuận lợi cho các bậc phụ huynh có thể nắm bắt được những thông tin về học sinh một cách nhanh chóng, đầy đủ, ở đề tài tốt nghiệp này, em đã tìm hiểu và viết một chương trình tự động thông báo kết quả học tập của học sinh qua điện thoại. Em nhận thấy có 3 vấn đề chính sau đây được đặt ra cần giải quyết là :
· Nhận được tín hiệu gọi tới từ điện thoại , tạo một kết nối giữa máy tính và cuộc gọi đó và nhận biết phím nào đã được bấm từ máy điện thoại của người gọi để thực hiện yêu cầu của người đó
· Tìm kết quả trong cơ sở dữ liệu
· Thông báo bằng giọng nói cho người gọi nghe
Vấn đề đầu tiên là phải tạo được một giao tiếp giữa điện thoại và máy tính thông qua một modem. Và để truyền được tín hiệu tiếng nói từ máy tính đến điện thoại, modem này phải có hỗ trợ chức năng “voice“. Máy tính lúc này sẽ đồng thời đóng vai trò của máy điện thoại và nhân viên trường học. Người gọi có thể sử dụng bất kỳ điện thoại nào để gọi tới. Lúc này máy tính sẽ tự động “nhấc máy” và đối thoại với người gọi.
Vấn đề thứ hai được giải quyết bằng cách sử dụng các câu lệnh truy vấn (SQL) mà bất kỳ thao tác nào với cơ sở dữ liệu cũng cần phải có.
Vấn đề cuối cùng là áp dụng công nghệ “text-to-speech” để chuyển từ chữ trong máy tính sang tiếng nói, sau đó sẽ truyền đi qua điện thoại tới người gọi.
Tất cả những vấn đề này sẽ được trình bày chi tiết trong các phần sau
LỜI NÓI ĐẦU
Trong mỗi gia đình, các bậc cha mẹ có con cắp sách tới trường lúc nào cũng quan tâm đến việc học của con mình. Chẳng hạn bữa nay con mình có lên trả bài hay không? Các bài kiểm tra trong tháng được bao nhiêu điểm? Kết quả thi ở cuối mỗi học kỳ ra sao? Và kể cả việc muốn biết con mình có nghỉ học bữa nào không hoặc có vi phạm nội quy gì ở trường hay không và lý do tại sao? Thông thường, gia đình chỉ biết những chuyện này sau khi nhà trường phát sổ liên lạc về nhà.
Ngày nay, với sự phát triển liên tục của ngành máy tính, ta có thể tự động hóa công việc này bằng cách kết nối máy tính với điện thoại như là một hệ thống trả lời tự động. Khi một phụ huynh gọi điện thoại tới số máy này, hệ thống sẽ thông báo các kết quả học tập của học sinh. Điều này thật là thuận lợi, nhanh chóng và dễ dàng, có thể thực hiện ở mọi lúc mọi nơi.
Tuy đề tài này đã được hoàn thành nhưng chắc chắn không tránh khỏi thiếu sót. Em rất mong được sự quan tâm, giúp đỡ và góp ý của các thầy, cô và các bạn.
114 trang |
Chia sẻ: lvcdongnoi | Lượt xem: 2440 | Lượt tải: 1
Bạn đang xem trước 20 trang tài liệu Thông báo kết quả học tập của học sinh qua điện thoại, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
c sinh ngay khi hệ thống đang hoạt động
Cho phép thu lại tiếng nói của người dùng
Hạn chế :
Vì chương trình sử dụng giao tiếp là modem nên tại một thời điểm, hệ thống chỉ tiếp nhận được một cuộc gọi. Tuy nhiên, hệ thống chỉ hoạt động trong một trường học nên điều này có thể chấp nhận được.
Cơ sở dữ liệu được cài đặt bằng Access nên chưa được mã hóa để bảo mật
Vì thời gian có hạn nên tiếng nói thu vào chưa được lọc để đạt chất lượng cao hơn
Bảng chỉ mục chưa được tối ưu
Hướng phát triển :
Hỗ trợ telephony card nhằm kết nối với nhiều cuộc gọi tới ở cùng thời điểm.
Mã hóa cơ sở dữ liệu Access hoặc thay thế bằng hệ quản trị cơ sở dữ liệu khác như Oracle, SQL Server, ... để tăng cường khả năng bào mật
Mở rộng chương trình cập nhật dữ liệu ở dạng bảng (lưới) nhằm cho phép thấy nhiều mẫu tin cùng lúc
Thêm một số chức năng cho chương trình thu âm để người dùng linh động hơn trong việc thu tiếng nói như : giảm độ ồn, chỉnh sửa trực tiếp sóng âm thanh ở dạng đồ họa, ...
Tạo lại bảng chỉ mục để tìm kiếm nhanh hơn
PHẦN 5 KẾT LUẬN
Chương trình “Thông báo kết quả học tập của học sinh qua điện thoại” đã được hoàn thiện, có thể cài đặt để chạy trên bất kỳ hệ điều hành Windows 32-bit nào. Với những yêu cầu đặt ra của đề tài, chương trình đã giải quyết được và cho ra kết quả như mong muốn. Chương trình này có thể ứng dụng cho các trường học phổ thông.
Đề tài “Thông báo kết quả học tập của học sinh qua điện thoại” là một đề tài rất hay và thiết thực. Trong quá trình nghiên cứu, tìm hiểu, em đã có dịp ôn lại rất nhiều kiến thức đã học như : phân tích thiết kế hệ thống thông tin quản lý, cài đặt, kết nối và truy xuất cơ sở dữ liệu, tạo và xử lý file âm thanh và các kỹ thuật lập trình trong Visual Basic. Song song đó, em cũng được biết thêm nhiều điều mới như các kiến thức liên quan đến lập trình giao tiếp giữa điện thoại và máy tính (TAPI), lập trình giao tiếp với multimedia. Từ những kiến thức thu thập được , em đã hiểu được phần nào về hoạt động của các hộp thư thoại ( voice mail) và các hệ thống trả lời tự động (answering machine) mà hiện nay được sử dụng rất nhiều.
Tuy đề tài đã được khép lại nhưng vẫn còn nhiều vấn đề cần được nghiên cứu và phát triển thêm nhằm mở rộng chương trình như : sử dụng telephony card để trả lời nhiều cuộc gọi ở cùng thời điểm, mở rộng cơ sở dữ liệu và tăng cường chức năng bảo mật, xử lý nhiều hơn tiếng nói được thu vào nhằm cho chất lượng cao hơn, vv... Đó là những mục tiêu phát triển mà bất cứ một chương trình nào cũng có.
PHỤ LỤCMÃ NGUỒNTHỰC HIỆNMỘT SỐCÔNG VIỆC CHÍNH
1. CHƯƠNG TRÌNH CHÍNH
Mở cơ sở dữ liệu :
'Mo CSDL san sang cho viec tra loi
'Tra ve True neu mo thanh cong
Private Function Open_Database() As Boolean
'Load database
If File_Exist(SourcePath + "KQHT.mdb") Then
Set DB = OpenDatabase(SourcePath + DBName)
Set VRS = DB.OpenRecordset("tblVOICEINDEX", dbOpenTable)
VRS.Index = "idxChuoi"
Open_Database = True
Else
Open_Database = False
End If
End Function
Đóng cơ sở dữ liệu :
Private Sub Close_Database()
VRS.Close
DB.Close
End Sub
Khởi tạo TAPI :
'Khoi tao TAPI
'Tra ve False neu co loi
Private Function Init_TAPI() As Boolean
Dim Loi As Long
Loi = lineInitialize(hTAPI, App.hInstance, AddressOf LineCallBack, App.EXEName, TotalLines)
If Loi < 0 Then
MsgBox "Không thể khởi tạo thư viện TAPI !", vbCritical, Title
Init_TAPI = False
Else
Init_TAPI = True
End If
End Function
Chờ cuộc gọi tới :
'Cho doi 1 cuoc goi toi
'Tra ve thong bao loi neu co
Public Function Wait_Call() As String
Dim Loi As Long
Wait_Call = vbNullString
'Mo Line
If Not Open_Line() Then
Wait_Call = "Không thể dùng modem được chọn !"
Exit Function
End If
'Dang ky cac Message cho Line
Loi = lineSetStatusMessages(hLine, ALL_TAPIMESSAGES, 0)
If Loi < 0 Then
Wait_Call = "Không thể tạo sự kiện để nhận cuộc gọi !"
Call Close_Line
Exit Function
End If
frmKQHT.imgStatus.Picture = LoadResPicture("System_On", vbResBitmap)
'Function lineCallBack se duoc goi khi chuong reo
End Function
Mở line hiện tại :
'Mo Line hien tai voi CurLineID
‘Tra ve True neu thanh cong
Private Function Open_Line() As Boolean
Dim Loi As Long
Dim NegoVersion As Long 'Version lay duoc sau khi Negotiate
Dim plineExtenID As lineExtensionID
Call lineNegotiateAPIVersion(hTAPI, CurLineID, LOW_TAPIVERSION, HIGH_TAPIVERSION, NegoVersion, plineExtenID)
If lineOpen(hTAPI, CurLineID, hLine, NegoVersion, Unused, _
Unused, LINECALLPRIVILEGE_OWNER, _
LINEMEDIAMODE_AUTOMATEDVOICE, Unused) < 0 Then 'Error
Open_Line = False
Else
Open_Line = True
End If
End Function
Ngắt kết nối của cuộc gọi hiên tại :
'Ngat ket noi cuoc goi hien tai
Public Sub Disconnect()
If Playing Then
Call Stop_Playing
Call Wait
End If
Call Drop_Call
Call Close_Line
' Dong file wave sau khi doc xong du lieu file wave
If Not frmKQHT.mnuRecord.Checked Then Call Close_VoiceFiles
frmKQHT.mnuRecord.Enabled = True
'Neu KHONG phai do nhan nut STOP de disconnect thi
'tao Line moi de nhan cuoc goi khac
If frmKQHT.cmdStop.Tag "clicked" Then Call Wait_Call
End Sub
Hủy và giải phóng cuộc gọi hiện tại :
'Huy bo cuoc goi hien tai
Private Sub Drop_Call()
If hCall 0 Then
Call lineDrop(hCall, "", 0)
Call lineDeallocateCall(hCall)
hCall = 0
End If
End Sub
Đóng line hiện tại :
'Dong Line hien tai
Private Sub Close_Line()
If hLine 0 Then
Call lineClose(hLine)
hLine = 0
End If
End Sub
Kết thúc TAPI :
Private Sub ShutDown_TAPI()
Call lineShutdown(hTAPI)
End Sub
Tiếp nhận các sự kiện của TAPI :
'Xu ly cac su kien TAPI
Public Function LineCallBack(ByVal dwDevice As Long, ByVal dwMsg As Long, ByVal dwCallbackInstance As Long, ByVal dwParam1 As Long, ByVal dwParam2 As Long, ByVal dwParam3 As Long) As Long
On Error GoTo Thoat
Select Case dwMsg
Case LINE_LINEDEVSTATE 'Thong diep cho trang thai cua LINE
Call LineDevStateProc(dwDevice, dwCallbackInstance, dwParam1, dwParam2, dwParam3)
Case LINE_CALLSTATE 'Thong diep cho trang thai cua CALL
Call LineCallStateProc(dwDevice, dwCallbackInstance, dwParam1, dwParam2, dwParam3)
Case LINE_MONITORDIGITS 'Thong diep cho tin hieu DTMF gui toi
Call Receive_DTMF(dwParam1)
End Select
Exit Function
Thoat:
Call Disconnect
End Function
Tiếp nhận các sự kiện liên quan đến cuộc gọi (call) :
'Xu ly cac su kien trang thai cua CALL
'hCall = dwDevice
'hCallback = hCallbackInstance
'CallState = dwParam1
Private Sub LineCallStateProc(ByVal dwDevice As Long, ByVal hCallbackInstance As Long, ByVal dwParam1 As Long, ByVal dwParam2 As Long, ByVal dwParam3 As Long)
Select Case dwParam1
Case LINECALLSTATE_OFFERING: 'Tin hieu co cuoc goi toi
hCall = dwDevice
Case LINECALLSTATE_CONNECTED:
Call After_Connected
Case LINECALLSTATE_DISCONNECTED: 'Xay ra khi cuoc goi bi ngat
Call Disconnect
Case LINECALLSTATE_IDLE
Call Disconnect
End Select
End Sub
Tiếp nhận các sự kiện liên quan đến line :
'Xu ly cac su lien trang thai cua LINE
'hLine = dwDevice
'hCallback = hCallbackInstance
'DeviceState = dwParam1
Private Sub LineDevStateProc(ByVal dwDevice As Long, ByVal hCallbackInstance As Long, ByVal dwParam1 As Long, ByVal dwParam2 As Long, ByVal dwParam3 As Long)
Select Case dwParam1
Case LINEDEVSTATE_RINGING: 'Chuong reo --> So chuong = dwParam3
frmKQHT.imgStatus.Picture = LoadResPicture("System_Ring", vbResBitmap)
If dwParam3 >= Rings Then Call Answer_Call
End Select
End Sub
Kết nối với cuộc gọi tới :
'Tra loi cuoc goi toi
Private Sub Answer_Call()
Dim Loi As Long
Loi = lineAnswer(hCall, "", 0)
If Loi < 0 Then
Call Disconnect
End If
End Sub
Sau khi kết nối thành công :
‘Sau khi ket noi, mo file voice va phat loi chao
Private Sub After_Connected()
If Not frmKQHT.mnuRecord.Checked Then 'Neu KHONG dang chay ctr Record
frmKQHT.mnuRecord.Enabled = False
If Open_VoiceFiles() = True Then
frmKQHT.imgStatus.Picture = LoadResPicture("System_Hangup", vbResBitmap)
PhutHT = 0
frmKQHT.timCall.Enabled = True
Call Welcome
Else
frmKQHT.cmdStop = True
MsgBox "Không thể mở các file *.sam", vbSystemModal + vbCritical, Title
End If
Else 'Dang cap nhat tieng noi, thong bao busy
frmKQHT.imgStatus.Picture = LoadResPicture("System_Hangup", vbResBitmap)
If Load_WaitFile() = True Then Call Start_Playing(1000)
End If
End Sub
Mở các file *.sam :
'Mo cac file Voice de doc du lieu
‘Tra ve True neu thanh cong
Public Function Open_VoiceFiles() As Boolean
Dim pmmIOInfo As mmIOInfo
Dim c As Byte
Dim Handle As Long
Open_VoiceFiles = False
For c = Asc("@") To Asc("Z")
If Dir(SourcePath + Chr(c) + ".sam") = vbNullString Then Exit Function
Handle = mmioOpen(SourcePath + Chr(c) + ".sam", pmmIOInfo, MMIO_READ)
If Handle 0 Then hVoiceFile(c - 63) = Handle Else Exit Function
Next
Open_VoiceFiles = True
End Function
Nạp dữ liệu tiếng nói vào bộ nhớ :
'Load data from file into mem
Public Function Load_VoiceFiles(Chuoi As String) As Boolean
Dim Loi As Long, OldDataSize As Long, TotalDataSize As Long
Dim arrChuoi() As ChuoiVoice 'Mang cac chuoi con va nhung thong tin cua chung
Dim arrChuoiCon() As String 'Mang chuoi con, chi co ten chuoi
Dim TenChuoi As String
Dim i As Long, LastIndex As Long
Dim Found As Boolean 'Bao hieu co tim thay 1 chuoi nao trong CSDL khong ?
'Tach chuoi me thanh cac chuoi con
arrChuoiCon = Split(Chuoi, Cach, , vbTextCompare)
Found = False
Load_VoiceFiles = False
LastIndex = UBound(arrChuoiCon)
ReDim arrChuoi(LastIndex)
TotalDataSize = 0
'Tim thong tin chuoi trong CSDL
For i = LBound(arrChuoiCon) To LastIndex
VRS.Seek "=", arrChuoiCon(i)
If VRS.NoMatch = False Then 'Found
arrChuoi(i).hVoiceFile = hVoiceFile(Asc(UCase(VRS!Nhom)) - 63)
arrChuoi(i).FileOffset = VRS!FileOffset
arrChuoi(i).DataSize = VRS!DataSize
TotalDataSize = TotalDataSize + VRS!DataSize
Found = True 'Chi can co 1 voice
End If
Next i
'Neu khong co voice nao thi thoat
If Not Found Then Exit Function
'Cap phat bo nho
hMem = GlobalAlloc(GMEM_ZEROINIT, TotalDataSize)
pWaveBuffer = GlobalLock(hMem)
TotalSamples = TotalDataSize
'Doc du lieu
OldDataSize = 0
For i = LBound(arrChuoiCon) To LastIndex
If (arrChuoi(i).hVoiceFile 0) Then 'Co tu nay
Call mmioSeek(arrChuoi(i).hVoiceFile, arrChuoi(i).FileOffset, SEEK_SET)
Loi = mmioRead(arrChuoi(i).hVoiceFile, pWaveBuffer + OldDataSize, arrChuoi(i).DataSize)
If (Loi = -1) Then
hMem = GlobalFree(hMem)
Exit Function
End If
OldDataSize = OldDataSize + arrChuoi(i).DataSize 'Tong so byte da doc vao mem
End If
Next
Load_VoiceFiles = True
Thoat:
End Function
Phát tiếng nói :
'Bat dau phat voice da co trong mem
Public Sub Start_Playing(LoopCount As Long)
Dim OpenFlag As Long
Dim Loi As Long
Dim ErrMsg As String * 200
'Thiet lap flag de mo waveout device
If WaveOutID = -1 Then 'Neu ra sound card
OpenFlag = CALLBACK_FUNCTION
Else
OpenFlag = CALLBACK_FUNCTION Or WAVE_MAPPED
End If
'Set format
With pWaveFormat
.cbSize = 0
.nAvgBytesPerSec = 11025
.nBlockAlign = 1
.nChannels = 1
.nSamplesPerSec = 11025
.wBitsPerSample = 8
.wFormatTag = 1
End With
Loi = waveOutOpen(hWaveOut, WaveOutID, pWaveFormat, AddressOf waveOutProc, 0, OpenFlag)
If Loi 0 Then
hMem = GlobalFree(hMem)
Exit Sub
End If
'Chuan bi du lieu am thanh de phat ra
pWaveHeader.lpData = pWaveBuffer
pWaveHeader.dwBufferLength = TotalSamples * pWaveFormat.nBlockAlign
pWaveHeader.dwFlags = 0
pWaveHeader.dwLoops = LoopCount - 1 'So lan lap lai , dem lui
Loi = waveOutPrepareHeader(hWaveOut, pWaveHeader, Len(pWaveHeader))
If Loi 0 Then
Call Close_WaveOut
hMem = GlobalFree(hMem)
Exit Sub
End If
'Bat dau phat am thanh
Loi = waveOutWrite(hWaveOut, pWaveHeader, Len(pWaveHeader))
If Loi 0 Then
Call Close_WaveOut
hMem = GlobalFree(hMem)
Else
Playing = True
End If
'Sub waveOutProc se duoc goi khi phat xong
End Sub
Ngừng phát tiếng nói :
Public Sub Stop_Playing()
pWaveHeader.dwLoops = 0
Call waveOutReset(hWaveOut)
'Sub waveOutProc se duoc goi de tiep tuc
End Sub
Tiếp nhận các sự kiện của thiết bị phát âm thanh :
'Xu ly su kien cua WaveOut
Private Sub waveOutProc(ByVal hwo As Long, ByVal uMsg As Long, ByVal dwInstance As Long, ByRef hdr As WAVEHDR, ByVal dwParam2 As Long)
On Error Resume Next
If uMsg = MM_WOM_DONE Then
frmKQHT.timWaveOut.Enabled = True
End If
End Sub
Lấy ID của thiết bị phát âm thanh :
'Lay ID cua thiet bi de phat am thanh
Public Function Get_WaveOutID(DeviceClass As String) As Boolean
Dim Loi As Long
Dim pVarString As varString
pVarString.dwTotalSize = Len(pVarString)
Loi = lineGetID(hLine, 0, hCall, LINECALLSELECT_CALL, pVarString, DeviceClass)
If Loi < 0 Then
Get_WaveOutID = False
Else
If pVarString.dwStringOffset = 0 Then 'Nothing
Get_WaveOutID = False
Exit Function
Else
'Lay ID
WaveOutID = pVarString.dwData
Get_WaveOutID = True
End If
End If
End Function
Nhận mã DTMF :
'Nhan cac ma DTMF tu lineCallBack
Public Sub Receive_DTMF(Phim As Long)
PhutHT = 0 'Reset thoi gian roi
If Playing Then Call Stop_Playing
'Dinh nghia lai ma phim
Select Case Phim
Case &H30 To &H39: Phim = Phim And &HF
Case &H2A:
Phim = Phim_SAO '*
If (Status STATUS_MaHS) Then
Goto_Menu
Exit Sub
End If
Case &H23: Phim = Phim_# '#
End Select
'Cac thao tac khac
Select Case Status
Case STATUS_MaHS 'Neu dang nhan ma so
Call Receive_MaHS(Phim)
Case STATUS_NGHIHOC
Call Receive_Thang(Phim)
Case STATUS_VIPHAM
Call Receive_Thang(Phim)
Case STATUS_KQKIEMTRA
Call Receive_Thang(Phim)
Case STATUS_KQTHI
Call Receive_HocKy(Phim)
Case STATUS_KQTHANG
Call Receive_Thang(Phim)
Case STATUS_KQHOCKY
Call Receive_HocKy(Phim)
Case STATUS_KQNAMHOC
Case STATUS_HOCSINH
Case STATUS_NAMHOC
Call Receive_NamHoc(Phim)
Case STATUS_MENU
Call Menu(Phim)
End Select
End Sub
Menu với các phím bấm tương ứng :
Private Sub Menu(Phim As Long)
Select Case Phim
Case Phim_# ''#: Nhap ma so khac
Call Nhap_MaHS
Case 1
Status = STATUS_NGHIHOC
Call Nhap_Thang(Status)
Case 2
Status = STATUS_VIPHAM
Call Nhap_Thang(Status)
Case 3
Status = STATUS_KQKIEMTRA
Call Nhap_Thang(Status)
Case 4
Status = STATUS_KQTHI
Call Nhap_HocKy(Status)
Case 5
Status = STATUS_KQTHANG
Call Nhap_Thang(Status)
Case 6
Status = STATUS_KQHOCKY
Call Nhap_HocKy(Status)
Case 7
Status = STATUS_KQNAMHOC
Call Monitor_DTMF(False)
Call Get_KQNamHoc
Case 8
Status = STATUS_HOCSINH
Call Monitor_DTMF(False)
Call Get_Info_HS
Case 9
Status = STATUS_NAMHOC
Call Nhap_NamHoc
Case Phim_SAO ' *: Thoat
Call Play_Voice1("@tạm_biệt")
Call Wait
Call Disconnect
End Select
End Sub
Nhận mã số học sinh :
'Nhan ma so hoc sinh
Private Sub Receive_MaHS(Phim As Long)
Dim Chuoi As String
Select Case Phim
Case 0 To 9
DTMFBuffer = DTMFBuffer & Phim
If Len(DTMFBuffer) = 7 Then 'Neu ma so da du 7 ky tu
Call Monitor_DTMF(False)
If Check_MaHS() = True Then ' tim thay hoc sinh
MaHS = DTMFBuffer
Chuoi = "@đã_nhập_mã_số " + Convert_MaHS2VoiceString(MaHS)
Call Play_Voice1(Chuoi)
Call Wait
Call Goto_Menu
Else 'khong co hoc sinh
Chuoi = "@không_có_mã_số " + Convert_MaHS2VoiceString(DTMFBuffer)
Call Play_Voice1(Chuoi)
Call Wait
Call Nhap_MaHS
End If
End If
Case Phim_# '# 'Nhap lai
Call Nhap_MaHS
Case Phim_SAO '*
If MaHS = vbNullString Then
Call Play_Voice1("@chưa_nhập_mã_số")
Call Wait
Call Nhap_MaHS
Else
Call Goto_Menu
End If
End Select
End Sub
Nhận năm học :
'Nhan nam hoc mac dinh cho phien lam viec
Private Sub Receive_NamHoc(Phim As Long)
Select Case Phim
Case 0 To 9
DTMFBuffer = DTMFBuffer & Phim
If Len(DTMFBuffer) = 4 Then 'Neu year da du 4 chu so
Call Monitor_DTMF(False)
TenNamHoc = Check_NamHoc(DTMFBuffer) 'Ktra co nam hoc nay chua ? MaNH = DTMFBuffer
If DTMFBuffer vbNullString Then 'Neu tim thay co nam hoc nay
MaNH = DTMFBuffer 'Thiet lap MaNH mac dinh
TenNH(0) = CInt(Left(TenNamHoc, 4))
TenNH(1) = CInt(Right(TenNamHoc, 4))
Chuoi = "@ñaõ_choïn_naêm_hoïc " & Split_Number(TenNH(0)) & Cach _
& Split_Number(TenNH(1))
Call Play_Voice1(Chuoi)
Call Wait
Call Goto_Menu
Else
If TenNamHoc = "error" Then 'Neu nam hoc khong hop le
DTMFBuffer = vbNullString
Chuoi = "@lỗi_năm_học"
Else 'Neu chua co nam hoc nay
Chuoi = "@chưa_có_năm_học " & Split_Number(CInt(TenNamHoc)) _
& Cach & Split_Number(CInt(TenNamHoc) + 1)
End If 'TenNamHoc
Call Play_Voice1(Chuoi)
Call Wait
Call Nhap_NamHoc
End If 'DTMFBuffer
End If 'len(DTMFBuffer)
End Select
End Sub
Nhận tháng :
'Nhan ten thang
Private Sub Receive_Thang(Phim As Long)
Dim Thang As Byte
Select Case Phim
Case 0 To 9
DTMFBuffer = DTMFBuffer & Phim
If Len(DTMFBuffer) = 2 Then
Call Monitor_DTMF(False)
Thang = CByte(DTMFBuffer)
If ((Thang >= 1) And (Thang = 9) And (Thang <= 12)) Then
Select Case Status
Case STATUS_KQTHANG: Call Get_KQThang(Thang)
Case STATUS_KQKIEMTRA: Call Get_KQKiemTra(Thang)
Case STATUS_NGHIHOC: Call Get_NghiHoc(Thang)
Case STATUS_VIPHAM: Call Get_ViPham(Thang)
End Select
Else
Call Play_Voice1("@lỗi_tháng")
Call Wait
Call Nhap_Thang(Status)
End If
End If
End Select
End Sub
Nhận học kỳ :
'Nhan ten hoc ky
Private Sub Receive_HocKy(Phim As Long)
'Chi co the la hoc ky 1 hoac 2
Call Monitor_DTMF(False)
Select Case Phim
Case 1, 2
If Status = STATUS_KQHOCKY Then
Call Get_KQHocKy(Phim)
Else 'Status =STATUS_KQTHI
Call Get_KQThi(Phim)
End If
Case Else
Call Play_Voice1("@lỗi_học_kỳ")
Call Wait
Call Nhap_HocKy(Status)
End Select
End Sub
Giám sát để thu nhận các mã DTMF :
'Giam sat cac ma DTMF
'dwDigitModes = 0 --> Ngung giam sat
'On=True: giam sat - Off=False: ngung giam sat
Public Sub Monitor_DTMF(OnOff As Boolean)
Dim Loi As Long
Dim DigitModes As Long
If OnOff = True Then DigitModes = LINEDIGITMODE_DTMF Else DigitModes = 0
Loi = lineMonitorDigits(hCall, DigitModes)
If Loi < 0 Then 'Co the cuoc goi bi ngat
Call Disconnect
End If
End Sub
Lấy thông tin về các lần nghỉ học :
'thong bao thong tin ve NGHI HOC
Public Sub Get_NghiHoc(ByVal Thang As Byte)
Dim RS As Recordset, RS1 As Recordset
Dim SQL As String, GiayPhep As String
Dim Chuoi As String
Dim NgayNH As String
Dim DauThang As String, CuoiThang$
If (Thang >= 9) Then
DauThang = "#" & Thang & "/1/" & TenNH(0) & "#"
If Thang < 12 Then
CuoiThang = "#" & Thang + 1 & "/1/" & TenNH(0) & "#"
Else
CuoiThang = "#1/1/" & TenNH(1) & "#"
End If
Else
DauThang = "#" & Thang & "/1/" & TenNH(1) & "#"
CuoiThang = "#" & Thang + 1 & "/1/" & TenNH(1) & "#"
End If
'Loc theo ma HS
SQL = "SELECT tblLYDO.TenLD, tblNGHIHOC.SoNgayNH, " _
+ " tblNGHIHOC.GiayPhep, tblNGHIHOC.NgayNH " _
+ " FROM tblLYDO INNER JOIN tblNGHIHOC " _
+ " ON tblLYDO.MaLD = tblNGHIHOC.MaLD " _
+ " WHERE (tblNGHIHOC.MaHS = '" + MaHS + "')"
Set RS = DB.OpenRecordset(SQL, dbOpenDynaset, dbReadOnly)
'Loc theo ngay nghi hoc
SQL = "(tblNGHIHOC.NgayNH >= " + DauThang + ")" _
+ " AND (tblNGHIHOC.NgayNH <= " + CuoiThang + ")"
RS.Filter = SQL
Set RS1 = RS.OpenRecordset
RS.Close
'Sort
RS1.Sort = "tblNGHIHOC.NgayNH "
Set RS = RS1.OpenRecordset
RS1.Close
If RS.EOF Then 'Neu khong co nghi hoc vao ngay nay
'@không_có_nghỉ_học = @không_có_nghỉ_học_trong_tháng
Chuoi = "@học_sinh" + Im200 + HoTenHS + Im400 + "@không_có_nghỉ_học " _
& Thang & Im400 + "@năm_học" + Im200 & TenNH(0) _
& Im400 & TenNH(1)
Else
'@các_lần_nghỉ_học = @các_lần_nghỉ_học_trong_tháng
Chuoi = "@các_lần_nghỉ_học " & Thang & Im200 + "@của_học_sinh" _
+ Im200 + HoTenHS
Do While Not RS.EOF
NgayNH = CStr(RS!NgayNH)
If RS!GiayPhep = True Then GiayPhep = "@có_phép" Else GiayPhep = "@không_phép"
Chuoi = Chuoi + Im800 + "ngày" + Im200 & Day(NgayNH) _
& " tháng " & Month(NgayNH) & Im200 + "năm" _
+ Im200 & Year(NgayNH) & Im400 + "@số_ngày_nghỉ" _
+ Im200 & RS!SoNgayNH & Im200 & "ngày" _
+ Im400 + GiayPhep + Im400 + "@lý_do" + Im200 + RS!TenLD
RS.MoveNext
Loop
End If
Chuoi = Chuoi + " @về_menu"
RS.Close
Call Monitor_DTMF(True)
Call Play_Voice(Chuoi)
End Sub
Lấy thông tin về các lần vi phạm nội quy :
'thong bao ve loi vi pham
Public Sub Get_ViPham(ByVal Thang As Byte)
Dim RS As Recordset, RS1 As Recordset
Dim SQL As String
Dim Chuoi As String
Dim NgayVP As String
Dim DauThang As String, CuoiThang$
'Tim gioi han dau va cuoi cua thang
If (Thang >= 9) Then
DauThang = "#" & Thang & "/1/" & TenNH(0) & "#"
If Thang < 12 Then
CuoiThang = "#" & Thang + 1 & "/1/" & TenNH(0) & "#"
Else
CuoiThang = "#1/1/" & TenNH(1) & "#"
End If
Else
DauThang = "#" & Thang & "/1/" & TenNH(1) & "#"
CuoiThang = "#" & Thang + 1 & "/1/" & TenNH(1) & "#"
End If
SQL = "SELECT tblLOI.TenLoi, tblVIPHAM.LanVP, " _
+ " tblVIPHAM.NgayVP " _
+ " FROM tblVIPHAM INNER JOIN tblLOI " _
+ " ON tblLOI.MaLoi = tblVIPHAM.MaLoi " _
+ " WHERE (tblVIPHAM.MaHS = '" + MaHS + "')"
Set RS = DB.OpenRecordset(SQL, dbOpenDynaset, dbReadOnly)
'Loc theo ngay vi pham
SQL = "(tblVIPHAM.NgayVP >= " + DauThang + ")" _
+ " AND (tblVIPHAM.NgayVP <= " + CuoiThang + ")"
RS.Filter = SQL
Set RS1 = RS.OpenRecordset
RS.Close
'Sort
RS1.Sort = " tblVIPHAM.NgayVP , tblVIPHAM.LanVP "
Set RS = RS1.OpenRecordset
RS1.Close
If RS.EOF Then 'Neu khong co vi pham vao ngay nay
'@không_có_vi_phạm = @không_có_vi_phạm_trong_tháng
Chuoi = "@học_sinh" + Im200 + HoTenHS + Im400 + "@không_có_vi_phạm " _
& Thang & Im400 + "@năm_học" + Im200 & TenNH(0) _
& Im400 & TenNH(1)
Else
'@các_lần_vi_phạm = @các_lần_vi_phạm_trong_tháng
Chuoi = "@các_lần_vi_phạm " & Thang & Im200 + "@của_học_sinh" _
+ Im200 + HoTenHS
Do While Not RS.EOF
NgayVP = CStr(RS!NgayVP)
Chuoi = Chuoi + Im800 + "ngày " & Day(NgayVP) _
& " tháng " & Month(NgayVP) & Im200 + "năm " _
& Year(NgayVP) & Im400 + "@lỗi_vi_phạm" _
+ Im200 + RS!TenLoi
RS.MoveNext
Loop
End If
Chuoi = Chuoi + " @về_menu"
RS.Close
Call Monitor_DTMF(True)
Call Play_Voice(Chuoi)
End Sub
Lấy kết quả cuối năm học :
Public Sub Get_KQNamHoc()
Dim RS As Recordset, RS1 As Recordset
Dim SQL As String, GiayPhep As String, Chuoi As String
SQL = "SELECT tblKQNAMHOC.DTBNH, tblKQNAMHOC.HangNH," _
& " tblHOCLUC.TenHL, tblHANHKIEM.TenHK, tblKQNAMHOC.MaNH " _
& " FROM tblHANHKIEM " _
& " INNER JOIN (tblHOCLUC " _
& " INNER JOIN tblKQNAMHOC " _
& " ON tblHOCLUC.MaHL = tblKQNAMHOC.MaHL)" _
& " ON tblHANHKIEM.MaHK=tblKQNAMHOC.MaHK" _
& " WHERE (tblKQNAMHOC.MaHS='" + MaHS + "') "
Set RS = DB.OpenRecordset(SQL, dbOpenDynaset, dbReadOnly)
'Loc theo nam hoc
RS.Filter = " (tblKQNAMHOC.MaNH='" + MaNH + "')"
Set RS1 = RS.OpenRecordset
RS.Close
If RS1.EOF Then 'Neu khong co ket qua
Chuoi = "@chưa_có_KQ_cuối_năm_học" + Im200 & TenNH(0) _
+ Im400 & TenNH(1) + Im400 + "@của_học_sinh" _
+ Im200 + HoTenHS
Else
Chuoi = "@KQ_cuối_năm_học" + Im200 & TenNH(0) _
& Im400 & TenNH(1) & Im400 + "@của_học_sinh" _
+ Im200 + HoTenHS + Im800 + "@điểm_trung_bình" _
+ Im200 + Split_FloatNumber(RS1!DTBNH) + Im400 _
+ "hạng" + Im200 & RS1!HangNH & Im400 _
+ "@học_lực" + Im200 + RS1!TenHL + Im400 + "@hạnh_kiểm" _
+ Im200 + RS1!TenHK
End If
Chuoi = Chuoi + " @về_menu"
RS1.Close
Call Monitor_DTMF(True)
Call Play_Voice(Chuoi)
End Sub
Lấy kết quả cuối học kỳ :
Public Sub Get_KQHocKy(ByVal TenHKy As Byte)
Dim RS As Recordset, RS1 As Recordset
Dim SQL As String, Chuoi As String
SQL = "SELECT tblKQHOCKY.DTBHKy, " _
& " tblKQHOCKY.HangHKy, tblHOCLUC.TenHL, tblHANHKIEM.TenHK, " _
& " tblKQHOCKY.TenHKy, tblKQHOCKY.MaNH" _
& " FROM tblHANHKIEM " _
& " INNER JOIN (tblHOCLUC " _
& " INNER JOIN tblKQHOCKY " _
& " ON tblHOCLUC.MaHL = tblKQHOCKY.MaHL)" _
& " ON tblHANHKIEM.MaHK=tblKQHOCKY.MaHK " _
& " WHERE (tblKQHOCKY.MaHS='" + MaHS + "') "
Set RS = DB.OpenRecordset(SQL, dbOpenDynaset, dbReadOnly)
'Loc theo nam hoc va hoc ky
SQL = " (tblKQHOCKY.TenHKy=" & TenHKy & ") AND " _
& " (tblKQHOCKY.MaNH='" & MaNH & "')"
RS.Filter = SQL
Set RS1 = RS.OpenRecordset
RS.Close
If RS1.EOF Then 'Neu khong co ket qua
Chuoi = "@chưa_có_KQ_của_học_kỳ " & TenHKy _
& Im400 + "@năm_học" + Im200 & TenNH(0) _
& Im400 & TenNH(1) & Im400 + "@của_học_sinh" _
+ Im200 + HoTenHS
Else
Chuoi = "@KQ_của_học_kỳ " & TenHKy & Im400 _
+ "@năm_học" + Im200 & TenNH(0) _
& Im400 & TenNH(1) & Im400 _
& "@của_học_sinh" + Im200 + HoTenHS + Im800 _
+ "@điểm_trung_bình" + Im200 + Split_FloatNumber(RS1!DTBHKy) _
+ Im400 + "hạng" + Im400 & RS1!HangHKy _
& Im400 + "@học_lực" + Im200 + RS1!TenHL + Im400 _
+ "@hạnh_kiểm" & Im200 & RS1!TenHK
End If
Chuoi = Chuoi + " @về_menu"
RS1.Close
Call Monitor_DTMF(True)
Call Play_Voice(Chuoi)
End Sub
Lấy kết quả cuối tháng :
Public Sub Get_KQThang(ByVal TenThang As Byte)
Dim RS As Recordset, RS1 As Recordset
Dim SQL As String, Chuoi As String
SQL = "SELECT tblKQTHANG.DTBThang, tblKQTHANG.HangThang, " _
& " tblHOCLUC.TenHL, tblHANHKIEM.TenHK, " _
& "tblKQTHANG.TenThang, tblKQTHANG.MaNH" _
& " FROM tblHANHKIEM " _
& " INNER JOIN (tblHOCLUC " _
& " INNER JOIN tblKQTHANG " _
& " ON tblHOCLUC.MaHL = tblKQTHANG.MaHL)" _
& " ON tblHANHKIEM.MaHK=tblKQTHANG.MaHK " _
& " WHERE (tblKQTHANG.MaHS='" + MaHS + "') "
Set RS = DB.OpenRecordset(SQL, dbOpenDynaset, dbReadOnly)
'Loc theo nam hoc va thang
SQL = " (tblKQTHANG.TenThang=" & TenThang & ") AND " _
& " (tblKQTHANG.MaNH='" & MaNH & "')"
RS.Filter = SQL
Set RS1 = RS.OpenRecordset
RS.Close
If RS1.EOF Then 'Neu khong co ket qua
Chuoi = "@chưa_có_KQ_của_tháng " & TenThang _
& Im400 + "@năm_học" + Im200 & TenNH(0) & Im400 _
& TenNH(1) & Im400 + "@của_học_sinh" + Im200 + HoTenHS
Else
Chuoi = "@KQ_của_tháng " & TenThang _
& Im400 + "@năm_học" + Im200 & TenNH(0) _
& Im400 & TenNH(1) & Im400 + "@của_học_sinh" _
+ Im200 + HoTenHS + Im400 + "@điểm_trung_bình" + Im200 _
+ Split_FloatNumber(RS1!DTBThang) + Im400 + "hạng" + Im200 _
& RS1!HangThang & Im400 + "@học_lực" + Im200 _
+ RS1!TenHL + Im400 + "@hạnh_kiểm" + Im200 + RS1!TenHK
End If
Chuoi = Chuoi + " @về_menu"
RS1.Close
Call Monitor_DTMF(True)
Call Play_Voice(Chuoi)
End Sub
Lấy kết quả thi học kỳ :
Public Sub Get_KQThi(ByVal HKThi As Byte)
Dim RS As Recordset, RS1 As Recordset
Dim SQL As String, Chuoi As String
SQL = "SELECT tblKQTHI.DiemThi, tblMONHOC.TenMH, " _
+ "tblKQTHI.HKThi, tblKQTHI.MaNH, tblKQTHI.MaMH" _
+ " FROM tblMONHOC " _
+ " INNER JOIN tblKQTHI " _
+ " ON tblMONHOC.MaMH=tblKQTHI.MaMH " _
+ " WHERE (tblKQTHI.MaHS='" + MaHS + "')"
Set RS = DB.OpenRecordset(SQL, dbOpenDynaset, dbReadOnly)
'Loc theo nam hoc va hoc ky
SQL = " (tblKQTHI.HKThi=" & HKThi & ") AND " _
+ " (tblKQTHI.MaNH='" & MaNH & "') "
RS.Filter = SQL
Set RS1 = RS.OpenRecordset
RS.Close
'Sort
RS1.Sort = "tblKQTHI.MaMH"
Set RS = RS1.OpenRecordset
RS1.Close
If RS.EOF Then 'Neu khong co ket qua
'chưa có điểm thi = chưa có điểm thi của các môn học của học kỳ
Chuoi = "@chưa_có_điểm_thi " & HKThi & Im400 + "@năm_học" _
+ Im200 & TenNH(0) & Im400 & TenNH(1) _
& Im400 + "@của_học_sinh" + Im200 + HoTenHS
Else
'điểm thi = điểm thi của các môn học của học kỳ
Chuoi = "@điểm_thi " & HKThi & Im400 + "@năm_học" + Im200 _
& TenNH(0) & Im400 & TenNH(1) & Im400 _
+ "@của_học_sinh" + Im200 + HoTenHS
Do While Not RS.EOF
Chuoi = Chuoi + Im800 + RS!TenMH + Im400 _
+ Split_FloatNumber(RS!DiemThi)
RS.MoveNext
Loop
End If
Chuoi = Chuoi + " @về_menu"
RS.Close
Call Monitor_DTMF(True)
Call Play_Voice(Chuoi)
End Sub
Lấy kết quả kiểm tra trong tháng :
Public Sub Get_KQKiemTra(ByVal ThangKT As Byte)
Dim RS As Recordset, RS1 As Recordset
Dim SQL As String, Chuoi As String
Dim CurTenMH As String, CurTenLoaiKT As String, CurLanKT As String
SQL = "SELECT tblKQKIEMTRA.DiemKT, tblMONHOC.TenMH, " _
& " tblKQKIEMTRA.LanKT, tblLOAIKT.TenLoaiKT, tblKQKIEMTRA.MaNH, " _
& "tblKQKIEMTRA.ThangKT, tblKQKIEMTRA.MaMH" _
& " FROM tblLOAIKT " _
& " INNER JOIN (tblMONHOC " _
& " INNER JOIN tblKQKIEMTRA " _
& " ON tblMONHOC.MaMH=tblKQKIEMTRA.MaMH) " _
& " ON tblLOAIKT.MaLoaiKT=tblKQKIEMTRA.MaLoaiKT " _
& " WHERE (tblKQKIEMTRA.MaHS='" + MaHS + "') "
Set RS = DB.OpenRecordset(SQL, dbOpenDynaset, dbReadOnly)
'Loc theo nam hoc va thang
SQL = " (tblKQKIEMTRA.ThangKT=" & ThangKT & ") AND " _
& " (tblKQKIEMTRA.MaNH='" & MaNH & "')"
RS.Filter = SQL
Set RS1 = RS.OpenRecordset
RS.Close
'Sort
RS1.Sort = "tblKQKIEMTRA.MaMH, tblLOAIKT.TenLoaiKT DESC, tblKQKIEMTRA.LanKT"
Set RS = RS1.OpenRecordset
RS1.Close
If RS.EOF Then 'Neu khong co ket qua
'chưa có điểm kiểm tra = chưa có điểm kiểm tra của các môn học của tháng
Chuoi = "@chưa_có_điểm_kiểm_tra " + Im200 & ThangKT _
& Im400 + "@năm_học" + Im200 & TenNH(0) & Im400 _
& TenNH(1) & Im400 + "@của_học_sinh" + Im200 + HoTenHS
Else
''điểm kiểm tra = điểm kiểm tra của các môn học của tháng
Chuoi = "@điểm_kiểm_tra " & ThangKT & Im400 _
+ "@năm_học" + Im200 & TenNH(0) & Im400 _
& TenNH(1) & Im400 + "@của_học_sinh" + Im200 + HoTenHS
Do While Not RS.EOF
CurTenMH = RS!TenMH
Chuoi = Chuoi + Im800 + "môn " + Im200 + CurTenMH
Do While RS!TenMH = CurTenMH
CurTenLoaiKT = RS!TenLoaiKT
Chuoi = Chuoi + Im800 + "@kiểm_tra " + CurTenLoaiKT
Do While (RS!TenLoaiKT = CurTenLoaiKT) And (RS!TenMH = CurTenMH)
CurLanKT = RS!LanKT
Chuoi = Chuoi + Im800 + "lần " + CurLanKT
Chuoi = Chuoi + Im400 + Split_FloatNumber(RS!DiemKT)
RS.MoveNext
If RS.EOF Then GoTo Thoat
Loop
Loop
Loop
End If
Thoat:
Chuoi = Chuoi + " @về_menu"
RS.Close
Call Monitor_DTMF(True)
Call Play_Voice(Chuoi)
End Sub
Lấy thông tin chi tiết về học sinh :
Public Sub Get_Info_HS()
Dim RS As Recordset
Dim SQL As String, Chuoi As String, GT As String
SQL = "SELECT tblHOCSINH.NgS, tblHOCSINH.GT, tblNOISINH.TenNS, " _
& " tblLOP.TenLOP, tblKHOI.TenKhoi " _
& " FROM tblNOISINH " _
& " INNER JOIN (tblKHOI " _
& " INNER JOIN (tblLOP " _
& " INNER JOIN (tblHOCSINH " _
& " INNER JOIN tblHS_LOP " _
& " ON tblHOCSINH.MaHS = tblHS_LOP.MaHS) " _
& " ON tblLOP.MaLop = tblHS_LOP.MaLop) " _
& " ON tblKHOI.TenKhoi = tblLOP.TenKhoi) " _
& " ON tblNOISINH.MaNS = tblHOCSINH.MaNS " _
& " WHERE tblHOCSINH.MaHS='" + MaHS + "'"
Set RS = DB.OpenRecordset(SQL, dbOpenDynaset, dbReadOnly)
If Not RS.EOF Then 'Neu co
If RS!GT = True Then GT = "nam" Else GT = "nữ"
'thông tin chi tiết = thông tin chi tiết của học sinh
Chuoi = "@thông_tin_chi_tiết" + Im200 + HoTenHS + Im400 _
& "@ngày_sinh" + Im200 & Day(RS!NgS) & " tháng " _
& Month(RS!NgS) & Im200 + " năm " & Year(RS!NgS) _
& Im400 + "@giới_tính" + Im200 + GT + Im400 + "@nơi_sinh" _
+ Im200 + RS!TenNS + Im400 + "@là_học_sinh_của_lớp" + Im200 _
+ Split_TenLop(RS!TenKhoi, RS!TenLop) + Im400 + "@năm_học" _
+ Im200 & TenNH(0) & Im400 & TenNH(1)
End If
Chuoi = Chuoi + " @về_menu"
RS.Close
Call Monitor_DTMF(True)
Call Play_Voice(Chuoi)
End Sub
2. CHƯƠNG TRÌNH CẬP NHẬT DỮ LIỆU
Lấy học sinh trong lớp hiện tại :
'Chon hoc sinh trong lop hien tai
Private Function Load_HocSinh() As Boolean
Dim SQL As String
SQL = "SELECT tblHOCSINH.MaHS, tblHOCSINH.HoHS, tblHOCSINH.TenHS, " _
& " tblHOCSINH.NgS , tblHOCSINH.GT, tblHOCSINH.MaNS " _
& " FROM tblHOCSINH " _
& " INNER JOIN tblHS_LOP " _
& " ON tblHOCSINH.MaHS = tblHS_LOP.MaHS " _
& " WHERE (tblHS_LOP.MaNH ='" + frmMain.DBcboNH.BoundText + "')" _
& " AND (tblHS_LOP.MaLop = " + frmMain.DBcboLop.BoundText + ")"
Set rsHS = DB.OpenRecordset(SQL)
Load_HocSinh = Not rsHS.EOF
End Function
Thêm học sinh mới :
Private Sub cmdNew_Click()
On Error GoTo Thoat
RecHT = rsHS.AbsolutePosition 'Luu vtri cu de quay lai
rsHS.AddNew
Call Lock_Data(False)
Call Enable_Buttons(False)
cmdUpdate.Enabled = True
cmdDel.Enabled = True
Call Clear_Data(False)
txtMaHS = Generate_MaHS
txtHoHS.SetFocus
Adding = True
Thoat:
End Sub
Sửa đổi thông tin của học sinh :
'Sua doi du lieu cua record hien tai
Private Sub cmdEdit_Click()
On Error GoTo Thoat
Call Enable_Buttons(False)
cmdUpdate.Enabled = True
Call Lock_Data(False)
txtMaHS = rsHS!MaHS
txtHoHS.SetFocus
rsHS.Edit
Thoat:
End Sub
Lưu học sinh mới vào cơ sở dữ liệu :
'Luu du lieu vao cac table
Private Function Save_Data() As Boolean
Dim SQL As String
rsHS!MaHS = txtMaHS
rsHS!HoHS = txtHoHS
rsHS!TenHS = txtTenHS
rsHS!NgS = txtNgS.Tag
rsHS!GT = cboGT.ListIndex - 1
rsHS!MaNS = DBcboNS.BoundText
rsHS.Update
If Adding Then
'Update tblHS_LOP
SQL = "INSERT INTO tblHS_LOP(MaHS,MaLop,MaNH) " _
+ " VALUES('" + txtMaHS + "'," _
+ frmMain.DBcboLop.BoundText + ",'" + frmMain.DBcboNH.BoundText + "')"
DB.Execute SQL
End If
End Function
Xóa học sinh :
Private Sub Delete_HS()
Dim SQL As String
Dim RS As Recordset
'Xoa 1 record trong tblHS_LOP
RecHT = rsHS.AbsolutePosition
If RecHT = rsHS.RecordCount - 1 Then RecHT = RecHT - 1
SQL = "DELETE FROM tblHS_LOP " _
+ " WHERE (MaHS='" + txtMaHS.Text + "') " _
+ " AND (MaLop=" + frmMain.DBcboLop.BoundText + ") " _
+ " AND (MaNH='" + frmMain.DBcboNH.BoundText + "')"
DB.Execute SQL
'Ktra neu hoc sinh nay khong con thuoc 1 lop nao nua thi xoa khoi tblHOCSINH
SQL = "SELECT MaHS FROM tblHS_LOP " _
+ " WHERE (MaHS='" + txtMaHS.Text + "') "
Set RS = DB.OpenRecordset(SQL)
If RS.EOF Then 'HS khong con thuoc lop nao nua --> XOA
SQL = "DELETE FROM tblHOCSINH " _
+ " WHERE (MaHS='" + txtMaHS.Text + "') "
DB.Execute SQL
End If
RS.Close
End Sub
Chuyển học sinh sang lớp khác :
'Chuyen HS qua lop khac
Private Sub cmdMove_Click()
Dim SQL As String
On Error GoTo Thoat
cmdMove.Tag = vbNullString 'Se nhan MaLop
frmMove.Show vbModal, frmMain
If (cmdMove.Tag vbNullString) And (cmdMove.Tag frmMain.DBcboLop.BoundText) Then
RecHT = rsHS.AbsolutePosition
If RecHT = rsHS.RecordCount - 1 Then RecHT = RecHT - 1
'Update tblHS_LOP
SQL = "UPDATE tblHS_LOP SET MaLop=" + cmdMove.Tag _
+ " WHERE (MaHS='" + txtMaHS + "') AND (MaLop=" + frmMain.DBcboLop.BoundText _
+ ") AND (MaNH='" + frmMain.DBcboNH.BoundText + "')"
DB.Execute SQL
'Refresh data
If Load_HocSinh() = True Then
rsHS.MoveLast 'refresh completely
rsHS.AbsolutePosition = RecHT
Call Show_Data
Else ' nothing
Call Show_NoData
End If
End If
Thoat:
End Sub
Thêm học sinh ở năm học cũ vào năm học mới :
'Them cac HS o nam hoc cu vao lop hien tai
Private Sub cmdHSCu_Click()
Dim RS As DAO.Recordset
Dim SQL As String
Dim NHCu As Integer
Dim MaNHCu As String
On Error GoTo Thoat
'Ktra nam hoc truoc co hay khong ?
NHCu = CInt(Left(frmMain.DBcboNH.Text, 4)) - 1
MaNHCu = Right(CStr(NHCu), 2)
SQL = "SELECT * FROM tblNAMHOC WHERE MaNH='" + MaNHCu + "'"
Set RS = DB.OpenRecordset(SQL)
If (NHCu < 1980) Or (RS.EOF) Then
MsgBox "Kh«ng t×m thÊy n¨m häc " & NHCu & " - " & NHCu + 1
RS.Close
Else
cmdHSCu.Tag = RS!TenNH
RS.Close
frmHSCu.Show vbModal, frmMain
End If
Thoat:
End Sub
Nạp kết quả cuối học kỳ :
'Chon cac ket qua cua hoc sinh hien tai
Private Function Load_KQ() As Boolean
Dim SQL As String
SQL = "SELECT * " _
+ " FROM tblKQHOCKY " _
+ " WHERE (tblKQHOCKY.MaHS ='" + txtMaHS + "')" _
+ " AND (MaNH='" + frmMain.DBcboNH.BoundText + "')" _
+ " ORDER BY TenHKy"
Set rsKQHK = DB.OpenRecordset(SQL)
Load_KQ = Not rsKQHK.EOF
End Function
Nạp kết quả cuối năm học :
'Chon cac ket qua cua hoc sinh hien tai
Private Function Load_KQ() As Boolean
Dim SQL As String
SQL = "SELECT * " _
+ " FROM tblKQNAMHOC " _
+ " WHERE (tblKQNAMHOC.MaHS ='" + txtMaHS + "')" _
+ " AND (MaNH='" + frmMain.DBcboNH.BoundText + "')"
Set rsKQNH = DB.OpenRecordset(SQL)
Load_KQ = Not rsKQNH.EOF
End Function
Nạp kết quả cuối tháng :
'Chon cac ket qua cua hoc sinh hien tai
Private Function Load_KQ() As Boolean
Dim SQL As String
SQL = "SELECT * " _
+ " FROM tblKQTHANG " _
+ " WHERE (tblKQTHANG.MaHS ='" + txtMaHS + "')" _
+ " AND (MaNH='" + frmMain.DBcboNH.BoundText + "')" _
+ " ORDER BY TenThang"
Set rsKQThang = DB.OpenRecordset(SQL)
Load_KQ = Not rsKQThang.EOF
End Function
Nạp kết quả kiểm tra :
'Chon cac ket qua cua hoc sinh hien tai
Private Function Load_KQ() As Boolean
Dim SQL As String
SQL = "SELECT tblKQKIEMTRA.MaHS, tblKQKIEMTRA.ThangKT, tblKQKIEMTRA.MaMH, " _
+ " tblKQKIEMTRA.MaNH , tblKQKIEMTRA.DiemKT, " _
+ " tblKQKIEMTRA.MaLoaiKT, tblKQKIEMTRA.LanKT " _
+ " FROM tblKQKIEMTRA " _
+ " WHERE (tblKQKIEMTRA.MaHS ='" + txtMaHS + "')" _
+ " AND (MaNH='" + frmMain.DBcboNH.BoundText + "')" _
+ " ORDER BY ThangKT, MaMH, MaLoaiKT, LanKT"
Set rsKT = DB.OpenRecordset(SQL)
Load_KQ = Not rsKT.EOF
End Function
Nạp kết quả thi :
'Chon cac ket qua cua hoc sinh hien tai
Private Function Load_KQ() As Boolean
Dim SQL As String
SQL = "SELECT tblKQTHI.MaHS, tblKQTHI.HKThi, tblKQTHI.MaMH, " _
+ " tblKQTHI.MaNH , tblKQTHI.DiemThi " _
+ " FROM tblKQTHI " _
+ " WHERE (tblKQTHI.MaHS ='" + txtMaHS + "')" _
+ " AND (MaNH='" + frmMain.DBcboNH.BoundText + "')" _
+ " ORDER BY HKThi, MaMH"
Set rsThi = DB.OpenRecordset(SQL)
Load_KQ = Not rsThi.EOF
End Function
Nạp các lần nghỉ học :
'Chon cac ket qua cua hoc sinh hien tai
Private Function Load_KQ() As Boolean
Dim SQL As String
SQL = "SELECT tblNGHIHOC.MaHS, tblNGHIHOC.NgayNH, tblNGHIHOC.SoNgayNH, " _
+ " tblNGHIHOC.GiayPhep , tblNGHIHOC.MaLD " _
+ " FROM tblNGHIHOC " _
+ " WHERE (tblNGHIHOC.MaHS ='" + txtMaHS + "')" _
+ " ORDER BY NgayNH "
Set rsNgH = DB.OpenRecordset(SQL)
Load_KQ = Not rsNgH.EOF
End Function
Nạp các lần vi phạm :
'Chon cac ket qua cua hoc sinh hien tai
Private Function Load_KQ() As Boolean
Dim SQL As String
SQL = "SELECT tblVIPHAM.MaHS, tblVIPHAM.NgayVP, " _
+ " tblVIPHAM.LanVP, tblVIPHAM.MaLoi " _
+ " FROM tblVIPHAM " _
+ " WHERE (tblVIPHAM.MaHS ='" + txtMaHS + "')" _
+ " ORDER BY NgayVP, LanVP "
Set rsVP = DB.OpenRecordset(SQL)
Load_KQ = Not rsVP.EOF
End Function
3. CHƯƠNG TRÌNH THU TIẾNG NÓI
Tạo vùng đệm để thu âm :
'Chuan bi vung dem va header de thu
Private Function Prepare_Buffer(BufferSize As Long) As Boolean
Dim Loi As Long
Dim hData As Long
'Cap phat bo nho de luu cac mau am thanh
hData = GlobalAlloc(GPTR, BufferSize)
If hData = 0 Then
MsgBox "Không thể cấp phát bộ nhớ !", vbCritical, "Thu"
Prepare_Buffer = False
Exit Function
End If
'Tro toi vung nho vua cap phat
pWaveHeader.lpData = GlobalLock(hData)
If pWaveHeader.lpData = 0 Then
MsgBox "Không thể lấy địa chỉ vùng nhớ được cấp phát !", vbCritical, "Thu"
hData = GlobalFree(hData)
Prepare_Buffer = False
Exit Function
End If
pWaveHeader.dwBufferLength = BufferSize
Loi = waveInPrepareHeader(hWaveIn, pWaveHeader, Len(pWaveHeader))
If Loi 0 Then
MsgBox "Lỗi : waveInPrepareHeader", vbCritical, "Thu"
hData = GlobalFree(hData)
Prepare_Buffer = False
Exit Function
End If
Loi = waveInAddBuffer(hWaveIn, pWaveHeader, Len(pWaveHeader))
If Loi 0 Then
MsgBox "Lỗi : waveInAddBuffer", vbCritical, "Thu"
hData = GlobalFree(hData)
Call waveInUnprepareHeader(hWaveIn, pWaveHeader, Len(pWaveHeader))
Prepare_Buffer = False
Exit Function
End If
'Luu handle cua vung nho cac sample
pWaveHeader.dwUser = hData
Prepare_Buffer = True
End Function
Thu âm thanh :
'Bat dau thu am thanh
Public Sub Start_Record()
Dim BufferSize As Long
Dim Loi As Long
With pWaveFormat
.cbSize = 0
.nAvgBytesPerSec = BytesPerSec
.nBlockAlign = 1
.nChannels = 1
.nSamplesPerSec = BytesPerSec
.wBitsPerSample = 8
.wFormatTag = 1
End With
BufferSize = MaxTime * pWaveFormat.nSamplesPerSec '=Tong so sample = Tong so byte bo nho can cap phat
Loi = waveInOpen(hWaveIn, SoundCard, pWaveFormat, AddressOf waveInProc, 0, CALLBACK_FUNCTION)
If Loi 0 Then
MsgBox "Lỗi : waveInOpen", vbCritical, "Thu"
Call Enable_Buttons(True)
Exit Sub
End If
If Prepare_Buffer(BufferSize) = False Then 'Loi
Call waveInClose(hWaveIn)
Call Enable_Buttons(True)
Exit Sub
End If
'Bat dau thu
Loi = waveInStart(hWaveIn)
If Loi 0 Then
MsgBox "Lỗi : waveInStart", vbCritical, "Thu"
Loi = waveInClose(hWaveIn)
Call Enable_Buttons(True)
Exit Sub
End If
'Sub waveInProc will be called when finish recording
End Sub
Tiếp nhận các sự kiện của thiết bị thu âm :
'This sub will be called when finish recording
Private Sub waveInProc(ByVal hwi As Long, ByVal uMsg As Long, ByVal dwInstance As Long, ByRef dwParam1 As Long, ByVal dwParam2 As Long)
Select Case uMsg
Case MM_WIM_DATA
frmRecord.Timer1.Enabled = True
End Select
End Sub
Lưu dữ liệu tiếng nói vào file *.sam :
'Ghi du lieu am thanh vao file
Private Function Save_Voice() As Boolean
Dim FileNum As Long, arrData() As Byte
Dim Loi As Long
Dim Res As VbMsgBoxResult
Save_Voice = False
'Dinh vtri o cuoi file de ghi
If Dir(SourcePath + VoiceFName, vbNormal) = vbNullString Then
NewFileOffset = 1 'Offset bat dau tu 1 de ghi
AddNew = True
Else 'Ghi tiep vao file da co roi
RS.Seek "=", Trim(txtChuoi)
If RS.NoMatch = False Then 'Neu da thu roi thi xoa, sau do thu lai
Res = MsgBox("Từ này đã được thu rồi. Bạn có muốn thu lại ?", vbQuestion + vbYesNo + vbDefaultButton2, "Thu")
If Res = vbNo Then Exit Function
proBar.Max = proBar.Max + 2
Call Remove_Voice(RS!FileOffset, RS!DataSize)
AddNew = False
Else
AddNew = True
End If
NewFileOffset = FileLen(SourcePath + VoiceFName) + 1 'Di chuyen toi cuoi file
End If
'Chuyen du lieu vao mang
NewDataSize = pWaveHeader.dwBytesRecorded
ReDim arrData(NewDataSize - 1)
CopyMemory arrData(0), pWaveHeader.lpData, NewDataSize
proBar.Value = proBar.Value + 1
'Cat bo silence o dau va cuoi
Call Truncate(arrData())
NewDataSize = UBound(arrData) + 1
proBar.Value = proBar.Value + 1
'Ghi vao file
FileNum = FreeFile
Open SourcePath + VoiceFName For Binary Access Write As #FileNum
Put #FileNum, NewFileOffset, arrData()
Close #FileNum
proBar.Value = proBar.Value + 1
Save_Voice = True
End Function
Cập nhật lại bảng chỉ mục sau khi xóa :
'Update FileOffset sau khi remove Voice
'Update all FileOffset > Current FileOffset
Private Sub Update_Index(OldFileOffset As Long, OldDataSize As Long)
Dim SQL As String
SQL = "UPDATE tblVOICEINDEX SET FileOffset=FileOffset - " _
& OldDataSize & " WHERE (Nhom = '" + Nhom + "')" _
& " AND (FileOffset > " & OldFileOffset & ")"
DB.Execute SQL
End Sub
Ghi mới vào bảng chỉ mục sau khi thu xong :
'Ghi index cua am thanh vua thu vao CSDL
Private Sub Write_Index()
If AddNew = True Then
RS.AddNew
RS!Chuoi = txtChuoi.Tag
RS!Nhom = Nhom
Else
RS.Edit
End If
RS!FileOffset = NewFileOffset - 1 'Offset bat dau tu 0 khi doc ra de phat
RS!DataSize = NewDataSize
RS.Update
End Sub
Lấy thông tin của một từ đã được thu từ bảng chỉ mục :
'Lay FileOffset va DataSize trong CSDL
Public Function Get_Offset_Size(ByRef FileOffset As Long, ByRef DataSize As Long) As Boolean
RS.Seek "=", frmRecord.txtChuoi.Tag
If RS.NoMatch Then
Get_Offset_Size = False
MsgBox "Chuỗi này chưa được thu !", vbCritical, Title
Else
FileOffset = RS!FileOffset
DataSize = RS!DataSize
Get_Offset_Size = True
End If
End Function
Thêm khoảng thời gian im lặng:
'Chen them 1 khoang im lang vao dau/cuoi loi noi
Private Sub Insert_Silence()
Dim FileOffset As Long, DataSize As Long
Dim BeforeSize As Long, AfterSize As Long 'So byte im lang can dung truoc va sau
Dim i As Long
Dim FileNum As Integer
Dim arrData() As Byte, arrTemp() As Byte
'Tinh kich thuoc du lieu
BeforeSize = Val(txtBefore) * BytesPerSec \ 1000 'Thoi gian theo milisecond
AfterSize = Val(txtAfter) * BytesPerSec \ 1000
If (BeforeSize = 0) And (AfterSize = 0) Then GoTo Thoat
If Get_Offset_Size(FileOffset, DataSize) = False Then GoTo Thoat
NewDataSize = BeforeSize + DataSize + AfterSize 'se ghi vao CSDL
ReDim arrData(NewDataSize - 1)
Call Fill_Silence(arrData(), BeforeSize, AfterSize)
'Doc du lieu vao mang
ReDim arrTemp(DataSize - 1)
FileNum = FreeFile
Open SourcePath + VoiceFName For Binary Access Read As #FileNum
Get #FileNum, FileOffset + 1, arrTemp
Close FileNum
For i = 0 To DataSize - 1
arrData(BeforeSize + i) = arrTemp(i)
Next
proBar.Value = proBar.Value + 1
'Xoa bo doan du lieu cu trong CSDL
Call Remove_Voice(FileOffset, DataSize)
proBar.Value = proBar.Value + 1
'Ghi lai du lieu vao cuoi file voice
FileNum = FreeFile
Open SourcePath + VoiceFName For Binary Access Write As #FileNum
NewFileOffset = LOF(FileNum) + 1
Put #FileNum, NewFileOffset, arrData
Close #FileNum
proBar.Value = proBar.Value + 1
'Cap nhat vao CSDL
AddNew = False 'Cap nhat
Call Write_Index
Thoat:
End Sub
Xóa một đoạn âm thanh đã thu :
'Loai bo doan am thanh da co
'Offset danh tu 1 khi ghi file va danh tu 0 khi doc file de phat
Private Sub Remove_Voice(OldFileOffset As Long, OldDataSize As Long)
Dim FileNum_R, FileNum_W As Long
Dim DataSize1 As Long, DataSize2 As Long
Dim arrData() As Byte
'Mo file
OldFileOffset = OldFileOffset + 1 'Offset danh tu 1
FileNum_R = FreeFile
Open SourcePath + VoiceFName For Binary Access Read As #FileNum_R
FileNum_W = FreeFile
Open SourcePath + NewFName For Binary Access Write As #FileNum_W
'Tinh kich thuoc 2 doan du lieu dau va cuoi
DataSize1 = OldFileOffset - 1
DataSize2 = FileLen(SourcePath + VoiceFName) - DataSize1 - OldDataSize
'Doc va ghi lai doan du lieu dau
If DataSize1 > 0 Then 'Neu khong phai la first record
ReDim arrData(DataSize1 - 1)
Get #FileNum_R, , arrData
Put #FileNum_W, , arrData
End If
proBar.Value = proBar.Value + 1
'Doc va ghi lai doan du lieu cuoi
If DataSize2 > 0 Then 'Neu khong phai la last record
ReDim arrData(DataSize2 - 1)
Get #FileNum_R, OldFileOffset + OldDataSize, arrData
Put #FileNum_W, , arrData
End If
Close #FileNum_R
Close #FileNum_W
'Xoa file cu va doi ten file moi
Kill SourcePath + VoiceFName
Name SourcePath + NewFName As SourcePath + VoiceFName
proBar.Value = proBar.Value + 1
'Update index table
Call Update_Index(OldFileOffset - 1, OldDataSize)
End Sub
Nạp dữ liệu tiếng nói vào bộ nhớ để phát :
'Load data from database into memmory
Private Function Loaded_VoiceFile() As Boolean
Dim FileOffset As Long, DataSize As Long, hFile As Long, Loi As Long
Dim pmmIOInfo As mmIOInfo
'Tim thong tin chuoi trong CSDL
If Get_Offset_Size(FileOffset, DataSize) = False Then
Call Enable_Buttons(True)
Exit Function
End If
'Ktra file voice co khong ?
If File_Exist(SourcePath + VoiceFName) = False Then
Call Enable_Buttons(True)
Exit Function
End If
'Mo file Voice de doc du lieu
hFile = mmioOpen(SourcePath + VoiceFName, pmmIOInfo, MMIO_READ)
Loi = mmioSeek(hFile, FileOffset, SEEK_SET)
If Loi = -1 Then
MsgBox "File '" + SourcePath + VoiceFName + "' không hợp lệ !", vbCritical, "Phát"
Call mmioClose(hFile, 0)
Call Enable_Buttons(True)
Exit Function
End If
'Cap phat bo nho
hMem = GlobalAlloc(GMEM_ZEROINIT, DataSize)
pWaveBuffer = GlobalLock(hMem)
'Doc du lieu voice
Loi = mmioRead(hFile, pWaveBuffer, DataSize)
If Loi = -1 Then
MsgBox "Không đọc được file '" + SourcePath + VoiceFName + "'", vbCritical, "Phát"
hMem = GlobalFree(hMem)
Call mmioClose(hFile, 0)
Call Enable_Buttons(True)
Exit Function
End If
' Dong file wave sau khi doc xong du lieu file wave
Loi = mmioClose(hFile, 0)
'Set format for playing
TotalSamples = DataSize
With pWaveFormat
.cbSize = 0
.nAvgBytesPerSec = BytesPerSec
.nBlockAlign = 1
.nChannels = 1
.nSamplesPerSec = BytesPerSec
.wBitsPerSample = 8
.wFormatTag = 1
End With
Loaded_VoiceFile = True
End Function
Phát tiếng nói :
'Bat dau phat
Private Sub Start_Playing()
Dim Loi As Long
Dim ErrMsg As String * 200
Loi = waveOutOpen(hWaveOut, SoundCard, pWaveFormat, AddressOf waveOutProc, 0, CALLBACK_FUNCTION)
If Loi 0 Then
hMem = GlobalFree(hMem)
Call waveOutGetErrorText(Loi, ErrMsg, Len(ErrMsg))
MsgBox "Lỗi : waveOutOpen : " & ErrMsg, vbCritical, "Phát"
Call waveOutClose(hWaveOut)
Call Enable_Buttons(True)
Exit Sub
End If
'Chuan bi header cua am thanh de phat ra
pWaveHeader.lpData = pWaveBuffer
pWaveHeader.dwBufferLength = TotalSamples * pWaveFormat.nBlockAlign
pWaveHeader.dwFlags = 0
pWaveHeader.dwLoops = 0
Loi = waveOutPrepareHeader(hWaveOut, pWaveHeader, Len(pWaveHeader))
If Loi 0 Then
hMem = GlobalFree(hMem)
Call waveOutGetErrorText(Loi, ErrMsg, Len(ErrMsg))
MsgBox "Lỗi : waveOutPrepareHeader : " & ErrMsg, vbCritical, "Phát"
Call Enable_Buttons(True)
Call waveOutClose(hWaveOut)
Exit Sub
End If
'Bat dau phat am thanh
Loi = waveOutWrite(hWaveOut, pWaveHeader, Len(pWaveHeader))
If Loi 0 Then
hMem = GlobalFree(hMem)
Call waveOutGetErrorText(Loi, ErrMsg, Len(ErrMsg))
MsgBox "Lỗi : waveOutWrite : " & ErrMsg, vbCritical, "Phát"
Call Enable_Buttons(True)
Call waveOutClose(hWaveOut)
End If
'Sub waveOutProc will be called when finish playing
End Sub
Tiếp nhận các sự kiện của thiết bị phát âm :
'This sub will be called when finish playing
Public Sub waveOutProc(ByVal hwo As Long, ByVal uMsg As Long, ByVal dwInstance As Long, ByRef hdr As WAVEHDR, ByVal dwParam2 As Long)
If uMsg = MM_WOM_DONE Then
frmRecord.Timer1.Enabled = True
End If
End Sub
TÀI LIỆU THAM KHẢO
CDs MSDN 10/2001
E-book : “MAPI, SAPI, and TAPI Developer's Guide” (Michael Amundsen -
TAPI reference (
TAPI description (
TAPI reference and examples (
The Canonical WAVE File Format (
Audio Interchange File Format (
Modem truyền số liệu (Nguyễn Hồng Sơn - Hoàng Đức Hải)
Visual Basic - Lập trình cơ sở dữ liệu
Bí quyết lập trình Visual Basic 6.0 (Nguyễn Tiến - Đặng Xuân Hường - Nguyễn Văn Hoài - Trương Ngọc Vân)
MỤC LỤC
Các file đính kèm theo tài liệu này:
- Thông báo kết quả học tập của học sinh qua điện thoại.doc