*!* Q291535: How To Find installed modems using Microsoft Visual FoxPro
*!* This article use Mscom32.ocx to detect if any modems are installed
*!* and reports the COM port it is using.
*!*
Public oform1
oform1=Createobject([MODEMFORM])
oform1.Show
Return
**************************************************
*
Define Class MODEMFORM As Form
Height = 128
Width = 160
DoCreate = .T.
AutoCenter = .T.
BorderStyle = 2
Caption = [Com Port Test]
MaxButton = .F.
MinButton = .F.
Visible = .F.
AlwaysOnTop = .T.
BackColor = Rgb(0,0,255)
Name = [Form1]
*-- Form array that stores information about available machine com ports.
Dimension acommports[1,2]
Add Object ocxCOMM As MSCOMM_OCX With ;
Top = 101, ;
Left = 72, ;
Height = 21, ;
Width = 38, ;
Name = [ocxCOMM]
Add Object lblava_ports As Label With ;
AutoSize = .T., ;
FontName = [Verdana], ;
Caption = [Available COM Ports:], ;
Height = 16, ;
Left = 14, ;
Top = 15, ;
Width = 133, ;
ForeColor = Rgb(255,255,255), ;
BackColor = Rgb(0,0,255), ;
Name = [lblAVA_PORTS]
Add Object command1 As CommandButton With ;
Top = 78, ;
Left = 11, ;
Height = 27, ;
Width = 138, ;
FontName = [Tahoma], ;
Caption = [\<Test Ports for Modem], ;
Name = [Command1]
Add Object timer1 As Timer With ;
Top = 105, ;
Left = 12, ;
Height = 23, ;
Width = 23, ;
Enabled = .F., ;
Interval = 1500, ;
Name = [Timer1]
Add Object lblports As Label With ;
FontName = [Verdana], ;
Alignment = 2, ;
Caption = [lblPORTS], ;
Height = 17, ;
Left = 42, ;
Top = 46, ;
Width = 77, ;
ForeColor = Rgb(255,255,255), ;
BackColor = Rgb(0,0,255), ;
Name = [lblPORTS]
Procedure WaitForResponse
*~ This method loops for the specified
*~ amount of time calling DOEVENTS().
*~ This allows time for the modem to respond to the requests.
Lparameters lnDelayInSeconds
Local lnStartTime
lnStartTime = Seco()
Do While Seco() <= (lnStartTime + lnDelayInSeconds) ;
AND Not Seco() < lnStartTime
DoEvents()
Enddo
Endproc
Procedure Error
Lparameters nError, cMethod, nLine
*~ In THIS.INIT we loop through 10 COM ports,
*~ attempting to open each with the MSCOMM32.OCX control.
*~ We trap the errors here and if it's an OLE error,
*~ nError will be 1429 (this came from the control).
If Inlist(nError, 1429, 1426)
*~ Populate an error array and check the OLE message.
Local aErrArray(1)
Aerror(aErrArray)
*~ If the error msg was "Invalid Port Number"
*~ the control tried to open a port that either
*~ doesn't exist or has nothing on it.
*~ Set a global var (glBadPort) to .T.
*~ this var is used in THIS.INIT loop.
If [INVALID PORT NUMBER] $ Upper(aErrArray(3)) Or ;
[UNKNOWN OLE STATUS CODE] $ Upper(aErrArray(3))
glBadPort = .T.
Endif
Else
*~ We experienced a non - OLE error. Report it.
Messagebox([Error #: ] + Allt(Str(nError)) + Chr(13) + ;
[Message: ] + Message() + Chr(13) + ;
[Line with error: ] + Allt(Str(nLine)) + Chr(13) + ;
[Method: ] + cMethod)
Endif
Endproc
Procedure Init
*~ Var that indicates a non-existent or inactive COM port.
*~ This var is flipped by THISFORM.ERROR()
_vfp.AutoYield=.F.
Public glBadPort
glBadPort = .F.
Local i, lcGoodPorts
*~ lcGoodPorts used to build string displayed
*~ in THISFORM.lblPORTS.CAPTION
lcGoodPorts = []
*~ Set initial properties of MSCOMM .OCX
With This.ocxCOMM
.RThreshold = 1
.SThreshold = 1
.Settings = [9600,n,8,1]
.RTSEnable = .F.
.InputLen = 0
Endwith
*~ Loop through 10 ports, trying to open each.
For i = 1 To 10
With This.ocxCOMM
.CommPort = i
.PortOpen = .T.
*~ glBadPort set to .T. by THIS.ERROR if the # was bad.
If !glBadPort
*~ Expand the array if i>1. The array is initally 1 row.
If i > 1
Dimension This.acommports[ALEN(THIS.aCommPorts,1)+1,2]
Endif
*~ Valid port, so store the port # to the first column
*~ and a blank to the second column of the current row
*~ in THISFORM.aCommPorts. We will use this space later
*~ in THISFORM.COMMAND1.CLICK() to store return value
*~ communication with the port.
*~ Also store the port # to the lcGoodPorts variable.
This.acommports(i,1) = i
This.acommports(i,2) = []
lcGoodPorts = lcGoodPorts + Allt(Str(i)) + [ ]
Endif
*~ Reset glBadPort for next loop.
glBadPort = .F.
*~ Close the port if it was opened to avoid error on next try.
If .PortOpen
.PortOpen = .F.
Endif
Endwith
Endfor
*~ List the valid ports in THISFORM.lblPORTS.CAPTION
This.lblports.Caption = lcGoodPorts
Release glBadPort
Endproc
Procedure ocxCOMM.OnComm
*** ActiveX Control Event ***
*~ CommEvent = 2 means the control received data.
*~ Store the data the control received to
*~ the appropriate array row/column.
*~ The row/column to store to is determined by
*~ global variable "gnPortNum" which is set in the
*~ thisform.command1.click() loop.
If This.commevent = 2
Thisform.acommports(gnPortNum,2) = ;
THISFORM.acommports(gnPortNum,2) + This.Input
Endif
Endproc
Procedure command1.Error
Lparameters nError, cMethod, nLine
*~ Trap OLE error from the COMM .OCX
*~ nError = 1429: we experienced an OLE error. This may
*~ be because we tried to open or communicate via
*~ the port and there is a non-standard object attached to
*~ it (such as a printer). Do nothing here; it's not a modem
*~ since we cannot open AND communicate with it.
*~ You may want to enhance this error trap.
If Inlist(nError, 1429, 1426)
Else
*~ We experienced a non - OLE error. Report it.
Messagebox([Error #: ] + Allt(Str(nError)) + Chr(13) + ;
[MESSAGE: ] + Message() + Chr(13) + ;
[LINE WITH ERROR: ] + Allt(Str(nLine)) + Chr(13) + ;
[Method: ] + cMethod)
Endif
Endproc
Procedure command1.Click
*~ gnPortNum is used in the ONCOMM event of the .OCX
Public gnPortNum
Local i, lnModemPort
lnModemPort = 0
With Thisform
*~ Loop through the form array...
For i = 1 To Alen(.acommports,1)
gnPortNum = i
Wait Window [Testing COM ] + ;
ALLT(Str(.acommports(i,1))) + [...] Nowait Noclear
If .ocxCOMM.PortOpen
.ocxCOMM.PortOpen = .F.
Endif
*~ Open the port and send standard Hayes-compatible
*~ commands to it. These commands first reset ([ATZ])
*~ the modem if it's there, then tell it to return
*~ an ID string ([ATI0]). The return string from a modem
*~ will contain an [OK], which is how we can tell it's a modem.
.ocxCOMM.CommPort = .acommports(i,1)
.ocxCOMM.PortOpen = .T.
.ocxCOMM.Output = [ATZ] + Chr(13)
.WaitForResponse(2)
.ocxCOMM.Output = [ATI0] + Chr(13)
.WaitForResponse(2)
Wait Clear
Endfor
Wait Window [Compiling Results...] Nowait Noclear
.timer1.Enabled = .T.
Endwith
Endproc
Procedure timer1.Timer
*~ Clear the variable used in the ONCOMM event
*~ of the .OCX.
Rele gnPortNum
Local i, lnModemPort
lnModemPort = 0
*~ Disable this timer so the code only runs once.
This.Enabled = .F.
With Thisform
*~ Close the port if it is open.
.ocxCOMM.PortOpen = .F.
*~ Loop through the completed array.
*~ If the first element is <> 0,
*~ check the second in the row for an "OK".
*~ If present, that means the port has a modem.
For i = 1 To Alen(.acommports,1)
If .acommports(i,1) <> 0
If [OK] $ Upper(.acommports(i,2))
*~ Modem found, exit the loop.
lnModemPort = .acommports(i,1)
Exit
Endif
Endif
Next i
Endwith
*~ Report to user.
Wait Clear
If lnModemPort <> 0
Messagebox([Modem Found On COM ] + Allt(Str(lnModemPort)),0,[])
Else
Messagebox([No Modem Found.] ,0,[])
Endif
Endproc
Enddefine
*
*-- EndDefine: form1
**************************************************
Define Class MSCOMM_OCX As OleControl
OleClass = [MSCOMMLib.MSComm.1]
Enddefine