[WM][VB][Voice Mail]
在手機上打字是一件很痛苦的事情,如果用說的可能會來得比較快樂點,現在就來跟各位說如何發一封語音郵件,那在手機上要如何錄音呢,我們可以利用 Recording and Playing Sound with the Waveform Audio Interface參考http://msdn.microsoft.com/en-us/library/aa446573.aspx
Step1:開啟vs2008 新增一個vb 智慧型裝置專案,在表單上產生ListBox元件來顯示整個操作過程訊息, Button按鍵用來開始錄音及結束發送mail
Step2:將滑鼠移到方案總管到SmartDeviceProject1下的參考,按下滑鼠右鍵加入參考
Step3:選擇Microsoft.WindowsMobile.PocketOutlook按下確定
Step4:插入Class Memory

01

Imports ...System 02
Imports System.Runtime.InteropServices 03
04
Public Class Memory 05
06
07
Public Const LMEM_FIXED As Integer = &H0 08
09
Public Const LMEM_ZEROINIT As Integer = &H40 10
11
Public Const LMEM_MOVEABLE As Integer = &H2 12
13
Public Const LMEM_MODIFY As Integer = &H80 14
15
16
<DllImport("coredll.dll")> _ 17

Public Shared Function LocalAlloc() Shared Function LocalAlloc(ByVal uFlags As Integer, ByVal uBytes As Integer) As IntPtr 18
End Function 19
20
<DllImport("coredll.dll")> _ 21

Public Shared Function LocalFree() Shared Function LocalFree(ByVal hMem As IntPtr) As IntPtr 22
End Function 23
24
<DllImport("coredll.dll")> _ 25

Public Shared Function LocalReAlloc() Shared Function LocalReAlloc(ByVal hMem As IntPtr, ByVal uBytes As Integer, ByVal fuFlags As Integer) As IntPtr 26
End Function 27
28
End Class
Step5:插入Class Wave

001

Imports ...System 002
Imports System.IO 003
Imports System.Runtime.InteropServices 004
005
006
Public Class Wave 007
008
009
Public Const WAVE_MAPPER As Integer = -1 010
011
Public Const CALLBACK_WINDOW As Integer = &H10000 012
013
Private Const WAVERR_BASE As Integer = 32 014
Private Const MMSYSERR_BASE As Integer = 0 015
016
017
Public Enum MMSYSERR 018
NOERROR = 0 019
GENERROR = (MMSYSERR_BASE + 1) 020
BADDEVICEID = (MMSYSERR_BASE + 2) 021
NOTENABLED = (MMSYSERR_BASE + 3) 022
ALLOCATED = (MMSYSERR_BASE + 4) 023
INVALHANDLE = (MMSYSERR_BASE + 5) 024
NODRIVER = (MMSYSERR_BASE + 6) 025
NOMEM = (MMSYSERR_BASE + 7) 026
NOTSUPPORTED = (MMSYSERR_BASE + 8) 027
BADERRNUM = (MMSYSERR_BASE + 9) 028
INVALFLAG = (MMSYSERR_BASE + 10) 029
INVALPARAM = (MMSYSERR_BASE + 11) 030
HANDLEBUSY = (MMSYSERR_BASE + 12) 031
INVALIDALIAS = (MMSYSERR_BASE + 13) 032
BADDB = (MMSYSERR_BASE + 14) 033
KEYNOTFOUND = (MMSYSERR_BASE + 15) 034
READERROR = (MMSYSERR_BASE + 16) 035
WRITEERROR = (MMSYSERR_BASE + 17) 036
DELETEERROR = (MMSYSERR_BASE + 18) 037
VALNOTFOUND = (MMSYSERR_BASE + 19) 038
NODRIVERCB = (MMSYSERR_BASE + 20) 039
LASTERROR = (MMSYSERR_BASE + 20) 040
End Enum 041
042
' Enum equivalent to WAVERR_* 043
Private Enum WAVERR 044
NONE = 0 045
BADFORMAT = WAVERR_BASE + 0 046
STILLPLAYING = WAVERR_BASE + 1 047
UNPREPARED = WAVERR_BASE + 2 048
SYNC = WAVERR_BASE + 3 049
LASTERROR = WAVERR_BASE + 3 050
End Enum 051
052
053
Public Const WAVE_INVALIDFORMAT As Integer = &H0 054
055
Public Const WAVE_FORMAT_1M08 As Integer = &H1 056
057
Public Const WAVE_FORMAT_1S08 As Integer = &H2 058
059
Public Const WAVE_FORMAT_1M16 As Integer = &H4 060
061
Public Const WAVE_FORMAT_1S16 As Integer = &H8 062
063
Public Const WAVE_FORMAT_2M08 As Integer = &H10 064
065
Public Const WAVE_FORMAT_2S08 As Integer = &H20 066
067
Public Const WAVE_FORMAT_2M16 As Integer = &H40 068
069
Public Const WAVE_FORMAT_2S16 As Integer = &H80 070
071
Public Const WAVE_FORMAT_4M08 As Integer = &H100 072
073
Public Const WAVE_FORMAT_4S08 As Integer = &H200 074
075
Public Const WAVE_FORMAT_4M16 As Integer = &H400 076
077
Public Const WAVE_FORMAT_4S16 As Integer = &H800 078
079
Public Class WAVEFORMATEX 080
081
Protected Const WF_OFFSET_FORMATTAG As Integer = 20 082
Protected Const WF_OFFSET_CHANNELS As Integer = 22 083
Protected Const WF_OFFSET_SAMPLESPERSEC As Integer = 24 084
Protected Const WF_OFFSET_AVGBYTESPERSEC As Integer = 28 085
Protected Const WF_OFFSET_BLOCKALIGN As Integer = 32 086
Protected Const WF_OFFSET_BITSPERSAMPLE As Integer = 34 087
Public Const WF_OFFSET_DATA As Integer = 44 088
089

