Estoy intentando hacer funcionar un ejemplo que usa la clase TCRW de Tom Groeger, pero no lo consigo. Si bien se abre la ventana, arroja el error "Error BASE/1004 No exported method: PEOPENPRINTJOB".
Agradecería una ayuda.
El código completo, incluyendo la clase TCRW, es el siguiente:
- Code: Select all Expand view
- #INCLUDE "fivewin.CH"
#include "STRUCT.CH"
#define FW_LEAN_AND_MEAN
#define CallDll fwcalldll
#define GetProcAddress GetProcAdd
#define TRUE 1
#define FALSE 0
STATIC oWnd, oCrystal
REQUEST DBFCDX, DBFFPT
FUNCTION Main()
oCrystal := TCCRPE():NEW()
DEFINE WINDOW oWnd MENU CreaMenu() MDI
ACTIVATE WINDOW oWnd VALID (oCrystal:PECloseEngine(),.T.)
RETURN (.T.)
FUNCTION CreaMenu()
LOCAL oMenu
MENU oMenu
MenuItem "Prueba" Action RunReport()
ENDMENU
RETURN (oMenu)
FUNCTION RunReport()
LOCAL oVentHija, cReportName, hReport, oCrystal
cReportName := "C:\Crystal7fw\listado.rpt"
//cGetFile("*.rpt","Choose Report")
DEFINE Window oVentHija MDICHILD OF oWnd
oCrystal:PEOpenPrintJob(cReportName)
oCrystal:PeOutputToWindow( oVentHija )
oCrystal:PESetTabLocation("C:\Crystal7fw\provin.dbf")
ACTIVATE WINDOW oVentHija ON INIT (oCrystal:PeStartPrintJob(), hReport := oCrystal:PEGetWindowHandle(),WndSetSize(hReport,oVentHija:nWidth-7,oVentHija:nHeight-8,.T.));
ON PAINT (WndSetSize(hReport,oVentHija:nWidth-7,oVentHija:nHeight-8,.T.));
VALID (oCrystal:PEClosePrintJob(),.T.)
RETURN (.T.)
// ===========================================================================
// TCRW.PRG (C) Tom Groeger 1998
// ===========================================================================
//
// 16 & 32 Bit Wrapper Classes for Crystal Reports gives you access to
// Crystal Reports 32Bit Dll. The class constructor automatically checks if
// 32Bit Dll's are available, and falls back to 16Bit if not.
// Thanks to Matthew Cullen/Adsystems for his help !
//
// downloaded from http://www.fivedb.com
//
// ===========================================================================
// ==========================================================================
// CLASS TCRW // Crystal Reports 16/32Bit Wrapper
// ==========================================================================
CREATE CLASS TCCRPE
VAR hDll AS NUMERIC
VAR l32 AS LOGICAL
VAR nJobHandle
VAR lError
VAR cReport
VAR oJobInfo
VAR oTabLocation
MESSAGE New METHOD NEW_ CONSTRUCTOR
MESSAGE FreeLibrary METHOD FREECRPE_
MESSAGE GetModuleHandle METHOD GETMOD_
MESSAGE PEOpenEngine METHOD PEOPEN_
MESSAGE PEErrorText METHOD ERRORT_
MESSAGE PEGetErrorCode METHOD ERRORN_
MESSAGE PEGetHandleString METHOD GETSTR_
MESSAGE PEOpenPrintJob METHOD OPENJOB_
MESSAGE PEOutputToWindow METHOD OUTPUTW_
MESSAGE PEPrintWindow METHOD PRINTWND_
MESSAGE PEOutToPrinter METHOD OUTPUTP_
MESSAGE PEStartPrintJob METHOD STARTPR_
MESSAGE PEGetWindowHandle METHOD GETHWND_
MESSAGE PEGetJobStatus METHOD GETJOBS_
MESSAGE PESetSelFormula METHOD SETSELE_
MESSAGE PEGetSelFormula METHOD GETSELE_
MESSAGE PECheckSelFormula METHOD CHECKSEL_
MESSAGE PESetFormula METHOD SETFORM_
MESSAGE PECheckFormula METHOD CHECKFOR_
MESSAGE PEGetNTables METHOD GETNTAB_
MESSAGE PEGetTabLocation METHOD GETTLOC_
MESSAGE PESetTabLocation METHOD SETTLOC_
MESSAGE PEGetSqlQuery METHOD GETSQLQ_
MESSAGE PESetSqlQuery METHOD SETSQLQ_
MESSAGE PETestNTable METHOD TESTTAB_
MESSAGE PEIsPrintFinished METHOD ISPRTRDY_
MESSAGE PEClosePrintJob METHOD CLOSEJOB_
MESSAGE PECloseEngine METHOD PECLOSE_
ENDCLASS
// ===========================================================================
// METHOD TCrw::New()
//
// Purpose:
// 16/32Bit Crystal Reports Class Constructor
//
// ===========================================================================
METHOD NEW_()
LOCAL cTemp
::hDll := 0
::nJobHandle := 0
::lError := .F.
// Check if we load 16 or 32 Bits. First try to load CRPE32
//
::hDll := LoadLibrary("CRPE32.DLL")//LoadLib32( "CRPE32.DLL" )
::l32 := .T.
// Still no Dll, so bail out
//
IF ABS( ::hDll ) <= 32
::lError := .T.
IF ::hDll == 2
cTemp := "find"
ELSE
cTemp := "load"
ENDIF
MsgAlert( "Could not " + cTemp + " CRPE or CRPE32.DLL")
ELSE
::PEOpenEngine()
// Create JobInfo Class
//
STRUCT ::oJobInfo
MEMBER structSize AS WORD LEN 2
MEMBER NumRecords AS DWORD LEN 4
MEMBER NumSelect AS DWORD LEN 4
MEMBER NumPrinted AS DWORD LEN 4
MEMBER DispPageN AS WORD LEN 2
MEMBER LatestPage AS WORD LEN 2
MEMBER StartPageN AS WORD LEN 2
MEMBER PrintEnded AS BOOL LEN 2
ENDSTRUCT
::oJobInfo:SetMember(1, 22 )
STRUCT ::oTabLocation
MEMBER structSize AS WORD LEN 2
MEMBER location AS STRING LEN 256
ENDSTRUCT
::oTabLocation:SetMember(1, 258 )
ENDIF
RETURN Self
// ==========================================================================
// Method TCrw::FreeLibrary()
//
// ========================================================================== */
METHOD FREECRPE_()
IF ABS( ::hDll ) > 32
IF ::l32
FreeLib32( ::hDll )
ELSE
FreeLibrary( ::hDll )
ENDIF
ENDIF
::hDll := 0
RETURN .T.
// ==========================================================================
// METHOD TCrw::PEOpenEngine() -> lError
//
// Prepares the Report Engine for requests. This method is a necessary
// part of any custom-print link. It is also required for any print-only
// link in which you want the report to print to a window that is to remain
// visible after the report is printed.
// It is not necessary to use this method with a print-only link where
// you are directing the report to a printer
// ========================================================================== */
METHOD PEOPEN_()
LOCAL cFarProc
LOCAL cFunc := "PEOpenEngine"
cFarProc := GetProcAddress( ::hDLL, cFunc, .T., LONG )
::lError := ( CallDll( cFarProc ) == FALSE )
IF ::lError
MsgAlert( "Could not open the Print Engine!" + CRLF + ::PeErrorText())
ENDIF
RETURN ! ::lError
// ==========================================================================
// Method TCrw::PEErrorText()
//
// Purpose:
// Returns a string describing the status of the most recent Report
// Engine method called. These method can be used in a custom-print
// link to display the error string to the user as part of an error message.
// ========================================================================== */
METHOD ERRORT_()
LOCAL cFarProc
LOCAL cBuffer
LOCAL cError
LOCAL hError := 0
LOCAL nLen := 0
LOCAL nRet
LOCAL cFunc := "PEGetErrorText"
// Get ErrorCode
//
cError := "Error Code " + ALLTRIM( STR( ::PEGetErrorCode())) + ":" + CRLF
// Get StringHandle of ErrorText
//
cFarProc := GetProcAddress( ::hDLL, cFunc, .T., _INT, LONG, PTR, PTR )
nRet := CallDll( cFarProc , ::nJobHandle, @hError, @nLen )
// Now get the String
//
IF nRet == TRUE
cError += ::PEGetHandleString( hError, nLen )
ENDIF
return cError
// ==========================================================================
// Method TCrw::PEGetErrorCode() -> nCode
//
// Returns a number that indicates the status of the most recent Report
// Engine method called. When a call to another method fails, this call
// gets the error code that was generated so you can take some action based
// on that error code. If no Error occured, the method returns 0
// ========================================================================== */
METHOD ERRORN_()
LOCAL cFarProc
LOCAL nCode := 0
LOCAL cFunc := "PEGetErrorCode"
cFarProc := GetProcAddress( ::hDLL, cFunc, .T., _INT, LONG )
nCode := CallDll( cFarProc, ::nJobHandle )
RETURN nCode
// ==========================================================================
// Method TCrw::PEOpenPrintJob() -> lError
//
// Prepares to print a report and sets a number which identifies the
// particular print job, called a print job handle. This Handle is
// used in all subsequent calls related to the new print job
// (where a print job handle is required). This method is used as a
//
// reportFilePath Specifies the file name and path of the report
// you want to open
//
// ========================================================================== */
METHOD OPENJOB_( cReportName )
LOCAL cFarProc
LOCAL cFunc := "PEOpenPrintJob"
::cReport := cReportName
cFarProc := GetProcAddress( ::hDll, cFunc,.T., _INT, LPSTR )
::nJobHandle := CallDll( cFarProc, ::cReport )
::lError := .F.
IF ::nJobHandle == 0
MsgAlert( "Could not open Print Job!" + CRLF + '[' + ::cReport + ']' )
::lError := .T.
ENDIF
RETURN ! ::lError
// ==========================================================================
// Method TCrw::PEPrintWindow() -> lError
//
// Prints the report displayed in the print window. This method can be
// used in a custom-print link to enable the user to preview the report
// in the print window, and then, if everything looks satisfactory, to
// print the report to the printer (in response to a user event).
//
// ========================================================================== */
METHOD PRINTWND_( lWait )
LOCAL cFarProc
LOCAL cFunc := "PEPrintWindow"
LOCAL nRet
DEFAULT lWait := .T.
::lError := .F.
cFarProc := GetProcAddress( ::hDll, cFunc, .T., _INT, LONG, LONG )
nRet := CallDll( cFarProc, ::nJobHandle, IIF(lWait,1,0))
IF nRet == FALSE
::lError := .T.
ENDIF
RETURN ! ::lError
// ==========================================================================
// Method TCrw::PEIsPrintFinished() -> lYesNo // PEIsPrintJobFinished
//
// Monitors the print job to see if it is finished or still in progress.
// You can use this method any time you have a call that is contingent
// on a print job being finished.
//
// ========================================================================== */
METHOD ISPRTRDY_()
LOCAL nRet
LOCAL cFarProc
LOCAL cFunc := "PEIsPrintJobFinished"
cFarProc := GetProcAddress( ::hDll, cFunc, .T., _INT, LONG )
nRet := CallDll( cFarProc, ::nJobHandle )
RETURN ( nRet == TRUE )
// ==========================================================================
// Method TCrw::PEGetSelFormula() // PEGetSelectionFormula
//
// Returns the string for the selection formula used in the specified report.
// This method is typically used as one of a series of methods
// (PEGetSelectionFormula, PEGetHandleString, PESetSelectionFormula).
// The series can be used in a custom-print link to identify and then
// change an existing record selection formula at print time in response
// to a user selection.
//
// ========================================================================== */
METHOD GETSELE_()
LOCAL cFarProc
LOCAL nRet
LOCAL nText := 0
LOCAL nLen := 0
LOCAL cForm := ""
LOCAL cFunc := "PEGetSelectionFormula"
cFarProc := GetProcAddress( ::hDll,cFunc,.T., _INT,LONG,PTR,PTR )
nRet := CallDll( cFarProc, ::nJobHandle, @nText, @nLen )
IF nRet == FALSE
::lError := .T.
ELSE
cForm := ::PEGetHandleString( nText, nLen )
ENDIF
RETURN cForm
// ==========================================================================
// Method TCrw::PeOutputToWindow( oWnd ) -> lError
//
// Prepares to direct printed output to a print window
//
// ========================================================================== */
METHOD OUTPUTW_( oWnd )
LOCAL nRet
LOCAL cFarProc
LOCAL oRect := oWnd:GetCliRect()
LOCAL cFunc := "PEOutputToWindow"
::lError := .F.
cFarProc := GetProcAddress( ::hDll, cFunc, .T., _INT,; // nRetVar
LONG,; // nHandle
LPSTR,; // cReport
LONG,; // nTop
LONG,; // nLeft
LONG,; // nWidth
LONG,; // nHeigth
LONG,; // nStyle
LONG ) // hWnd
nRet := CallDll( cFarProc, ::nJobHandle, ::cReport,;
oRect:nLeft, oRect:nTop,;
oRect:nWidth-20, oRect:nHeight-60,;
nOr( WS_CLIPCHILDREN, WS_VISIBLE ),;
oWnd:hWnd )
IF nRet == FALSE
MsgAlert( 'Could not output to Window!' )
::lError := .T.
ENDIF
RETURN ! ::lError
// ==========================================================================
// Method TCrw::PeOutToPrinter( nCopies ) -> lError
//
// Prepares to direct printed output to a printer
//
// ========================================================================== */
METHOD OUTPUTP_( nCopies)
LOCAL nRet
LOCAL cFarProc
LOCAL cFunc := "PEOutputToPrinter"
DEFAULT nCopies := 1
::lError := .F.
cFarProc := GetProcAddress( ::hDll, cFunc, .T., _INT, LONG, LONG )
nRet := CallDll( cFarProc, ::nJobHandle, nCopies )
IF nRet == FALSE
MsgAlert( 'Could not output to Printer!' )
::lError := .T.
ENDIF
RETURN ! ::lError
// ==========================================================================
// Method TCrw::PeStartPrintJob( ) -> lError
//
// Purpose:
// Starts the printing of a report.
//
// ========================================================================== */
METHOD STARTPR_()
LOCAL nRet
LOCAL cFarProc
LOCAL cFunc := "PEStartPrintJob"
::lError := .F.
MEMORY( -1 )
Sysrefresh()
cFarProc := GetProcAddress( ::hDll, cFunc,.T., _INT, LONG, LONG )
nRet := CallDll( cFarProc , ::nJobHandle, .T. )
IF nRet == FALSE
::lError := .T.
MsgAlert( "Could not start Report!" + CRLF + ::PEErrorText())
ENDIF
RETURN ! ::lError
// ==========================================================================
// Method TCrw::PEGetWindowHandle() -> hWnd
//
// Purpose:
// Returns the handle of the print window . This method can be used in
// a custom-print link if you want to do something with the print window
// (move it, change its size, etc.).
// PEGetWindowHandle can also be used to determine if the user has already
// closed the print window.
//
// ========================================================================== */
METHOD GETHWND_()
LOCAL hWnd
LOCAL cFarProc
LOCAL cFunc := "PEGetWindowHandle"
cFarProc := GetProcAddress( ::hDll, cFunc,.T.,_INT, LONG )
hWnd := CallDll( cFarProc , ::nJobHandle )
RETURN hWnd
// ==========================================================================
// Method TCrw::PEGetGetJobStatus() -> nStatus
//
// Evaluates the status of a print job. You can use this method in a
// number of programming situations, for example:
// - to trigger error messages, for example, when a print job fails
// (due to insufficient memory, insufficient disk space, etc.),
// - to trigger screen displays (hourglass, series of graphics, etc.)
// that confirm to the user that work is in progress, or
// — to find out whether a job was canceled by the user after
// PEStartPrintJob returns.
//
// ========================================================================== */
METHOD GETJOBS_()
LOCAL cStruct
LOCAL nStatus := 0
LOCAL cFarProc := "PEGetJobStatus"
cStruct := ::oJobInfo:cBuffer
cFarProc := GetProcAddress( ::hDll, cFarProc,.T.,_INT, LONG, LPSTR )
nStatus := CallDll( cFarProc, ::nJobHandle, @cStruct )
RETURN nStatus
// ==========================================================================
// Method TCrw::PESetSelFormula()
//
// Changes the selection formula to the formula string you supply as a
// parameter. This method can be used by itself to replace a known
// record selection formula.
// The method can also be used as one of a series of methods
// (PEGetSelectionFormula, PEGetHandleString, PESetSelectionFormula).
// The series can be used in a custom-print link to identify and then
// change an existing record selection formula at print time in response
// to a user selection.
// ========================================================================== */
METHOD SETSELE_( cFormula )
LOCAL nRet
LOCAL cFarProc := "PESetSelectionFormula"
::lError := .F.
cFarProc := GetProcAddress( ::hDll, cFarProc,.T.,_INT,LONG, LPSTR )
nRet := CallDll( cFarProc, ::nJobHandle, cFormula )
IF nRet == FALSE
MsgAlert( "Invalid Selection!" + CRLF + "[" + cFormula + "]" )
::lError := .T.
ENDIF
RETURN ! ::lError
// ==========================================================================
// Method TCrw::PECheckSelFormula()
//
// Checks the text of the report's record selection formula for errors.
// Use this method whenever the record selection formula has been changed
// and you wish to check the formula for syntax errors.
// If the record selection formula contains an error, this method returns
// False
// ========================================================================== */
METHOD CHECKSEL_()
LOCAL nRet
LOCAL cFarProc := "PECheckSelectionFormula"
::lError := .F.
cFarProc := GetProcAddress( ::hDll, cFarProc,.T.,_INT, LONG )
nRet := CallDll( cFarProc, ::nJobHandle )
IF nRet == FALSE
::lError := .T.
ENDIF
RETURN ! ::lError
// ==========================================================================
// Method TCrw::PESetFormula( cformulaName, cFormulaString )
//
// Changes the specified formula to the formula string you supply as a
// parameter. This method will only change the text of a formula which
// already exists in the report; you can not use it to add a formula.
// This method can be used by itself to replace the formula string for
// a known formula.
// It can also be used as one of a series of methods (PEGetFormula,
// PEGetHandleString, PESetFormula). The series can be used in a
// custom-print link to identify and then change an existing formula at
// print time in response to a user selection.
//
// ==========================================================================
METHOD SETFORM_( cName, cString )
LOCAL nRet
LOCAL cFarProc := "PESetFormula"
::lError := .F.
cFarProc := GetProcAddress( ::hDll,cFarProc ,.T.,_INT, LONG, LPSTR, LPSTR )
nRet := CallDll( cFarProc, ::nJobHandle, cName, cString )
IF nret == FALSE
//MsgAlert( "Could not set Formula!" + CRLF + "[" + cName + "]" + ;
// + CRLF + "[" + cString + "]" )
::lError := .T.
ENDIF
RETURN ! ::lError
// ==========================================================================
// Method TCrw::PECheckFormula( cFormualName )
//
// The PECheckFormula method checks the text of a named formula for
// validity. Use this method to check a named formula for errors. This
// method works like the Check button in the Formula Editor. If the
// named formula contains an error, the method returns False
//
// ========================================================================== */
METHOD CHECKFOR_( cformulaName )
LOCAL nRet
LOCAL cFarProc := "PECheckFormula"
::lError := .F.
cFarProc := GetProcAddress( ::hDll, cFarProc,.T.,_INT,LONG,LPSTR )
nRet := CallDll( cFarProc, ::nJobHandle, cformulaName )
IF nRet == FALSE
MsgAlert("Invalid Formula!" + CRLF + "[" + cformulaName + "]" )
::lError := .T.
ENDIF
RETURN ! ::lError
// ==========================================================================
// Method TCrw::PEGetNTables()
//
// The PEGetNTables method retrieves the number of tables in the open report.
// It counts both PC and SQL databases. This method is one of a series of
// methods that enable you to retrieve and update database information in an
// opened report so that the report can be printed using different server,
// database, user, and/or table location settings.
//
// ========================================================================== */
METHOD GETNTAB_()
LOCAL nTables
LOCAL cFarProc := "PEGetNTables"
cFarProc := GetProcAddress( ::hDll, cFarProc,.T.,_INT, LONG )
nTables := CallDll( cFarProc, ::nJobHandle )
RETURN nTables
// ==========================================================================
// Method TCrw::PEGetTabLocation // PEGetNthTableLocation()
//
// The PEGetNthTableLocation method determines the location of a selected
// table used in the specified print job. This method is typically combined
// with PESetNthTableLocation to identify the location of a table and then
// to change it.
// ========================================================================== */
METHOD GETTLOC_( nPos )
LOCAL cBuffer
LOCAL nRet
LOCAL cFarProc := "PEGetNthTableLocation"
// Clear Filename-Buffer
//
::lError := .F.
::oTabLocation:SetMember( 2, CHR(0) )
cBuffer := ::oTabLocation:cBuffer
cFarProc := GetProcAddress( ::hDll, cFarProc, .T., _INT, LONG, LONG, LPSTR )
nRet := CallDll( cFarProc, ::nJobHandle, nPos, @cBuffer )
::oTabLocation:cBuffer := cBuffer
cBuffer := ::oTabLocation:GetMember( 2 )
IF nRet == FALSE .OR. EMPTY( cBuffer )
MsgAlert( "Error locating Table", ::PEGetErrorCode())
::lError := .T.
ENDIF
RETURN IIF( ::lError, "", TRIM( cBuffer ))
// ==========================================================================
// Method TCrw::PESetTabLocation // peSetNthTableLocation()
//
// The PESetNthTableLocation method sets the location for a selected table
// in the specified print job. This method is typically combined with
// PEGetTableLocation to identify the location of a table and then to
// change it.
// ==========================================================================
METHOD SETTLOC_( cName, nPos)
LOCAL nRet
LOCAL cFarProc := "PESetNthTableLocation"
DEFAULT nPos := 0
// Set Filename-Buffer
//
::oTabLocation:SetMember( 2, TRIM( cName ) + CHR(0) )
::lError := .F.
cFarProc := GetProcAddress( ::hDll, cFarProc, .T., _INT, LONG, LONG, LPSTR )
nRet := CallDll( cFarProc, ::nJobHandle, nPos, ::oTabLocation:cBuffer )
IF nRet == FALSE
::lError := .T.
MsgAlert( "Error setting Location " + cName, ::PEGetErrorText())
ENDIF
RETURN ! ::lError
// ==========================================================================
// Method TCrw::PEGetSqlQuery
//
// You can use this method to retrieve the SQL query that will be generated
// to print the report, and you can update the query using PESetSQLQuery.
//
// ========================================================================== */
METHOD GETSQLQ_()
LOCAL cFarProc := "PEGetSqlQuery"
LOCAL nHandle := 0
LOCAL nLen := 0
LOCAL cBuffer := ""
LOCAL nRet
::lError := .F.
cFarProc := GetProcAddress( ::hDll, cFarProc, .T., _INT, LONG, PTR, PTR )
nRet := CallDll( cFarProc, ::nJobHandle, @nHandle, @nLen )
IF nRet == FALSE
MsgAlert("Could not get SQL query!" + CRLF )
::lError := .T.
ELSE
cBuffer := ::PEGetHandleString( nHandle, nLen )
ENDIF
RETURN cBuffer
// ==========================================================================
// Method TCrw::PESetSqlQuery
//
// You can use this method to set a SQL query
//
// ========================================================================== */
METHOD SETSQLQ_( cQuery )
LOCAL nRet
LOCAL cFarProc := "PESetSqlQuery"
::lError := .F.
cFarProc := GetProcAddress( ::hDll, cFarProc, .T., _INT, LONG, LPSTR )
nRet := CallDll( cFarProc, ::nJobHandle, cQuery )
IF nRet == FALSE
MsgAlert('Could not set query!' + CRLF + cQuery )
::lError := .T.
ENDIF
RETURN ! ::lError
// ==========================================================================
// Method TCrw::PETestNTable( n ) // PETestNthTableConnectivity( nPos )
//
// Purpose:
// The PETestNthTableConnectivity method tests whether a database
// table's settings are valid and ready to be reported on.
// This method is typically used if you plan to print at a later time
// but you want to test now to make sure everything is in order for
// logging on.
//
// ========================================================================== */
METHOD TESTTAB_( nPos )
LOCAL nRet
LOCAL cFarProc := "PETestNthTableConnectivity"
LOCAL cError := ""
LOCAL cBuffer
DEFAULT nPos := 0
cFarProc := GetProcAddress( ::hDll, cFarProc, .T., _INT, LONG, LONG )
nRet := CallDll( cFarProc, ::nJobHandle, nPos )
IF nRet == FALSE
cError := ::PEErrorText()
cBuffer := ::PEGetTabLocation( nPos )
cError += CRLF + "File: " + cBuffer
ENDIF
RETURN cError
// ==========================================================================
// Method TCrw::PEClosePrintJob()
//
// PEClosePrintJob closes the print job. If printing has not yet finished,
// it continues; if the print window is open, it stays open.
// This method is used as a mandatory part of each custom-print link
// to shut down the print job once it has finished printing to screen
// or to window.
// ========================================================================== */
METHOD CLOSEJOB_()
LOCAL nRet
LOCAL cFarProc := "PEClosePrintJob"
::lError := .F.
IF ::nJobHandle != 0
cFarProc := GetProcAddress( ::hDll, cFarPRoc, .T., _INT, LONG )
nRet := CallDll( cFarProc, ::nJobHandle )
IF nRet == FALSE
::lError := .T.
ENDIF
ENDIF
RETURN ::lError
// ==========================================================================
// Method TCrw::PECloseEngine()
//
// PECloseEngine terminates the Report Engine. All printing is stopped
// and all windows are closed.
//
// NOTE: This will only happen if the calling application is the
// last one using CRPE !!!
//
// This method stops the Report Engine from sending output, but the
// report may continue to print from data remaining in the spooler.
// This method is a necessary part of any custom-print link. It is
// also required for any print-only link in which you want the report
// to print to a window that is to remain visible after the report is
// printed. It is not necessary to use this method with a print-only link
// where you are directing the report to a printer.
// ========================================================================== */
METHOD PECLOSE_()
LOCAL cFarProc := "PECloseEngine"
IF ::hDll != 0
cFarProc := GetProcAddress( ::hDll, cFarProc, .T., _INT )
CallDll( cFarProc )
ENDIF
RETURN .T.
// ==========================================================================
// Method TCrw::PEGetHandleString( nHandle )
//
// This method will return the text that the string handle is pointing to.
//
// ========================================================================== */
METHOD GETSTR_( nHandle, nLen )
LOCAL nRet
LOCAL cFarProc := "PEGetHandleString"
LOCAL cBuffer := SPACE( nLen )
cFarProc := GetProcAddress( ::hDll, cFarProc, .T., _INT, LONG,LPSTR,LONG )
nRet := CallDll( cFarProc , nHandle, @cBuffer, nLen )
IF nRet == FALSE
cBuffer := ""
ELSE
cBuffer := SUBSTR( cBuffer, 1, nLen -1 )
ENDIF
RETURN cBuffer
// ==========================================================================
// Method TCrw::GetModuleHandle( lpName )
//
// This method will return the Handle to a Module( Dll ) that is mapped
// into our address space
//
// ========================================================================== */
METHOD GETMOD_( cModule )
LOCAL hDll := LoadLib32( "Kernel32.dll" )
LOCAL cFarProc
LOCAL nRet
cFarProc := GetProcAddress( hDll, "GetModuleHandleA", .T., LONG, LPSTR )
nRet := CallDll( cFarProc ,cModule )
RETURN nRet