> >*!* Q291535: HOWTO: 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 > > >>Tracy,