Public Property wFormatTag() Property wFormatTag() 090
Get 091
Return Convert.ToInt32(m_wFormatTag) 092
End Get 093
Set(ByVal Value) 094
m_wFormatTag = Convert.ToUInt16(Value) 095
End Set 096
End Property 097

Protected m_wFormatTag As UInt16 = Convert.ToUInt16() m_wFormatTag As UInt16 = Convert.ToUInt16(0) 098
099

Public Property nChannels() Property nChannels() 100
Get 101
Return Convert.ToInt32(m_nChannels) 102
End Get 103
Set(ByVal Value) 104
m_nChannels = Convert.ToUInt16(Value) 105
End Set 106
End Property 107

Protected m_nChannels As UInt16 = Convert.ToUInt16() m_nChannels As UInt16 = Convert.ToUInt16(0) 108
109

Public Property nSamplesPerSec() Property nSamplesPerSec() 110
Get 111
Return Convert.ToInt32(m_nSamplesPerSec) 112
End Get 113
Set(ByVal Value) 114
m_nSamplesPerSec = Convert.ToUInt32(Value) 115
End Set 116
End Property 117

Protected m_nSamplesPerSec As UInt32 = Convert.ToUInt32() m_nSamplesPerSec As UInt32 = Convert.ToUInt32(0) 118
119

Public Property nAvgBytesPerSec() Property nAvgBytesPerSec() 120
Get 121
Return Convert.ToInt32(m_nAvgBytesPerSec) 122
End Get 123
Set(ByVal Value) 124
m_nAvgBytesPerSec = Convert.ToUInt32(Value) 125
End Set 126
End Property 127

Protected m_nAvgBytesPerSec As UInt32 = Convert.ToUInt32() m_nAvgBytesPerSec As UInt32 = Convert.ToUInt32(0) 128
129

Public Property nBlockAlign() Property nBlockAlign() 130
Get 131
Return Convert.ToInt32(m_nBlockAlign) 132
End Get 133
Set(ByVal Value) 134
m_nBlockAlign = Convert.ToUInt16(Value) 135
End Set 136
End Property 137

Protected m_nBlockAlign As UInt16 = Convert.ToUInt16() m_nBlockAlign As UInt16 = Convert.ToUInt16(0) 138
139

Public Property wBitsPerSample() Property wBitsPerSample() 140
Get 141
Return Convert.ToInt32(m_wBitsPerSample) 142
End Get 143
Set(ByVal Value) 144
m_wBitsPerSample = Convert.ToUInt16(Value) 145
End Set 146
End Property 147

Protected m_wBitsPerSample As UInt16 = Convert.ToUInt16() m_wBitsPerSample As UInt16 = Convert.ToUInt16(0) 148
149

Public Sub SeekTo() Sub SeekTo(ByVal fs As Stream) 150
fs.Seek(WF_OFFSET_FORMATTAG, SeekOrigin.Begin) 151
End Sub 152
153

Public Sub Skip() Sub Skip(ByVal fs As Stream) 154
fs.Seek(WF_OFFSET_DATA, SeekOrigin.Begin) 155
End Sub 156
157

Public Sub Read() Sub Read(ByVal rdr As BinaryReader) 158
159
m_wFormatTag = rdr.ReadUInt16() 160
m_nChannels = rdr.ReadUInt16() 161
m_nSamplesPerSec = rdr.ReadUInt32() 162
m_nAvgBytesPerSec = rdr.ReadUInt32() 163
m_nBlockAlign = rdr.ReadUInt16() 164
m_wBitsPerSample = rdr.ReadUInt16() 165
166
Dim dataId As UInt32 = rdr.ReadUInt32() 167
Dim dataLength As UInt32 = rdr.ReadUInt32() 168
169
End Sub 170
171

