I have extended my PRINTERS class to include a DIALOG to select a printer. I decided to include an option in the dialog to refresh the list of available printers. However if I try to use that option I get an error. The error appears to be that one (at least) of the controls on my dialog doesn't have a logical value in its update property. At least that's my guess from looking at error.log.
I have reproduced the fault with the following cut down code:
Code: Select all
#include "hbclass.ch"
#include "FiveLinux.ch"
STATIC oWnd
FUNCTION Main( xHomeDir, xDataDir)
PUBLIC oPRINTERS
oPRINTERS := PRINTERS():New()
DEFINE WINDOW oWnd TITLE ( "Test Dialog Update" ) MENU BldInMenu()
ACTIVATE WINDOW oWnd MAXIMIZED
RETURN nil
FUNCTION BldInMenu()
LOCAL lomMenu
MENU lomMenu
MENUITEM "_File"
MENU
MENUITEM "_Get Printers" ACTION TestPrinters()
MENUITEM "e_Xit" ACTION oWnd:End()
ENDMENU
ENDMENU
RETURN lomMenu
FUNCTION TestPrinters()
LOCAL sPrinter
LOCAL sPort
IF oPRINTERS:Select( "Test Document", @sPrinter, @sPort )
MsgInfo( "Print on " + sPrinter + " on port " + sPort )
ELSE
MsgInfo( "Printing cancelled" )
ENDIF
RETURN nil
CLASS PRINTERS
DATA aNames /** array of printer names */
DATA aPorts /** array of printer ports */
DATA iCount /** number of printers installed */
DATA sDefault /** name of default printer */
DATA iDefault /** number of default printer - index into aNames and aPorts */
DATA lDefault /** is there a default printer */
DATA lExists /** is any printer defined */
DATA lOSQueried /** has the OS been queried about available printers */
DATA brw_PRINTER_LIST /** Printer List BROWSE object on Printer Selection DIALOG */
DATA btn_PRINT /** Print button on Printer Selection DIALOG */
METHOD New( lGetList ) CONSTRUCTOR
METHOD GetList()
METHOD Select( psJobName, psPrinter, psPort )
ENDCLASS
METHOD New( plGetList ) CLASS PRINTERS
/** _syntax: PRINTERS():New( [<lGetList>] )
_arguments:
<lGetList> a logical value
If .T. the operating system is queried and printer lists and defaults are set as part of the object's initialisation.
Defaults to .T.
_returns: the created PRINTERS object
_description: see METHOD GetList() for a description of how the operating system is queried */
IF PCOUNT() < 1
lGetList := .T.
ELSE
lGetList := plGetList
ENDIF
::lOSQueried := .F.
IF lGetList
::GetList()
ENDIF
RETURN self
METHOD GetList() CLASS PRINTERS
/** _syntax: <PRINTERS_object>:GetList()
_arguments: none
_returns: nil
_description: Obtains information on installed printers from the operating system by RUNning lpstat -s > lpstat.txt.
Opens the redirected output of the above command and parses that file building a list of printernames (in ::aNames)
and ports (in ::aPorts).
Retrieves the name of the default printer (in ::sDefault) and determines its position (in ::iDefault)
If there is no default printer ::lDefault is set to .F.
Determines if there are any printers installed (in ::lExists) and how many are installed (in ::iCount) */
LOCAL iFileHandle /** file handle for reading output of lpstat command */
LOCAL sPrinterLine /** line buffer for reading output of lpstat command */
LOCAL sTest /** buffer for testing format of lines of lpstat command output */
LOCAL iEndOffset /** work variable for splitting out printer name and port data */
LOCAL lDefaultFound /** work variable for flagging that default printer name has been found */
LOCAL ii /** work variable loop counter */
::aNames := ARRAY( 0 )
::aPorts := ARRAY( 0 )
::iCount := 0
::sDefault := ""
::iDefault := 0
::lDefault := .F.
::lExists := .F.
RUN lpstat -s > lpstat.txt
iFileHandle := FOpen( "lpstat.txt" )
DO WHILE HB_FReadLine( iFileHandle, @sPrinterLine, CHR(10) ) = 0
sTest := SUBSTR( sPrinterLine, 1, 11 )
IF sTest = "device for "
sTest := SUBSTR( sPrinterLine, 12 )
iEndOffset := AT( ": ", sTest )
IF iEndOffset > 0
AAdd( ::aNames, ALLTRIM( SUBSTR( sTest, 1, iEndOffset - 1 ) ) )
AAdd( ::aPorts, SUBSTR( sTest, iEndOffset + 2 ) )
::iCount += 1
::lExists := .T.
ENDIF
ELSE
sTest := SUBSTR( sPrinterLine, 1, 27 )
IF sTest = "system default destination:"
::sDefault := ALLTRIM( SUBSTR( sPrinterLine, 28 ) )
::lDefault := .T.
ENDIF
ENDIF
ENDDO
FClose( iFileHandle )
IF ::lDefault
FOR ii = 1 TO ::iCount
IF ::aNames[ii] = ::sDefault
::iDefault := ii
EXIT
ENDIF
NEXT
ENDIF
::lOSQueried := .T.
RETURN nil
METHOD Select( psJobName, psPrinter, psPort )
/** _syntax: <PRINTERS_object>:Select( <JobName>, @<Printer, @<Port> )
_parameters: <JobName> a string
Name of the job(s) to be printed.
Gets displayed in the title of the dialog
<Printer> a string (passed by reference)
This gets updated with the name of the selected printer
<Port> a string (passed by reference)
This gets updated with the port of the selected printer
_returns: a logical value.
.T. indicates that the user has selected a printer and wishes to proceed
.F. indicates that the user wishes to cancel
_description: a dialog enabling the user to select a printer for (a) print job(s) or to cancel the print request
A printer can be selected by either:
double left clicking on it,
or highlighting it and clicking on the print button
The function gives an informational message if no printers are installed.
The function checks that a printer list has been created, if not it invokes ::GetList()
The user can get the printer list refreshed by clicking on the Refresh button */
LOCAL dlg_SELECT_PRINTER /** Select Printer Dialog */
LOCAL sTitle /** Dialog Title */
LOCAL lRetCode /** Function Return Code */
IF !::lOSQueried
::GetList()
ENDIF
sTitle := "Select Printer for Printing " + psJobName
DEFINE DIALOG dlg_SELECT_PRINTER TITLE sTitle SIZE 800, 500
IF ::iCount < 1
@ 30, 10 SAY "No printers currently installed"
ELSE
@ 3, 1 BROWSE ::brw_PRINTER_LIST ;
FIELDS ::aNames[::brw_PRINTER_LIST:nAt], ::aPorts[::brw_PRINTER_LIST:nAt] ;
HEADERS "Printer", "Port" SIZE 550, 400 OF dlg_SELECT_PRINTER UPDATE
::brw_PRINTER_LIST:bLDblClick := { | nRow, nCol | ::btn_PRINT:Click() }
BrwSetColWidths( ::brw_PRINTER_LIST , { 200, 350 } )
::brw_PRINTER_LIST:SetArray( ::aNames )
ENDIF
@ 30, 600 BUTTON ::btn_PRINT PROMPT "Print" WHEN ::lExists ;
ACTION ( psPrinter := ::aNames[::brw_PRINTER_LIST:nAt], psPort := ::aPorts[::brw_PRINTER_LIST:nAt], lRetCode := .T., dlg_SELECT_PRINTER:End() ) ;
PIXEL OF dlg_SELECT_PRINTER
@ 90, 600 BUTTON "Refresh" ACTION ( ::GetList(), dlg_SELECT_PRINTER:Update() ) PIXEL OF dlg_SELECT_PRINTER
@ 240, 600 BUTTON "Cancel" ACTION ( lRetCode := .F., dlg_SELECT_PRINTER:End() ) PIXEL OF dlg_SELECT_PRINTER
ACTIVATE DIALOG dlg_SELECT_PRINTER CENTERED
RETURN lRetCode
FUNCTION BrwSetColWidths( oBrw, aWidths )
iLastWidth := LEN( aWidths )
FOR iCount = 1 TO iLastWidth
oBrw:aColumns[iCount]:nWidth := aWidths[iCount]
NEXT
RETURN nil
Code: Select all
Application
===========
Path and name: ./PRINTERS (32 bits)
Time from start: 0 hours 0 mins 16 secs
Error occurred at: 06/15/08, 21:06:19
Error description: Error BASE/1066
Argument error: conditional
Args:
[ 1] = U nil
Stack Calls
===========
Called from (b)TWINDOW(79)
Called from AEVAL(0)
Called from (b)TWINDOW:TWINDOW(79)
Called from TDIALOG:UPDATE(0)
Called from (b)PRINTERS:SELECT(186)
Called from TBUTTON:CLICK(149)
Called from TBUTTON:HANDLEEVENT(158)
Called from _FLH(241)
Called from WINRUN(0)
Called from TDIALOG:ACTIVATE(71)
Called from PRINTERS:SELECT(188)
Called from TESTPRINTERS(34)
Called from (b)BLDINMENU(22)
Called from TMENU:COMMAND(60)
Called from TWINDOW:HANDLEEVENT(182)
Called from _FLH(241)
Called from WINRUN(0)
Called from TWINDOW:ACTIVATE(134)
Called from MAIN(11)
Variables in use
================
Procedure Type Value
==========================
(b)TWINDOW
Param 1: O Class: TSCROLLBAR
Param 2: N 2
Local 1: U nil
Local 2: U nil
Local 3: N 0
AEVAL
Param 1: A Len: 6
Param 2: B {|| ... }
(b)TWINDOW:TWINDOW
Param 1: O Class: TDIALOG
TDIALOG:UPDATE
(b)PRINTERS:SELECT
Param 1: O Class: TBUTTON
TBUTTON:CLICK
Local 1: O Class: TBUTTON
TBUTTON:HANDLEEVENT
Param 1: N 1
Param 2: N 0
Param 3: N 0
Local 1: O Class: TBUTTON
_FLH
Param 1: N 1
Param 2: N 0
Param 3: N 0
Param 4: N 21
Local 1: O Class: TBUTTON
WINRUN
Local 1: U nil
Local 2: U nil
Local 3: U nil
Local 4: U nil
TDIALOG:ACTIVATE
Param 1: L .T.
Param 2: U nil
Param 3: U nil
Param 4: U nil
Param 5: L .T.
Param 6: U nil
Local 1: O Class: TDIALOG
Local 2: N 7
PRINTERS:SELECT
Param 1: C "Test Document"
Param 2: U nil
Param 3: U nil
Local 1: O Class: PRINTERS
Local 2: O Class: TDIALOG
Local 3: C "Select Printer for Printing Test Document"
Local 4: U nil
TESTPRINTERS
Local 1: U nil
Local 2: U nil
(b)BLDINMENU
Param 1: O Class: TMENUITEM
TMENU:COMMAND
Param 1: N 135782784
Local 1: O Class: TMENU
Local 2: O Class: TMENUITEM
TWINDOW:HANDLEEVENT
Param 1: N 3
Param 2: N 135782784
Param 3: N 0
Local 1: O Class: TWINDOW
Local 2: U nil
_FLH
Param 1: N 3
Param 2: N 135782784
Param 3: N 0
Param 4: N 1
Local 1: O Class: TWINDOW
WINRUN
Local 1: U nil
Local 2: U nil
Local 3: U nil
Local 4: U nil
Local 5: U nil
Local 6: U nil
Local 7: U nil
TWINDOW:ACTIVATE
Param 1: U nil
Param 2: U nil
Param 3: U nil
Param 4: L .T.
Param 5: U nil
Local 1: O Class: TWINDOW
MAIN
Local 1: U nil
Local 2: U nil
Linked RDDs
===========
DBF
DBFFPT
DBFNTX
DBFBLOB
DataBases in use
================
Classes in use:
===============
1 HASHENTRY
2 HBCLASS
3 HBOBJECT
4 PRINTERS
5 TWINDOW
6 TMENU
7 TMENUITEM
8 TDIALOG
9 TCONTROL
10 TWBROWSE
11 TWBCOLUMN
12 TSCROLLBAR
13 TBUTTON
14 ERROR
Memory Analysis
===============
24 Static variables
Dynamic memory consume:
Actual Value: 0 bytes
Highest Value: 0 bytes
Thanks
Doug
(xProgrammer)