Public Sub Write() Sub Write(ByVal wrtr As BinaryWriter) 172
173
wrtr.Write(Convert.ToUInt16(m_wFormatTag)) 174
wrtr.Write(Convert.ToUInt16(m_nChannels)) 175
wrtr.Write(Convert.ToUInt32(m_nSamplesPerSec)) 176
wrtr.Write(Convert.ToUInt32(m_nAvgBytesPerSec)) 177
wrtr.Write(Convert.ToUInt16(m_nBlockAlign)) 178
wrtr.Write(Convert.ToUInt16(m_wBitsPerSample)) 179
180
End Sub 181
End Class 182
183
Public Class WAVEHDR 184
Implements IDisposable 185
186
Public Const WHDR_DONE As Integer = &H1 187
188
Public Const WHDR_PREPARED As Integer = &H2 189
190
Public Const WHDR_BEGINLOOP As Integer = &H4 191
192
Public Const WHDR_ENDLOOP As Integer = &H8 193
194
Public Const WHDR_INQUEUE As Integer = &H10 195
196
Public Const WAVE_FORMAT_PCM As Integer = 1 197
198
Public lpData As IntPtr = IntPtr.Zero 199
200
Public dwBufferLength As Integer = 0 201
202
Public dwBytesRecorded As Integer = 0 203
204
Public dwUser As Integer = 0 205
206
Public dwFlags As Integer = 0 207
208
Public dwLoops As Integer = 0 209
210
Public lpNext As IntPtr = IntPtr.Zero 211
212
Public reserved As Integer = 0 213
214

Public Function Read() Function Read(ByVal rdr As BinaryReader, ByVal readLength As Integer, ByVal align As Integer) As MMSYSERR 215
216
Dim bufferLength As Integer = readLength 217
218
If bufferLength Mod align <> 0 Then 219
bufferLength += (align - (bufferLength Mod align)) 220
End If 221
222
dwBufferLength = bufferLength 223
Dim data(readLength - 1) As Byte 224
rdr.Read(data, 0, data.Length) 225
226
If lpData.ToInt32() = IntPtr.Zero.ToInt32() Then 227
lpData = Memory.LocalAlloc(Memory.LMEM_FIXED, bufferLength) 228
End If 229
230
If lpData.ToInt32() = IntPtr.Zero.ToInt32() Then 231
Return MMSYSERR.NOMEM 232
End If 233
234
Marshal.Copy(data, 0, lpData, data.Length) 235
236
Return MMSYSERR.NOERROR 237
238
End Function 239
240

Public Function Write() Function Write(ByVal wrtr As BinaryWriter) As MMSYSERR 241
242
If lpData.ToInt32() = IntPtr.Zero.ToInt32() Then 243
Return Wave.MMSYSERR.NOMEM 244
End If 245
246
Dim data(dwBytesRecorded - 1) As Byte 247
Marshal.Copy(lpData, data, 0, data.Length) 248
wrtr.Write(data) 249
250
Return Wave.MMSYSERR.NOERROR 251
252
End Function 253
254

Public Function Init() Function Init(ByVal bufferLength As Integer, ByVal initData As Boolean) As MMSYSERR 255
256
If lpData.ToInt32() <> IntPtr.Zero.ToInt32() AndAlso dwBufferLength < bufferLength Then 257
Memory.LocalFree(lpData) 258
lpData = IntPtr.Zero 259
End If 260
261
If lpData.ToInt32() = IntPtr.Zero.ToInt32() Then 262
lpData = Memory.LocalAlloc(Memory.LMEM_FIXED, bufferLength) 263
End If 264
265
dwBufferLength = bufferLength 266
267
If lpData.ToInt32() = IntPtr.Zero.ToInt32() Then 268
Return MMSYSERR.NOMEM 269
End If 270
271
If initData Then 272
Dim i As Integer 273
For i = 0 To bufferLength - 1 274
Marshal.WriteByte(lpData, i, 0) 275
Next 276
End If 277
278
Return MMSYSERR.NOERROR 279
280
End Function 281
282

Public Sub Dispose() Sub Dispose() Implements IDisposable.Dispose 283
If lpData.ToInt32() <> IntPtr.Zero.ToInt32() Then 284
Memory.LocalFree(lpData) 285
End If 286
End Sub 287
End Class 288
End Class
Step6:插入Class WaveIn

001

Imports ...System 002
Imports System.Runtime.InteropServices 003
Imports System.IO 004
Imports Microsoft.WindowsCE.Forms 005
Imports System.Text 006
Imports System.Threading 007
Imports System.Windows.Forms 008
Imports System.Diagnostics 009
010
011
Public Class WaveIn 012
013
Protected Class WaveFile 014
Implements IDisposable 015
016
Protected m_hwi As IntPtr = IntPtr.Zero 017
018
019
Protected m_wfmt As Wave.WAVEFORMATEX = Nothing 020
021
022

Protected m_whdr() m_whdr() As Wave.WAVEHDR = Nothing 023
024
025
Protected m_inited As Boolean = False 026
027
028
Protected m_curBlock As Integer 029
030
031
Protected m_numBlocks As Integer 032
033
034
Protected m_bufferSize As Integer 035
036
Protected m_maxDataLength As Integer 037
038

Public ReadOnly Property Done() ReadOnly Property Done() 039
Get 040
Return Not m_recording 041
End Get 042
End Property 043
Protected m_recording As Boolean = False 044
045
046

Public Function Preload() Function Preload(ByVal curDevice As Integer, ByVal hwnd As IntPtr, ByVal maxRecordLength_ms As Integer, ByVal bufferSize As Integer) As Wave.MMSYSERR 047
048
' Do not allow recording to be interrupted 049
If m_recording Then 050
Return Wave.MMSYSERR.GENERROR 051
End If 052
053
' If this file is already initialized then start over 054
If m_inited Then 055
StopRecord() 056
FreeWaveBuffers() 057
End If 058
059
' Create an instance of WAVEINCAPS to check if our desired 060
' format is supported 061
Dim caps As WAVEINCAPS = New WAVEINCAPS 062
waveInGetDevCaps(0, caps.Data, caps.Size) 063
If (caps.dwFormats And Wave.WAVE_FORMAT_2S16) = 0 Then 064
Return Wave.MMSYSERR.NOTSUPPORTED 065
End If 066
067
' Initialize a WAVEFORMATEX structure specifying the desired 068
' format 069
m_wfmt = New Wave.WAVEFORMATEX 070
m_wfmt.wFormatTag = Wave.WAVEHDR.WAVE_FORMAT_PCM 071
m_wfmt.wBitsPerSample = 16 072
m_wfmt.nChannels = 2 073
m_wfmt.nSamplesPerSec = 22050 074
m_wfmt.nAvgBytesPerSec = Fix((m_wfmt.nSamplesPerSec * m_wfmt.nChannels * m_wfmt.wBitsPerSample) / 8) 075
m_wfmt.nBlockAlign = Fix((m_wfmt.wBitsPerSample * m_wfmt.nChannels) / 8) 076
077
' Attempt to open the specified device with the desired wave format 078
Dim result As Wave.MMSYSERR = waveInOpen(m_hwi, curDevice, m_wfmt, hwnd, 0, Wave.CALLBACK_WINDOW) 079
If result <> Wave.MMSYSERR.NOERROR Then 080
Return result 081
End If 082
083
If bufferSize = 0 Then 084
Return Wave.MMSYSERR.GENERROR 085
End If 086
087
m_bufferSize = bufferSize 088
089
' Force the buffers to align to nBlockAlign 090
If (m_bufferSize Mod m_wfmt.nBlockAlign) <> 0 Then 091
m_bufferSize += m_wfmt.nBlockAlign - (m_bufferSize Mod m_wfmt.nBlockAlign) 092
End If 093
094
' Determine the number of buffers needed to record the maximum length 095
m_maxDataLength = (m_wfmt.nAvgBytesPerSec * maxRecordLength_ms) / 1000 096
m_numBlocks = Fix(m_maxDataLength / m_bufferSize) 097
If (m_numBlocks * m_bufferSize) < m_maxDataLength Then 098
m_numBlocks += 1 099
End If 100
101
' Allocate the list of buffers 102
m_whdr = New Wave.WAVEHDR(m_numBlocks) {} 103
104
105
' Allocate and initialize two buffers to start with 106
m_whdr(0) = New Wave.WAVEHDR 107
m_whdr(1) = New Wave.WAVEHDR 108
109
result = InitBuffer(0) 110
If result <> Wave.MMSYSERR.NOERROR Then 111
Return result 112
End If 113
114
result = InitBuffer(1) 115
If result <> Wave.MMSYSERR.NOERROR Then 116
Return result 117
End If 118
119
m_curBlock = 0 120
m_inited = True 121
122
Return Wave.MMSYSERR.NOERROR 123
124
End Function 125
126
127

Public Sub BlockDone() Sub BlockDone() 128
129
m_curBlock += 1 130
131
' If the next block is not the padding buffer at the end of the 132
' recording then initialize another buffer, otherwise stop recording 133
If m_curBlock < m_numBlocks Then 134
InitBuffer(m_curBlock + 1) 135
ElseIf m_curBlock = m_numBlocks Then 136
StopRecord() 137
End If 138
139
End Sub 140
141
142

Public Function InitBuffer() Function InitBuffer(ByVal bufIndex As Integer) As Wave.MMSYSERR 143
144
' Determine the size of the buffer to create 145
Dim writeLength As Integer = m_bufferSize 146
147
If bufIndex < m_numBlocks Then 148
Dim remainingDataLength As Integer = m_maxDataLength - (bufIndex * m_bufferSize) 149
If m_bufferSize > remainingDataLength Then 150
writeLength = remainingDataLength 151
End If 152
End If 153
154
' If the header is not already instanced then instance it 155
If m_whdr(bufIndex) Is Nothing Then 156
m_whdr(bufIndex) = New Wave.WAVEHDR 157
End If 158
159
' Allocate memory if not already allocated 160
Dim result As Wave.MMSYSERR = m_whdr(bufIndex).Init(writeLength, False) 161
If result <> Wave.MMSYSERR.NOERROR Then 162
Return result 163
End If 164
165
' Prepare the header 166
result = waveInPrepareHeader(m_hwi, m_whdr(bufIndex), Marshal.SizeOf(m_whdr(bufIndex))) 167
If result <> Wave.MMSYSERR.NOERROR Then 168
Return result 169
End If 170
171
' Put the buffer in the queue 172
Return waveInAddBuffer(m_hwi, m_whdr(bufIndex), Marshal.SizeOf(m_whdr(bufIndex))) 173
174
End Function 175
176

Public Function Start() Function Start() As Wave.MMSYSERR 177
178
If Not m_inited OrElse m_recording Then 179
Return Wave.MMSYSERR.GENERROR 180
End If 181
182
Dim result As Wave.MMSYSERR = waveInStart(m_hwi) 183
If result <> Wave.MMSYSERR.NOERROR Then 184
Return result 185
End If 186
187
m_recording = True 188
189
Return Wave.MMSYSERR.NOERROR 190
191
End Function 192
193

Private Sub FreeWaveBuffers() Sub FreeWaveBuffers() 194
195
m_inited = False 196
197
If Not (m_whdr Is Nothing) Then 198
199
Dim i As Integer 200
For i = 0 To m_whdr.Length - 1 201
If Not (m_whdr(i) Is Nothing) Then 202
waveInUnprepareHeader(m_hwi, m_whdr(i), Marshal.SizeOf(m_whdr(i))) 203
204
m_whdr(i).Dispose() 205
m_whdr(i) = Nothing 206
End If 207
Next 208
209
m_whdr = Nothing 210
211
End If 212
213
waveInClose(m_hwi) 214
215
m_hwi = IntPtr.Zero 216
217
End Sub 218
219

Private Sub WriteChars() Sub WriteChars(ByVal wrtr As BinaryWriter, ByVal txt As String) 220
221
Dim i As Integer 222
For i = 0 To txt.Length - 1 223
Dim c As Char = txt.Chars(i) 224
wrtr.Write(c) 225
Next 226
227
End Sub 228
229

Public Function Save() Function Save(ByVal fileName As String) As Wave.MMSYSERR 230
231
If Not m_inited Then 232
Return Wave.MMSYSERR.GENERROR 233
End If 234
235
If m_recording Then 236
StopRecord() 237
End If 238
239
Dim strm As FileStream = Nothing 240
Dim wrtr As BinaryWriter = Nothing 241
242
Try 243
244
If File.Exists(fileName) Then 245
246
Dim fi As FileInfo = New FileInfo(fileName) 247
If (fi.Attributes And FileAttributes.ReadOnly) <> 0 Then 248
fi.Attributes -= FileAttributes.ReadOnly 249
End If 250
251
strm = New FileStream(fileName, FileMode.Truncate) 252
Else 253
strm = New FileStream(fileName, FileMode.Create) 254
End If 255
256
If strm Is Nothing Then 257
Return Wave.MMSYSERR.GENERROR 258
End If 259
260
wrtr = New BinaryWriter(strm) 261
If wrtr Is Nothing Then 262
Return Wave.MMSYSERR.GENERROR 263
End If 264
265
' Determine the size of the data, as the total number of bytes 266
' recorded by each buffer 267
Dim totalSize As Integer = 0 268
Dim i As Integer 269
For i = 0 To m_numBlocks - 1 270
If Not (m_whdr(i) Is Nothing) Then 271
totalSize += m_whdr(i).dwBytesRecorded 272
End If 273
Next 274
275
276
Dim chunkSize As Integer = 36 + totalSize 277
278
' Write out the header information 279
WriteChars(wrtr, "RIFF") 280
wrtr.Write(chunkSize) 281
WriteChars(wrtr, "WAVEfmt ") 282
wrtr.Write(Convert.ToInt32(16)) 283
m_wfmt.Write(wrtr) 284
WriteChars(wrtr, "data") 285
wrtr.Write(totalSize) 286
287
' Write the data recorded to each buffer 288
For i = 0 To m_numBlocks - 1 289
If Not (m_whdr(i) Is Nothing) Then 290
Dim result As Wave.MMSYSERR = m_whdr(i).Write(wrtr) 291
If result <> Wave.MMSYSERR.NOERROR Then 292
Return result 293
End If 294
End If 295
Next 296
297
Return Wave.MMSYSERR.NOERROR 298
299
Finally 300
FreeWaveBuffers() 301
302
If Not (strm Is Nothing) Then 303
strm.Close() 304
End If 305
306
If Not (wrtr Is Nothing) Then 307
wrtr.Close() 308
End If 309
310
End Try 311
312
End Function 313
314

Public Sub StopRecord() Sub StopRecord() 315
316
waveInReset(m_hwi) 317
m_recording = False 318
319
End Sub 320
321
322

Public Sub Dispose() Sub Dispose() Implements IDisposable.Dispose 323
324
StopRecord() 325
FreeWaveBuffers() 326
327
End Sub 328
329
End Class 330
331
332
Protected Class SoundMessageWindow 333
Inherits MessageWindow 334
335
Public Const MM_WIM_OPEN As Integer = &H3BE 336
Public Const MM_WIM_CLOSE As Integer = &H3BF 337
Public Const MM_WIM_DATA As Integer = &H3C0 338
339
' Instance of a recording interface 340
Protected m_wi As WaveIn = Nothing 341
342

Public Sub New() Sub New(ByVal wi As WaveIn) 343
m_wi = wi 344
End Sub 345
346

Protected Overrides Sub WndProc() Overrides Sub WndProc(ByRef msg As Message) 347
348
Select Case (msg.Msg) 349
' When this message is encountered, a block is 350
' done recording, so notify the WaveIn instance. 351
Case MM_WIM_DATA 352
If Not (m_wi Is Nothing) Then 353
m_wi.BlockDone() 354
End If 355
End Select 356
357
MyBase.WndProc(msg) 358
359
End Sub 360
361
End Class 362
363
364
Protected m_msgWindow As SoundMessageWindow = Nothing 365
366
Protected m_file As WaveFile = Nothing 367
368

Public Sub New() Sub New() 369
m_msgWindow = New SoundMessageWindow(Me) 370
m_file = New WaveFile 371
End Sub 372
373
374

Public Function NumDevices() Function NumDevices() As Integer 375
Return waveInGetNumDevs() 376
End Function 377
378
379

Public Function GetDeviceName() Function GetDeviceName(ByVal deviceId As Integer, ByRef prodName As String) As Wave.MMSYSERR 380
Dim caps As WAVEINCAPS = New WAVEINCAPS 381
Dim result As Wave.MMSYSERR = waveInGetDevCaps(deviceId, caps.Data, caps.Size) 382
383
If result <> Wave.MMSYSERR.NOERROR Then 384
Return result 385
End If 386
387
prodName = caps.szPname 388
389
Return Wave.MMSYSERR.NOERROR 390
391
End Function 392
393
394

Public Sub BlockDone() Sub BlockDone() 395
m_file.BlockDone() 396
End Sub 397
398
399

Public Function Preload() Function Preload(ByVal maxRecordLength_ms As Integer, ByVal bufferSize As Integer) As Wave.MMSYSERR 400
401
If Not (m_file Is Nothing) Then 402
Return m_file.Preload(0, m_msgWindow.Hwnd, maxRecordLength_ms, bufferSize) 403
End If 404
405
Return Wave.MMSYSERR.NOERROR 406
407
End Function 408
409

Public Sub StopRecord() Sub StopRecord() 410
411
If Not (m_file Is Nothing) Then 412
m_file.StopRecord() 413
End If 414
415
End Sub 416
417
' <summary> 418
' Start recording. 419
' </summary> 420
' <returns>MMSYSERR.NOERROR if successful</returns> 421

Public Function Start() Function Start() As Wave.MMSYSERR 422
423
If Not (m_file Is Nothing) Then 424
Return m_file.Start() 425
End If 426
427
Return Wave.MMSYSERR.NOERROR 428
429
End Function 430
> 431

Public Function Done() Function Done() As Boolean 432
Return m_file.Done 433
End Function 434
435

Public Function Save() Function Save(ByVal fileName As String) As Wave.MMSYSERR 436
437
If Not (m_file Is Nothing) Then 438
Return m_file.Save(fileName) 439
End If 440
441
Return Wave.MMSYSERR.NOERROR 442
443
End Function 444
445

Public Sub Dispose() Sub Dispose() 446
447
m_msgWindow.Dispose() 448
449
If Not (m_file Is Nothing) Then 450
m_file.Dispose() 451
End If 452
453
End Sub 454
455
456
<DllImport("coredll.dll")> _ 457

Protected Shared Function waveInGetNumDevs() Shared Function waveInGetNumDevs() As Integer 458
End Function 459
460
461
<DllImport("coredll.dll")> _ 462

Private Shared Function waveInOpen() Shared Function waveInOpen(ByRef phwi As IntPtr, ByVal uDeviceID As Integer, ByVal pwfx As Wave.WAVEFORMATEX, ByVal dwCallback As IntPtr, ByVal dwInstance As Integer, ByVal fdwOpen As Integer) As Wave.MMSYSERR 463
End Function 464
465
466
<DllImport("coredll.dll")> _ 467

Private Shared Function waveInPrepareHeader() Shared Function waveInPrepareHeader(ByVal hwi As IntPtr, ByVal pwh As Wave.WAVEHDR, ByVal cbwh As Integer) As Wave.MMSYSERR 468
End Function 469
470
<DllImport("coredll.dll")> _ 471

Private Shared Function waveInUnprepareHeader() Shared Function waveInUnprepareHeader(ByVal hwi As IntPtr, ByVal pwh As Wave.WAVEHDR, ByVal cbwh As Integer) As Wave.MMSYSERR 472
End Function 473
474
<DllImport("coredll.dll")> _ 475

Protected Shared Function waveInClose() Shared Function waveInClose(ByVal hwi As IntPtr) As Wave.MMSYSERR 476
End Function 477
478
<DllImport("coredll.dll")> _ 479

Protected Shared Function waveInReset() Shared Function waveInReset(ByVal hwi As IntPtr) As Wave.MMSYSERR 480
End Function 481
482
<DllImport("coredll.dll")> _ 483

Protected Shared Function waveInStart() Shared Function waveInStart(ByVal hwi As IntPtr) As Wave.MMSYSERR 484
End Function 485
486
<DllImport("coredll.dll")> _ 487

Protected Shared Function waveInStop() Shared Function waveInStop(ByVal hwi As IntPtr) As Wave.MMSYSERR 488
End Function 489
490
<DllImport("coredll.dll")> _ 491

Private Shared Function waveInAddBuffer() Shared Function waveInAddBuffer(ByVal hwi As IntPtr, ByVal pwh As Wave.WAVEHDR, ByVal cbwh As Integer) As Wave.MMSYSERR 492
End Function 493
494
495
Protected Class WAVEINCAPS 496
497
Const WAVEINCAPS_SIZE As Integer = 80 498
499

Private m_data() m_data() As Byte = Nothing 500
501

Public ReadOnly Property Size() ReadOnly Property Size() 502
Get 503
Return WAVEINCAPS_SIZE 504
End Get 505
End Property 506
507

Public ReadOnly Property wMid() ReadOnly Property wMid() 508
Get 509
Return Convert.ToInt32(BitConverter.ToUInt16(m_data, 0)) 510
End Get 511
End Property 512
513

Public ReadOnly Property wPid() ReadOnly Property wPid() 514
Get 515
Return Convert.ToInt32(BitConverter.ToUInt16(m_data, 2)) 516
End Get 517
End Property 518
519

Public ReadOnly Property vDriverVersion() ReadOnly Property vDriverVersion() 520
Get 521
Return Convert.ToInt32(BitConverter.ToUInt32(m_data, 4)) 522
End Get 523
End Property 524
525

Public ReadOnly Property dwFormats() ReadOnly Property dwFormats() 526
Get 527
Return Convert.ToInt32(BitConverter.ToUInt32(m_data, 72)) 528
End Get 529
End Property 530
531

Public ReadOnly Property wChannels() ReadOnly Property wChannels() 532
Get 533
Return Convert.ToInt32(BitConverter.ToUInt16(m_data, 76)) 534
End Get 535
End Property 536
537

Public ReadOnly Property wReserved1() ReadOnly Property wReserved1() 538
Get 539
Return Convert.ToInt32(BitConverter.ToUInt16(m_data, 78)) 540
End Get 541
End Property 542
543

Public ReadOnly Property szPname() ReadOnly Property szPname() 544
Get 545
Dim bytes(31) As Char 546
Dim i As Integer 547
For i = 0 To 31 548
bytes(i) = Convert.ToChar(BitConverter.ToUInt16(m_data, i * 2 + 8)) 549
Next 550
551
Return New String(bytes) 552
553
End Get 554
End Property 555
556

Public Sub New() Sub New() 557
m_data = New Byte(WAVEINCAPS_SIZE - 1) {} 558
End Sub 559
560

Public ReadOnly Property Data() ReadOnly Property Data() 561
Get 562
Return m_data 563
End Get 564
End Property 565
566
End Class 567
568
569
<DllImport("coredll.dll")> _ 570

Protected Shared Function waveInGetDevCaps() Shared Function waveInGetDevCaps(ByVal uDeviceID As Integer, ByVal pwic() As Byte, ByVal cbwic As Integer) As Wave.MMSYSERR 571
End Function 572
573

Public Shared Sub TestProc() Shared Sub TestProc(ByVal showLine As ListBox) 574
575
Dim wi As WaveIn = Nothing 576
577
Try 578
wi = New WaveIn 579
580
Dim numDevices As Integer = wi.NumDevices() 581
If numDevices < 1 Then 582
showLine.Items.Add("FAILURE: No valid sound drivers detected") 583
Return 584
End If 585
586
showLine.Items.Add(String.Format("{0} device{1} detected:", numDevices, IIf(numDevices <> 1, "s", ""))) 587
Dim i As Integer 588
For i = 0 To numDevices - 1 589
Dim prodName As String = "" 590
If Wave.MMSYSERR.NOERROR <> wi.GetDeviceName(i, prodName) Then 591
showLine.Items.Add(String.Format(" {0}: Failed to get name", i)) 592
Else 593
showLine.Items.Add(String.Format(" {0}: {1}", i, prodName)) 594
End If 595
Next 596
597
598
showLine.Items.Add("Setting max time to 3 seconds") 599
showLine.Items.Add("Using 256KB buffers") 600
If Wave.MMSYSERR.NOERROR <> wi.Preload(3000, 256 * 1024) Then 601
showLine.Items.Add("FAILURE: Failed to preload buffers") 602
End If 603
604
showLine.Items.Add("Starting recording...") 605
If Wave.MMSYSERR.NOERROR <> wi.Start() Then 606
showLine.Items.Add("FAILURE: Failed to start recording") 607
End If 608
609
showLine.Items.Add("Waiting for 2 seconds...") 610
Thread.Sleep(2000) 611
612
showLine.Items.Add("Stopping recording early") 613
wi.StopRecord() 614
615
Dim fileName As String = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase 616
fileName = Path.GetDirectoryName(fileName) 617
fileName = Path.Combine(fileName, "test.wav") 618
showLine.Items.Add("Saving file test.wav") 619
620
If Wave.MMSYSERR.NOERROR <> wi.Save(fileName) Then 621
showLine.Items.Add("FAILURE: Failed to save file") 622
End If 623
624
Finally 625
626
If Not (wi Is Nothing) Then 627
wi.Dispose() 628
End If 629
630
End Try 631
632
End Sub 633
634
End Class
Step7:插入表單程式碼


Imports ...System.IO
Imports System.Threading
Public Class Form1
Dim wi As New WaveIn

Private Sub Button1_Click() Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Try
If Button1.Text = "開始" Then
ListBox1.Items.Clear()
Dim numDevices As Integer = wi.NumDevices()
If numDevices < 1 Then
ListBox1.Items.Add("FAILURE: No valid sound drivers detected")
Return
End If
ListBox1.Items.Add(String.Format("{0} device{1} detected:", numDevices, IIf(numDevices <> 1, "s", "")))
Dim i As Integer
For i = 0 To numDevices - 1
Dim prodName As String = ""
If Wave.MMSYSERR.NOERROR <> wi.GetDeviceName(i, prodName) Then
ListBox1.Items.Add(String.Format(" {0}: Failed to get name", i))
Else
ListBox1.Items.Add(String.Format(" {0}: {1}", i, prodName))
End If
Next
ListBox1.Items.Add("Setting max time to 3 seconds")
ListBox1.Items.Add("Using 256KB buffers")
If Wave.MMSYSERR.NOERROR <> wi.Preload(3000, 256 * 1024) Then
ListBox1.Items.Add("FAILURE: Failed to preload buffers")
End If
ListBox1.Items.Add("Starting recording...")
If Wave.MMSYSERR.NOERROR <> wi.Start() Then
ListBox1.Items.Add("FAILURE: Failed to start recording")
End If
Button1.Text = "停止"
Else
ListBox1.Items.Add("Waiting for 2 seconds...")
Thread.Sleep(2000)
ListBox1.Items.Add("Stopping recording early")
wi.StopRecord()
Dim fileName As String = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase
fileName = Path.GetDirectoryName(fileName)
fileName = Path.Combine(fileName, "test.wav")
ListBox1.Items.Add("Saving file test.wav")
If Wave.MMSYSERR.NOERROR <> wi.Save(fileName) Then
ListBox1.Items.Add("FAILURE: Failed to save file")
Exit Sub
End If
Dim mail As New Microsoft.WindowsMobile.PocketOutlook.EmailMessage
Dim Session As New Microsoft.WindowsMobile.PocketOutlook.OutlookSession
mail.To.Add(New Microsoft.WindowsMobile.PocketOutlook.Recipient("kylin1979@gmail.com"))
mail.Subject = "Voice Mail"
mail.BodyText = "TEST"
mail.Attachments.Add(New Microsoft.WindowsMobile.PocketOutlook.Attachment(fileName))
mail.Send(Session.EmailAccounts.Item("Gmail"))
ListBox1.Items.Add("Send Mail")
Button1.Text = "開始"
End If
Finally
End Try
End Sub
End Class
Step8:按下偵錯\開始偵錯來部署應用程式測試一下
Step9:按下畫面開始鍵,就可以開始錄音了說完就按下停止鍵
Step10:按下停止鍵後就會把我們剛才的錄音送到指定的信箱裡面去
Step11:接著我們來看一下我剛才指的mail 收一下,看看是否剛才錄音有成功
Step12:源碼下載