*-------------------------------------------------------------------------------------------------------------------------------------------------------- * (EN) AUTOGENERATED - ATTENTION!! - NOT INTENDED FOR EXECUTION!! USE ONLY FOR MERGING CHANGES AND STORING WITH SCM TOOLS!! *-------------------------------------------------------------------------------------------------------------------------------------------------------- *< FOXBIN2PRG: Version="1.21" SourceFile="_frxcursor.vcx" CPID="1252" /> (Solo para binarios VFP 9 / Only for VFP 9 binaries) * * DEFINE CLASS frxcursor AS custom && Provides methods to translate and manipulate various values in label and report tables (LBXs and FRXs) *< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" /> #INCLUDE "_frxcursor.h" * *m: binstringtoint && Returns a numeric equivalent of a given binary number given in byte string form. *m: bintoint && Returns the integer form of binary data. Parameter: cBinary *m: charsettolocale && Converts a given Font Charset to a candidate locale Id for use with the STRCONV() function. Parameters: nCharSet *m: createbandcursor && Creates a cursor with alias "bands" containing records of information for each band in the report. Assumes source alias is "FRX" unless specified. Parameters: [cFrxAlias] *m: createcalcresetoncursor && Creates a cursor with alias "reset_on" that contains records of information for each prompt in the Calculation Reset combobox. Parameters: [cFrxAlias] *m: createdefaultprintenvcursor && Creates a one-row cursor with the same structure as the FRX. Default parameters are "frx", "defPrnEnv". Parameters: [ cFrxAlias [, cDestinationAlias]] *m: creategroupcursor && Creates a cursor with the alias "groups" containing records of information about each data group in the specified report cursor, default "frx". Parameters: [cFrxAlias] *m: createobjcursorrecord && Called from .createObjectCursor(). Parameter: cDestinationAlias *m: createobjectcursor && Creates a cursor (default alias: "objects") of records for each object record in the report alias. Parameters: [ cFrxAlias [, cDestinationAlias [, iFilterMode ]]] *m: createvariablecursor && Creates a cursor with the alias "vars" containing records of information for each report variable in the report. Parameters: [cFrxAlias] *m: frutopixels && Returns the pixel value of a given measurement in FRUs. *m: getbandfor && Returns a SCATTER NAME band object for the specified object ID. Calls .createObjectCursor() if necessary. Parameters: cObjectID [, lStart] *m: getfrutextheight && Reutrns the height of a given string in FRUs. Parameters: cText, cTypeface, iSize [, cStyle ] *m: getfrutextwidth && Returns the width of a given string in FRUs. Parameters: cText, cTypeface, iSize [, cStyle ] *m: getfrxtimestamp && Returns a FOX system file timestamp from a datetime value, any data type. Parameter: [vDateTime] *m: getmetadatadomdoc && Returns a reference to an MSXml.DomDocument with the metadata xml loaded. Assumes FRX is located on desired record. *m: getobjectsinband && Returns a collection of UNIQUEIDs (or RECNOs) for each object in a given band. Calls .createObjectCursor() if necessary. Parameters: cBandId [, lRecnos] *m: getreportattribute && Returns the value of a given report/header attribute. The FRX cursor must be open. Parameters: cToken [, iAlternate] *m: getselectedobjectcount && Returns the number of selected objects in the frx cursor. Parameter: [cFrxAlias] *m: gettargettypetext && Returns a readable string version of a target Type+Code. Parameters: iObjectType, iObjectCode *m: gettimestampstring && Returns a readable string version of a Fox system timestamp, using current date settings. Parameter: iStamp *m: getunitvaluefromfru && Returns a given unit value for a given value in FRUs, depending on the units. Parameters: nFruValue, iUnits *m: gorec && Restores record pointer with bounds checking. Parameters: i, cAlias *m: hasband && Returns .T. if the report has the specified band type. Calls .createBandCursor() if necessary. Parameters: iObjCode *m: hasdetailheader && Returns .T. if the specified detail band has an associated detail header band. Calls .createBandCursor() if necessary. Parameters: cUniqueId *m: hasprotectionflag && Returns .T. if the given binary data contains a specific bit set. Parameters: cBytes, iBit *m: insertband && Inserts a band record into an frx cursor. Assumes that the FRX is currently selected and that the record pointer is located appropriately. Parameter: iObjCode *m: insertdataenvrecord && Inserts a data environment object record into an FRX cursor. Assumes that the record pointer is appropriately located. Parameters: ID, NAME, EXPR, CODE *m: insertdetailband && Inserts a detail band into the frx cursor. Assumes: the record pointer is located appropriately. Parameters: none *m: insertdetailheaderfooter && Inserts detail header and footer bands into the frx cursor. Assumes: record pointer is located on the detail band record. Parameters: none *m: insertsummaryband && Inserts a summary band into the frx cursor. Parameters: lBreakToNewPage, lPageHeader, lPageFooter *m: inserttitleband && Inserts a title band into the frx cursor. Parameter: lBreakToNewPage *m: inttobin && Returns a binary form of an integer. Parameter: iNumber *m: inttobinstring && Returns a string of bytes, the binary version of a given integer. *m: pixelstofru && Returns the FRU value of a given measurement in pixels. *m: popprintenv && Restores the printer environment from a previously saved cursor. See .PushPrintEnvToCursor() method. Assumes: previously saved cursor is currently selected. *m: pushprintenvtocursor && Saves the current printer environment to a cursor. Parameter: cSavedInAlias *m: setcolumncount && Adds or removes columns (and column header/footer records) from the FRX cursor. Assumes: the frx cursor is selected. Parameters: iColumns *m: stripquotes && Returns a string with embraced string delimiters removed. Parameters: cString *m: synchobjectpositions && Updates VPOS values in the FRX cursor for each object, based on which band the object starts in, and the current height of each band as expressed in the bands cursor. Assumes: band and object cursors exist; current alias is frx cursor; no recno restore. *p: screendpi && Contains the working DPI of the ReportDesigner. Currently hard-coded to 96. *p: _memberdata && XML Metadata for customizable properties * * Name = "frxcursor" screendpi = 96 _memberdata = * PROCEDURE binstringtoint && Returns a numeric equivalent of a given binary number given in byte string form. *======================================================= * BinstringToInt( char ) * * Returns a numeric equivalent of a binary data in string * form. * * BinChar & Integer conversion, based on code by RS *======================================================= lparameter cByte local iReturn, i, b iReturn = 0 for m.i = len( m.cByte ) to 1 step -1 b = asc( substr( m.cByte, m.i, 1 )) iReturn = (m.iReturn*256) + m.b endfor return m.iReturn ENDPROC PROCEDURE bintoint && Returns the integer form of binary data. Parameter: cBinary *======================================================= * BinToInt( cBytes ) * * Returns an integer form of binary data *======================================================= LPARAMETERS tcBinary LOCAL lcInteger,lnInteger,lnCount,lnStrLen IF EMPTY(tcBinary) RETURN 0 ENDIF lnStrLen=LEN(tcBinary) lnInteger=0 FOR lnCount = 0 TO (lnStrLen-1) IF SUBSTR(tcBinary,lnStrLen-lnCount,1)=="1" lnInteger=lnInteger+2^lnCount ENDIF ENDFOR RETURN INT(lnInteger) ENDPROC PROCEDURE charsettolocale && Converts a given Font Charset to a candidate locale Id for use with the STRCONV() function. Parameters: nCharSet *======================================================= * CharsetToLocale( nCharset ) * * We need to map a given Font Charset to a candidate locale * for use with the STRCONV() function. * *---------------------------------------------------------- * References: Q224804, Q232625 * also http://www.science.co.il/Language-Locale-Codes.asp * * Charset------------------- CodePage---- Locale (hex / dec) * 0 Western 1252 1033 * 178 Arabic 1256, 864 0x0401 / 1025 (saudi) * 186 Baltic 1257, 0x0425 / 1061 * 134 Chinese Simplified 936 0x0804 / 2052 * 136 Chinese Traditional 950 0x0404 / 1028 * 238 Central European 1250, 0x0405 / 1029 (Czech) * 204 Cyrillic 1251, 855 0x0419 / 1049 (Russian) * 161 Greek 1253, 869 0x0408 / 1032 * 177 Hebrew 1255 0x040d / 1037 * 128 Japanese 932 0x0411 / 1041 * 129 Korean 1361, 949 0x0412 / 1042 * 162 Turkish 1254, 857 0x041f / 1055 * 163 Vietnamese 1258 0x042a / 1066 *======================================================= lparameter nCharset do case case inlist( m.nCharset, -1, 1 ) * Charset not assigned or system default * Map to default locale: return 0 case inlist( m.nCharset, 0 ) * 0 = Western return 1033 case inlist( m.nCharset, 2, 77, 255 ) * These are generic. Map to default locale? return 0 case m.nCharset = 178 * 178 Arabic 1256, 864 0x0401 / 1025 (saudi) return 1025 case m.nCharset = 186 * 186 Baltic 1257, 0x0425 / 1061 return 1061 case m.nCharset = 134 * 134 Chinese Simplified 936 0x0804 / 2052 return 2052 case m.nCharset = 136 * 136 Chinese Traditional 950 0x0404 / 1028 return 1028 case m.nCharset = 238 * 238 Central European 1250, 0x0405 / 1029 (Czech) return 1029 case m.nCharset = 204 * 204 Cyrillic 1251, 855 0x0419 / 1049 (Russian) return 1049 case m.nCharset = 161 * 161 Greek 1253, 869 0x0408 / 1032 return 1032 case m.nCharset = 177 * 177 Hebrew 1255 0x040d / 1037 return 1037 case m.nCharset = 128 * 128 Japanese 932 0x0411 / 1041 return 1041 case m.nCharset = 129 * 129 Korean 1361, 949 0x0412 / 1042 return 1042 case m.nCharset = 162 * 162 Turkish 1254, 857 0x041f / 1055 return 1055 case m.nCharset = 163 * 163 Vietnamese 1258 0x042a / 1066 return 1066 otherwise return 0 endcase return 0 ENDPROC PROCEDURE createbandcursor && Creates a cursor with alias "bands" containing records of information for each band in the report. Assumes source alias is "FRX" unless specified. Parameters: [cFrxAlias] *======================================================= * CreateBandCursor() * * Creats a cursor with the alias "bands" containing records * of information for each band in the report. * * Returns .T. if successfully created. *======================================================= lparameter tcFrxAlias if empty( m.tcFrxAlias ) tcFrxAlias = 'frx' endif if not used(m.tcFrxAlias) return .F. endif local curSel, curRec curSel = select() curRec = recno(m.tcFrxAlias) *------------------------------------------------------- * create the bands cursor: *------------------------------------------------------- if used("bands") use in bands endif select 0 create cursor bands ( ; UNIQUEID c(10), ; OBJTYPE N(2,0), ; OBJCODE n(3,0), ; EXPR M, ; BANDLABEL c(35), ; START n(9,3), ; STOP n(9,3), ; HEIGHT n(9,3), ; P_START i, ; P_STOP i, ; P_HEIGHT i, ; R_START i, ; R_STOP i, ; RESETTOTAL i, ; BAND_SEQ i, ; REL_BAND_ID c(10), ; REC_NO i ) *------------------------------------------------------- * Initialise stuff: *------------------------------------------------------- local nStart, iStart, iDetailCount local cSuffix, iBandCount, oRec local oGroup, oHeader local lcTitleId, lcSummaryId nStart = 0.000 iStart = 0 oGroup = newobject("Collection") oHeader = newobject("Collection") iBandCount = 0 iDetailCount = 0 store "" to lcTitleId, lcSummaryId *------------------------------------------------------- * Scan through the band records, building up the information * and then insert a new record into the bands cursor: *------------------------------------------------------- select (m.tcFrxAlias) scan for OBJTYPE = FRX_OBJTYP_BAND ; and not deleted() and ; PLATFORM = FRX_PLATFORM_WINDOWS *---------------------------------------------- * Initialise the record buffer *---------------------------------------------- select bands scatter memo blank name oRec select (m.tcFrxAlias) iBandCount = m.iBandCount + 1 oRec.BAND_SEQ = m.iBandCount *---------------------------------------------- * Transfer over some field values: *---------------------------------------------- oRec.UNIQUEID = UNIQUEID oRec.REC_NO = recno() oRec.OBJTYPE = OBJTYPE oRec.OBJCODE = OBJCODE oRec.EXPR = EXPR oRec.BANDLABEL = THIS.getTargetTypeText( OBJTYPE, OBJCODE ) *---------------------------------------------- * Save for later: *---------------------------------------------- if OBJCODE = FRX_OBJCOD_TITLE lcTitleID = UNIQUEID endif if OBJCODE = FRX_OBJCOD_SUMMARY lcSummaryID = UNIQUEID endif *---------------------------------------------- * Determine related header/footer IDs: *---------------------------------------------- do case case inlist( OBJCODE, FRX_OBJCOD_PAGEHEADER, FRX_OBJCOD_COLHEADER, FRX_OBJCOD_GROUPHEADER, FRX_OBJCOD_DETAILHEADER ) *------------------------------------- * Push the header ID on the stack: *------------------------------------- oHeader.Add( UNIQUEID ) case inlist( OBJCODE, FRX_OBJCOD_PAGEFOOTER, FRX_OBJCOD_COLFOOTER, FRX_OBJCOD_GROUPFOOTER, FRX_OBJCOD_DETAILFOOTER ) *------------------------------------- * Pop the related header ID off the stack and * store it: *------------------------------------- oRec.REL_BAND_ID = oHeader.Item( oHeader.Count ) oHeader.Remove( oHeader.Count ) endcase *---------------------------------------------- * Some bands need extra info in their labels: *---------------------------------------------- do case case OBJCODE = FRX_OBJCOD_GROUPHEADER cSuffix = ":" + trim(EXPR) oGroup.Add( m.cSuffix ) oRec.RESETTOTAL = FRX_RESETTOTAL_GROUP_OFFSET + oGroup.Count case OBJCODE = FRX_OBJCOD_DETAIL iDetailCount = m.iDetailCount + 1 oRec.RESETTOTAL = FRX_RESETTOTAL_DETAIL_OFFSET + m.iDetailCount cSuffix = " " + transform( m.iDetailCount ) ; + iif(not empty( trim(EXPR)), ":" + trim(EXPR), "") case OBJCODE = FRX_OBJCOD_GROUPFOOTER cSuffix = oGroup.Item( oGroup.Count ) oGroup.Remove( oGroup.Count ) otherwise cSuffix = "" endcase oRec.BANDLABEL = oRec.BANDLABEL + m.cSuffix *---------------------------------------------- * Band dimensions: *---------------------------------------------- oRec.HEIGHT = HEIGHT oRec.P_HEIGHT = THIS.FruToPixels( HEIGHT ) oRec.START = m.nStart oRec.STOP = m.nStart + oRec.HEIGHT + BAND_SEPARATOR_HEIGHT_FRUS nStart = oRec.STOP oRec.P_START = m.iStart oRec.P_STOP = m.iStart + oRec.P_HEIGHT + BAND_SEPARATOR_HEIGHT_PIXELS - 1 iStart = oRec.P_STOP + 1 *---------------------------------------------- * Run-time Band dimensions: *---------------------------------------------- oRec.R_START = oRec.P_START - 18 oRec.R_STOP = oRec.P_STOP - 2 && per RICHSTA * oRec.R_STOP = oRec.P_STOP - 3 && empirically *---------------------------------------------- * Add the record to the cursor: *---------------------------------------------- insert into bands from name oRec endscan *---------------------------------------------- * Retro-fit the Headers' relative Footer band id: *---------------------------------------------- select bands local iRec, cFooterId, cBandId scan if not empty( REL_BAND_ID ) iRec = recno() m.cFooterId = UNIQUEID m.cHeaderId = REL_BAND_ID locate for UNIQUEID = m.cHeaderId if found() replace REL_BAND_ID with m.cFooterId endif go m.iRec endif endscan if not empty( m.lcTitleId ) and not empty( m.lcSummaryId ) *---------------------------------------------- * Match up relative band ids: *---------------------------------------------- locate for UNIQUEID = m.lcTitleID replace REL_BAND_ID with m.lcSummaryId locate for UNIQUEID = m.lcSummaryID replace REL_BAND_ID with m.lcTitleId endif go top in bands release oGroup, oHeader THIS.goRec(m.curRec, m.tcFrxAlias) select (m.curSel) return .T. ENDPROC PROCEDURE createcalcresetoncursor && Creates a cursor with alias "reset_on" that contains records of information for each prompt in the Calculation Reset combobox. Parameters: [cFrxAlias] *======================================================= * CreateCalcResetOnCursor() * * Creates a cursor with the alias "reset_on" containing records * of information for each prompt in the Calculation Reset combobox. * * Returns .T. if successfully created. *======================================================= lparameter tcFrxAlias if empty( m.tcFrxAlias ) tcFrxAlias = 'frx' endif if not used(m.tcFrxAlias) return .F. endif local curSel, curRec, iGroupCount, iDetailCount, iNum curSel = select() *------------------------------------------------------- * create the reset_on cursor: *------------------------------------------------------- if used("reset_on") use in reset_on endif create cursor reset_on (; UNIQUEID c(10), ; OBJCODE n(2,0) , ; PROMPT_TEXT c(30), ; RESETTOTAL i ) *----------------------------------------------------------- * Add in the report/Page resets: *----------------------------------------------------------- insert into reset_on values ( "", 0, ENDOFREPORT_LOC, FRX_RESETTOTAL_ENDOFREPORT ) insert into reset_on values ( "", 0, ENDOFPAGE_LOC, FRX_RESETTOTAL_ENDOFPAGE ) select (m.tcFrxAlias) curRec = recno() *----------------------------------------------------------- * Add in the column reset if there are multi-cols: *----------------------------------------------------------- locate for OBJTYPE = FRX_OBJTYP_REPORTHEADER ; and PLATFORM = FRX_PLATFORM_WINDOWS if VPOS > 1 insert into reset_on values ( "", 0, ENDOFCOLUMN_LOC, FRX_RESETTOTAL_ENDOFCOLUMN ) else insert into reset_on values ( "", 0, "\"+ENDOFCOLUMN_LOC, FRX_RESETTOTAL_ENDOFCOLUMN ) endif *----------------------------------------------------------- * Only add in the group reset if there are groups: *----------------------------------------------------------- count for OBJTYPE = FRX_OBJTYP_BAND ; and OBJCODE = FRX_OBJCOD_GROUPHEADER ; and PLATFORM = FRX_PLATFORM_WINDOWS ; to iGroupCount if m.iGroupCount > 0 iNum = 1 insert into reset_on values ( "", 0, "\-", 1001 ) scan for OBJTYPE = FRX_OBJTYP_BAND ; and OBJCODE = FRX_OBJCOD_GROUPHEADER ; and PLATFORM = FRX_PLATFORM_WINDOWS insert into reset_on values ( ; &tcFrxAlias..UNIQUEID, ; &tcFrxAlias..OBJCODE, ; GROUP_BY_LOC + trim(&tcFrxAlias..EXPR), ; FRX_RESETTOTAL_GROUP_OFFSET + m.iNum ) iNum = m.iNum + 1 endscan endif *----------------------------------------------------------- * Only add in the detail reset if this is a multi-detail report: *----------------------------------------------------------- count for OBJTYPE = FRX_OBJTYP_BAND ; and OBJCODE = FRX_OBJCOD_DETAIL ; and PLATFORM = FRX_PLATFORM_WINDOWS ; to iDetailCount if m.iDetailCount > 1 iNum = 1 insert into reset_on values ( "", 0, "\-", 1002 ) scan for OBJTYPE = FRX_OBJTYP_BAND ; and OBJCODE = FRX_OBJCOD_DETAIL ; and PLATFORM = FRX_PLATFORM_WINDOWS insert into reset_on values ( ; &tcFrxAlias..UNIQUEID, ; &tcFrxAlias..OBJCODE, ; DETAIL_LOC + transform(m.iNum), ; FRX_RESETTOTAL_DETAIL_OFFSET + m.iNum ) iNum = m.iNum + 1 endscan endif THIS.goRec(m.curRec, m.tcFrxAlias) select (m.curSel) return .t. ENDPROC PROCEDURE createdefaultprintenvcursor && Creates a one-row cursor with the same structure as the FRX. Default parameters are "frx", "defPrnEnv". Parameters: [ cFrxAlias [, cDestinationAlias]] *======================================================= * CreateDefaultPrintEnvCursor( , ) * * Creates a one-row cursor with the same structure as the * FRX. Default parameters are "frx", "defPrnEnv". *======================================================= lparameters lcFrxAlias, lcPEAlias local curSel curSel = select() if empty( m.lcFrxAlias ) lcFrxAlias = 'frx' endif if empty( m.lcPEAlias ) lcPEAlias = 'defPrnEnv' endif select * ; from (m.lcFrxAlias) ; where OBJTYPE = FRX_OBJTYP_REPORTHEADER ; and PLATFORM = FRX_PLATFORM_WINDOWS ; into cursor (m.lcPEAlias) ; readwrite =sys(1037,2) select (m.curSel) return ENDPROC PROCEDURE creategroupcursor && Creates a cursor with the alias "groups" containing records of information about each data group in the specified report cursor, default "frx". Parameters: [cFrxAlias] *======================================================= * CreateGroupCursor() * * Creats a cursor with the alias "groups" containing records * of information for each data group in the report. * Used mainly by PanelGrouping class. * * Returns .T. if successfully created. *======================================================= lparameter tcFrxAlias if empty( m.tcFrxAlias ) tcFrxAlias = 'frx' endif if not used(m.tcFrxAlias) return .F. endif curSel = select() *------------------------------------------------------- * get the current report measurement units and tell our * converter to use them: *------------------------------------------------------- local iUnits iUnits = THIS.getReportAttribute("UNITS") *------------------------------------------------------- * create the groups cursor: *------------------------------------------------------- if used("groups") use in groups endif select 0 create cursor groups ( ; UNIQUEID c(10), ; EXPR M, ; PAGINATE i, ; REPRINT l, ; THRESH n(9,3), ; FOOTER_ID c(10) ) *------------------------------------------------------- * Initialise stuff: *------------------------------------------------------- local iPaginate, iCurRec, nThreshold, lisMultiCol iPaginate = 0 iCurRec = recno(m.tcFrxAlias) lIsMultiCol = THIS.getReportAttribute("MULTICOLUMN") *------------------------------------------------------- * Scan through the group header records, building up the information * and then insert a new record into the groups cursor: *------------------------------------------------------- select (m.tcFrxAlias) scan for OBJTYPE = FRX_OBJTYP_BAND and ; OBJCODE = FRX_OBJCOD_GROUPHEADER and ; not deleted() and ; PLATFORM = FRX_PLATFORM_WINDOWS *------------------------------------- * Pagination: try: * * 1 ( ) Normal (none set) * 2 ( ) Start on new column (COLBREAK) * 3 ( ) Start on new page (PAGEBREAK) * 4 ( ) Start on new page 1 (PAGEBREAK+RESETPAGE) *------------------------------------- do case case PAGEBREAK and RESETPAGE iPaginate = 4 case PAGEBREAK iPaginate = 3 case COLBREAK if m.lIsMultiCol iPaginate = 2 else *-------------------------------- * Even though this option used to be set to "new column", * the report only has one column, so reset to default: *-------------------------------- iPaginate = 1 endif otherwise iPaginate = 1 endcase *------------------------------------- * Calculate threshold in local units: *------------------------------------- nThreshold = THIS.getUnitValueFromFRU( WIDTH, m.iUnits ) insert into groups values ( ; &tcFrxAlias..UNIQUEID, ; &tcFrxAlias..EXPR, ; m.iPaginate, ; &tcFrxAlias..NOREPEAT, ; m.nThreshold, ; "" ) endscan *------------------------------------------------------- * Now grab the group footer IDs as well. Note of course * that they are in reverse order to the headers (nesting): *------------------------------------------------------- go bottom in groups scan for OBJTYPE = FRX_OBJTYP_BAND and ; OBJCODE = FRX_OBJCOD_GROUPFOOTER and ; not deleted() and ; PLATFORM = FRX_PLATFORM_WINDOWS select groups replace FOOTER_ID with &tcFrxAlias..UNIQUEID skip -1 select (m.tcFrxAlias) endscan *------------------------------------------------------- * Restore the record pointer in FRX (important) *------------------------------------------------------- THIS.goRec(m.icurRec, m.tcFrxAlias) select (m.curSel) return .T. ENDPROC PROCEDURE createobjcursorrecord && Called from .createObjectCursor(). Parameter: cDestinationAlias *======================================================= * createObjCursorRecord() * * Assumes: current alias is the source *======================================================= lparameters tcDestAlias, tlRuntimeMode local srcAlias, lIsGroup, oRec srcAlias = alias() lIsGroup = .F. select (m.tcDestAlias) scatter memo blank name oRec select (m.srcAlias) oRec.REC_NO = recno() do case case OBJTYPE = FRX_OBJTYP_LABEL oRec.CTYPE = TARGET_TEXT_LABEL_LOC * oRec.OBJNAME = TARGET_TEXT_LABEL_LOC + ": " + trim(EXPR) oRec.OBJNAME = THIS.stripQuotes(trim(EXPR)) oRec.OBJ_PICT = "pslabel.bmp" oRec.LOCALE_ID = THIS.CharsetToLocale( RESOID ) oRec.TYPE_SEQ = 1 case OBJTYPE = FRX_OBJTYP_FIELD oRec.CTYPE = TARGET_FIELD_LOC * oRec.OBJNAME = TARGET_FIELD_LOC + ": " + trim(EXPR) oRec.OBJNAME = THIS.stripQuotes(trim(EXPR)) oRec.OBJ_PICT = "pseditbx.bmp" oRec.LOCALE_ID = THIS.CharsetToLocale( RESOID ) oRec.TYPE_SEQ = 2 case OBJTYPE = FRX_OBJTYP_LINE oRec.CTYPE = TARGET_LINE_LOC oRec.OBJNAME = TARGET_LINE_LOC oRec.OBJ_PICT = "psline.bmp" oRec.TYPE_SEQ = 3 case OBJTYPE = FRX_OBJTYP_RECTANGLE oRec.CTYPE = TARGET_BOX_LOC oRec.OBJNAME = TARGET_BOX_LOC oRec.OBJ_PICT = "pshape.bmp" oRec.TYPE_SEQ = 4 case OBJTYPE = FRX_OBJTYP_PICTURE oRec.CTYPE = TARGET_PICTURE_LOC if not empty( NAME ) * oRec.OBJNAME = TARGET_PICTURE_LOC + ": " + trim(NAME) oRec.OBJNAME = THIS.stripQuotes(trim(NAME)) else * oRec.OBJNAME = TARGET_PICTURE_LOC + ": " + trim(PICTURE) oRec.OBJNAME = THIS.stripQuotes(trim(PICTURE)) endif oRec.OBJ_PICT = "psolebnd.bmp" oRec.TYPE_SEQ = 5 case OBJTYPE = FRX_OBJTYP_GROUP oRec.CTYPE = TARGET_GROUPED_LOC oRec.OBJNAME = TARGET_GROUPED_LOC + " (" + trans(HPOS)+")" oRec.OBJ_PICT = "group2.bmp" lIsGroup = .T. oRec.TYPE_SEQ = 6 endcase oRec.UNIQUEID = UNIQUEID oRec.OBJTYPE = OBJTYPE oRec.OBJCODE = OBJCODE oRec.EXPR = EXPR oRec.VPOS = VPOS oRec.HPOS = HPOS oRec.HEIGHT = HEIGHT oRec.P_START = THIS.FruToPixels( VPOS ) oRec.P_HEIGHT = THIS.FruToPixels( HEIGHT ) oRec.P_STOP = (oRec.P_START + oRec.P_HEIGHT - 1) oRec.WIDTH = WIDTH oRec.SELECTED = CURPOS if not m.lIsGroup if m.tlRuntimeMode *-------------------------------------------------------- * Determine the object's location, start and end bands, * as determined by the report run-time engine, using the * two adjusted lookup cursors we created earlier: *-------------------------------------------------------- *------------------------------------------- * Scan bottom up for start points: *------------------------------------------- select bands go bottom do while .T. if R_START <= oRec.P_START oRec.START_BAND_ID = UNIQUEID oRec.BANDLABEL = trim(BANDLABEL) oRec.BAND_OFFSET = oRec.P_START - P_START oRec.BAND_SEQ = BAND_SEQ exit endif if recno()=1 exit endif skip -1 in bands enddo *------------------------------------------- * scan top down for end points: *------------------------------------------- select bands go top *------------------------------------------- * This difference between object types * was determined through empirical testing. * It may have some flaws. *------------------------------------------- do case case inlist(oRec.OBJTYPE, FRX_OBJTYP_LABEL ) locate for R_STOP > oRec.P_STOP otherwise locate for R_STOP >= oRec.P_STOP endcase if found() *------------------------------------------- * an object cannot end in a band above * that in which it starts: *------------------------------------------- if BAND_SEQ >= oRec.BAND_SEQ oRec.END_BAND_ID = UNIQUEID else oRec.END_BAND_ID = oRec.START_BAND_ID endif else *--------------------------------------------------- * The object runs off the bottom of the band array. * Force the object to end in the Page Footer: *--------------------------------------------------- locate for OBJCODE = FRX_OBJCOD_PAGEFOOTER if found() oRec.END_BAND_ID = UNIQUEID endif endif *--------------------------------------------------- * Show both start and end bands against the object: *--------------------------------------------------- if oRec.END_BAND_ID <> oRec.START_BAND_ID oRec.BANDLABEL = oRec.BANDLABEL + "..." + trim(BANDLABEL) endif *--------------------------------------------------- * If an object starts and ends in two different bands... *--------------------------------------------------- if oRec.START_BAND_ID <> oRec.END_BAND_ID select bands locate for UNIQUEID = oRec.START_BAND_ID if empty( REL_BAND_ID ) or REL_BAND_ID # oRec.END_BAND_ID *--------------------------------------------------- * ...that are not a matched Header-Footer pair, * then the object is forced into the PageHeader band. *--------------------------------------------------- locate for OBJTYPE = FRX_OBJTYP_BAND ; and OBJCODE = FRX_OBJCOD_PAGEHEADER oRec.START_BAND_ID = UNIQUEID do case case inlist(oRec.OBJTYPE, FRX_OBJTYP_RECTANGLE ) oRec.BANDLABEL = TARGET_UNPREDICTABLE_LOC + " (" + trim(oRec.BANDLABEL) + ")" otherwise oRec.BANDLABEL = TARGET_FORCED_PAGEHEADER_LOC + " (" + trim(oRec.BANDLABEL) + ")" endcase oRec.BAND_SEQ = 99 oRec.END_BAND_ID = "" oRec.BAND_OFFSET = oRec.P_START - P_START && real start, not the run-time one endif endif else *-------------------------------------------------------- * Determine the object's location, start and end bands, * as determined by the Report Designer: *-------------------------------------------------------- select bands locate for P_START <= oRec.P_START ; and P_STOP >= oRec.P_START if found() oRec.START_BAND_ID = UNIQUEID oRec.BAND_OFFSET = oRec.P_START - P_START oRec.BANDLABEL = trim(BANDLABEL) oRec.BAND_SEQ = BAND_SEQ endif select bands locate for P_START <= oRec.P_STOP ; and P_STOP >= oRec.P_STOP if found() oRec.END_BAND_ID = UNIQUEID if oRec.END_BAND_ID <> oRec.START_BAND_ID oRec.BANDLABEL = oRec.BANDLABEL + " - " + trim(BANDLABEL) endif endif endif endif insert into (m.tcDestAlias) from name oRec select (m.srcAlias) return ENDPROC PROCEDURE createobjectcursor && Creates a cursor (default alias: "objects") of records for each object record in the report alias. Parameters: [ cFrxAlias [, cDestinationAlias [, iFilterMode ]]] *======================================================= * CreateObjectCursor() * * Creates a cursor (alias: objects) of records for each * object in the report. * Returns .T. if successful. * Calls .createBandCursor() if necessary. *======================================================= lparameter tcFrxAlias, tcDestAlias, tiFilter, tlRuntimeMode *------------------------------------------------------- * Ensure parameters are initialised appropriately: *------------------------------------------------------- if vartype( m.tiFilter ) = "L" tiFilter = OBJCSR_ALL_OBJECTS_IGNORE_GROUPS endif if empty( m.tcDestAlias ) tcDestAlias = 'objects' endif if empty( m.tcFrxAlias ) tcFrxAlias = 'frx' endif local curSel, curRec curSel = select() if not used(m.tcFrxAlias) return .F. else curRec = recno(m.tcFrxAlias) endif if not used('bands') if not THIS.createBandCursor(m.tcFrxAlias) select (m.curSel) return .F. endif endif *------------------------------------------------------- * create the objects cursor: *------------------------------------------------------- if used( m.tcDestAlias ) use in (m.tcDestAlias) endif select 0 create cursor &tcDestAlias ( ; UNIQUEID c(10), ; OBJTYPE N(2,0), ; OBJCODE n(3,0), ; EXPR M, ; VPOS n(9,3), ; HPOS n(9,3), ; HEIGHT n(9,3),; WIDTH n(9,3),; OBJNAME c(50),; LOCALE_ID i, ; P_START i, ; P_STOP i, ; P_HEIGHT i, ; BAND_OFFSET i, ; START_BAND_ID c(10),; END_BAND_ID c(10), ; BANDLABEL c(75), ; SELECTED l, ; OBJ_PICT c(12), ; BAND_SEQ i, ; REC_NO i, ; TYPE_SEQ i, ; CTYPE c(10) ) *------------------------------------------------------- * Select object records from the FRX: *------------------------------------------------------- do case case m.tiFilter = OBJCSR_ALL_OBJECTS_IGNORE_GROUPS *------------------------------------------------- * all object records (ignoring grouped items): *------------------------------------------------- select (m.tcFrxAlias) scan for inlist( OBJTYPE, FRX_OBJTYP_LABEL, FRX_OBJTYP_FIELD, ; FRX_OBJTYP_LINE, FRX_OBJTYP_RECTANGLE, FRX_OBJTYP_PICTURE ) and ; not deleted() and ; PLATFORM = FRX_PLATFORM_WINDOWS THIS.createObjCursorRecord( tcDestAlias, m.tlRuntimeMode ) endscan case m.tiFilter = OBJCSR_SHOW_ALL_OBJECTS *------------------------------------------------- * All objects+grouped objects in report: * Show groups as separate objects * do not expand grouped objects *------------------------------------------------- select (m.tcFrxAlias) scan for inlist( OBJTYPE, FRX_OBJTYP_LABEL, FRX_OBJTYP_FIELD, ; FRX_OBJTYP_LINE, FRX_OBJTYP_RECTANGLE, FRX_OBJTYP_PICTURE ) and ; not deleted() and ; PLATFORM = FRX_PLATFORM_WINDOWS THIS.createObjCursorRecord( tcDestAlias, m.tlRuntimeMode ) endscan *------------------------------------------------- * Now remove the grouped ones *------------------------------------------------- local iGrpStart, iGrpCount scan for OBJTYPE = FRX_OBJTYP_GROUP iGrpStart = VPOS iGrpCount = HPOS select (m.tcDestAlias) go m.iGrpStart delete next m.iGrpCount select (m.tcFrxAlias) endscan *------------------------------------------------- * Now add the groups themselves *------------------------------------------------- scan for OBJTYPE = FRX_OBJTYP_GROUP THIS.createObjCursorRecord( tcDestAlias, m.tlRuntimeMode ) endscan case m.tiFilter = OBJCSR_FILTER_ON_SELECTED *------------------------------------------------- * All currently selected object records: * do not show grouped objects * Show groups as separate objects *------------------------------------------------- select (m.tcFrxAlias) scan for inlist( OBJTYPE, FRX_OBJTYP_LABEL, FRX_OBJTYP_FIELD, ; FRX_OBJTYP_LINE, FRX_OBJTYP_RECTANGLE, FRX_OBJTYP_PICTURE ) and ; not deleted() and ; CURPOS and ; PLATFORM = FRX_PLATFORM_WINDOWS THIS.createObjCursorRecord( tcDestAlias, m.tlRuntimeMode ) endscan *------------------------------------------------- * Now add any selected grouped items themselves: *------------------------------------------------- scan for OBJTYPE = FRX_OBJTYP_GROUP and ; CURPOS and ; PLATFORM = FRX_PLATFORM_WINDOWS THIS.createObjCursorRecord( tcDestAlias, m.tlRuntimeMode ) endscan endcase go top in (m.tcDestAlias) THIS.goRec(m.curRec, m.tcFrxAlias) select (m.curSel) return .T. ENDPROC PROCEDURE createvariablecursor && Creates a cursor with the alias "vars" containing records of information for each report variable in the report. Parameters: [cFrxAlias] *======================================================= * CreateVariableCursor() * * Creats a cursor with the alias "vars" containing records * of information for each report variable in the report. * Used mostly by panelVariables class * * Returns .T. if successfully created. *======================================================= lparameter tcFrxAlias if empty( m.tcFrxAlias ) tcFrxAlias = 'frx' endif if not used(m.tcFrxAlias) return .F. endif curSel = select() *------------------------------------------------------- * This is needed later on: *------------------------------------------------------- if not used("reset_on") THIS.createCalcResetOnCursor() endif *------------------------------------------------------- * create the vars cursor: *------------------------------------------------------- if used("vars") use in vars endif select 0 create cursor vars ( ; UNIQUEID C(10), ; VARNAME M, ; VALUE_TO_STORE M, ; INITIAL_VALUE M, ; RELEASE_VAR L, ; CALC_TYPE N(2,0), ; RESET_ON N(2,0), ; REC_NO I ) *------------------------------------------------------- * Initialise stuff: *------------------------------------------------------- local iCurRec, iResetOn iCurRec = recno(m.tcFrxAlias) *------------------------------------------------------- * Scan through the variable records, building up the information * and then insert a new record into the vars cursor: *------------------------------------------------------- select (m.tcFrxAlias) scan for OBJTYPE = FRX_OBJTYP_VARIABLE and ; not deleted() and ; PLATFORM = FRX_PLATFORM_WINDOWS select reset_on locate for RESETTOTAL = &tcFrxAlias..RESETTOTAL insert into vars values ( ; &tcFrxAlias..UNIQUEID, ; &tcFrxAlias..NAME, ; &tcFrxAlias..EXPR, ; &tcFrxAlias..TAG, ; &tcFrxAlias..UNIQUE, ; &tcFrxAlias..TOTALTYPE+1, ; recno("reset_on"), ; recno(m.tcFrxAlias) ) endscan *------------------------------------------------------- * Restore the record pointer in FRX (important) *------------------------------------------------------- THIS.goRec(m.icurRec, m.tcFrxAlias) select (m.curSel) return .T. ENDPROC PROCEDURE frutopixels && Returns the pixel value of a given measurement in FRUs. *======================================================= * FruToPixels( num ) * * returns the value in pixels of a given FRU measurement. *======================================================= lparameter nFRU local iPixels *------------------------------------ * Fixed for SP1: * use the .screenDPI property instead of * the hard-coded 96 dpi value. The ReportBuilder * client will reset .screenDPI to 96 so that it * is correct for design-time report designer use. *------------------------------------ *iPixels = round((m.nFRU * 96)/10000,3) iPixels = round((m.nFRU * this.screenDPI)/10000,3) return int( m.iPixels ) ENDPROC PROCEDURE getbandfor && Returns a SCATTER NAME band object for the specified object ID. Calls .createObjectCursor() if necessary. Parameters: cObjectID [, lStart] *======================================================= * GetBandFor( UNIQUEID [, lStart ] ) * * Returns a SCATTER NAME band object for the specified * object. * Calls .createObjectCursor() if necessary. *======================================================= lparameters cObjectId, lStart if not used('frx') return null endif if parameters() < 2 lStart = .T. endif if not used('objects') THIS.createObjectCursor() endif local curSel, iRec, oBand curSel = select() oBand = null select objects locate for UNIQUEID = m.cObjectId if found() select bands if m.lStart locate for UNIQUEID = objects.START_BAND_ID else locate for UNIQUEID = objects.END_BAND_ID endif endif if not found() go bottom endif *scatter fields UNIQUEID, OBJCODE, BANDLABEL, RESETTOTAL, REC_NO ; * name oBand scatter name oBand select (m.curSel) return oBand ENDPROC PROCEDURE getfrutextheight && Reutrns the height of a given string in FRUs. Parameters: cText, cTypeface, iSize [, cStyle ] *======================================================= * GetFruTextHeight( cText, cTypeface, iSize [, cStyle ] ) * * Returns the height of a given string in FRUs *======================================================= lparameters cText, cTypeFace, iSize, cStyle if parameters() < 4 cStyle = "N" endif *------------------------------------------------------- * obtain text height in pixels: *------------------------------------------------------- local iHeight iHeight = fontmetric(1, cTypeFace, iSize, cStyle ) *------------------------------------------------------- * convert pixels to FRU: *------------------------------------------------------- *------------------------------------ * Fixed for SP1: * use the .screenDPI property instead of * the hard-coded 96 dpi value. The ReportBuilder * client will reset .screenDPI to 96 so that it * is correct for design-time report designer use. *------------------------------------ return this.pixelsToFru( m.iHeight ) ENDPROC PROCEDURE getfrutextwidth && Returns the width of a given string in FRUs. Parameters: cText, cTypeface, iSize [, cStyle ] *======================================================= * GetFruTextWidth( cText, cTypeface, iSize [, cStyle ] ) * * Returns the width of a given string in FRUs *======================================================= lparameters cText, cTypeFace, iSize, cStyle if parameters() < 4 cStyle = "N" endif *------------------------------------------------------- * obtain text width in pixels. Remember that txtwidth() returns * number of equivalent average characters, so must multiply by * the overall average character width: *------------------------------------------------------- local iWidth iWidth = txtwidth( cText, cTypeFace, iSize, cStyle ) iWidth = m.iWidth * fontmetric(6, cTypeFace, iSize, cStyle ) *------------------------------------------------------- * convert pixels to FRU using screen dpi: *------------------------------------------------------- *------------------------------------ * Fixed for SP1: * use the .screenDPI property instead of * the hard-coded 96 dpi value. The ReportBuilder * client will reset .screenDPI to 96 so that it * is correct for design-time report designer use. *------------------------------------ return this.pixelsToFru( m.iWidth ) ENDPROC PROCEDURE getfrxtimestamp && Returns a FOX system file timestamp from a datetime value, any data type. Parameter: [vDateTime] #define DEBUGGING .F. *======================================================= * GetFrxTimeStamp( vDateTime ) * * Returns a FOX system file timestamp * from a date time value, any data type * * Calls: intToBin(), binToInt() from browser.scx code *======================================================= lparameter tvDateTime *------------------------------------------------------- * Default to current datetime *------------------------------------------------------- LOCAL ltDateTime, lvFoxTimeStamp, lvTemp ltDateTime = CTOT(TRANSFORM(tvDateTime)) IF EMPTY(ltDateTime) ltDateTime = DATETIME() ENDIF #IF DEBUGGING ACTI SCREEN CLEAR ? ltDateTime #ENDIF *------------------------------------------------------- * bits 4-0, seconds in two-second increments *------------------------------------------------------- lvTemp = SEC(ltDateTime) / 2 lvFoxTimeStamp = PADL(RIGHT(THIS.IntToBin(lvTemp),5),5,"0") #IF DEBUGGING ? lvTemp ? lvFoxTimeStamp ? #ENDIF *------------------------------------------------------- * bits 10-5, minutes *------------------------------------------------------- lvTemp = MINUTE(ltDateTime) lvFoxTimeStamp = PADL(RIGHT(THIS.IntToBin(lvTemp),6),6,"0") + lvFoxTimeStamp #IF DEBUGGING ? lvTemp ? lvFoxTimeStamp ? #ENDIF *------------------------------------------------------- * bits 15-11, hours *------------------------------------------------------- lvTemp = HOUR(ltDateTime) lvFoxTimeStamp = PADL(RIGHT(THIS.IntToBin(lvTemp),5),5,"0") + lvFoxTimeStamp #IF DEBUGGING ? lvTemp ? lvFoxTimeStamp ? #ENDIF *------------------------------------------------------- * bits 20-16, days *------------------------------------------------------- lvTemp = DAY(ltDateTime) lvFoxTimeStamp = PADL(RIGHT(THIS.IntToBin(lvTemp),5),5,"0") + lvFoxTimeStamp #IF DEBUGGING ? lvTemp ? lvFoxTimeStamp ? #ENDIF *------------------------------------------------------- * bits 24-21, months *------------------------------------------------------- lvTemp = MONTH(ltDateTime) lvFoxTimeStamp = PADL(RIGHT(THIS.IntToBin(lvTemp),4),4,"0") + lvFoxTimeStamp #IF DEBUGGING ? lvTemp ? lvFoxTimeStamp ? #ENDIF *------------------------------------------------------- * bits 31-25, years with a 1980 offset *------------------------------------------------------- lvTemp = YEAR(ltDateTime)-1980 lvFoxTimeStamp = PADL(RIGHT(THIS.IntToBin(lvTemp),7),7,"0") + lvFoxTimeStamp #IF DEBUGGING ? lvTemp ? LEN(lvFoxTimeStamp) ? lvFoxTimeStamp ? #ENDIF lvFoxTimeStamp = THIS.BinToInt(lvFoxTimeStamp) RETURN lvFoxTimeStamp ENDPROC PROCEDURE getmetadatadomdoc && Returns a reference to an MSXml.DomDocument with the metadata xml loaded. Assumes FRX is located on desired record. *======================================================= * GetMetadataDomDoc( ) * * Returns a reference to an MSXml.DomDocument with the * XML stored in the STYLE column of the current record in * the frx cursor. Default alias is "frx". * * Check for null in case of errors. * * If the STYLE field is empty, a default XML document is * returned. *======================================================= lparameter lcFrxAlias local curSel, cXml, oDom if empty( m.lcFrxAlias ) lcFrxAlias = 'frx' endif if not used(m.lcFrxAlias) return .null. endif curSel = select() select (m.lcFrxAlias) *------------------------------------------------------ * Extract the metadata XML from STYLE field of frx cursor * record, and put default xml in if its empty: *------------------------------------------------------ cXml = STYLE if empty( m.cXml ) text noshow to m.cXml endtext replace STYLE with m.cXml endif select (m.curSel) *------------------------------------------------------ * Create a DomDocument and load up the xml. *------------------------------------------------------ oDom = createobject("MSXml.DomDocument") oDom.loadXML( m.cXml ) return oDom ENDPROC PROCEDURE getobjectsinband && Returns a collection of UNIQUEIDs (or RECNOs) for each object in a given band. Calls .createObjectCursor() if necessary. Parameters: cBandId [, lRecnos] *======================================================= * GetObjectsInBand( UNIQUEID [, lRecnos ] ) * * returns a Collection of UNIQUEID values for each object * in a given Band. * Calls .createObjectCursor() if necessary. *======================================================= lparameter cBandId, lRecnos local oBandObjects, curSel curSel = select() oBandObjects = newobject("Collection") if not used("objects") THIS.createObjectCursor() endif select objects scan if objects.START_BAND_ID = m.cBandId *------------------------------------------------------- * the object is defined as starting in this band *------------------------------------------------------- if m.lRecnos oBandObjects.Add( objects.REC_NO ) else oBandObjects.Add( objects.UNIQUEID ) endif endif endscan select (m.curSel) return oBandObjects ENDPROC PROCEDURE getreportattribute && Returns the value of a given report/header attribute. The FRX cursor must be open. Parameters: cToken [, iAlternate] *======================================================= * GetReportAttribute( cToken [, iAlt] ) * * Returns the value of a given report (or header) attribute. * The FRX cursor must be open. *======================================================= lparameters cKey, iAlt if parameters()<2 iAlt = 0 endif if not used('frx') return .F. endif local curSel, curRec, vRetVal curSel = select() select frx curRec = recno() locate for OBJTYPE = FRX_OBJTYP_REPORTHEADER and ; PLATFORM = FRX_PLATFORM_WINDOWS do case case upper(m.cKey) = "UNITS" if m.iAlt = 0 vRetVal = RULER else do case case RULER = FRX_RULER_FRUS vRetVal = UNITS_FRU_LOC case RULER = FRX_RULER_INCHES vRetVal = UNITS_INCHES_LOC case RULER = FRX_RULER_METRIC vRetVal = UNITS_METRIC_LOC case RULER = FRX_RULER_PIXELS vRetVal = UNITS_PIXELS_LOC case RULER = FRX_RULER_CHARACTERS vRetVal = UNITS_CHARACTERS_LOC otherwise vRetVal = "?" endcase endif case upper(m.cKey) = "MULTICOLUMN" *------------------------------------------------------- * If a report has multiple columns, * then the column width is not the default: *------------------------------------------------------- *vRetVal = (WIDTH <> -1) *------------------------------------------------------- * could also check for existence of ColumnHeader: *------------------------------------------------------- *vRetVal = THIS.hasBand(OBJCODE_COLHEADER) *------------------------------------------------------- * or just how many columns? *------------------------------------------------------- vRetVal = (VPOS > 1) case upper(m.cKey) = "COLUMNCOUNT" vRetVal = VPOS case upper(m.cKey) = "PROTECTION" vRetVal = ORDER case upper(m.cKey) = "SNAKED_COLUMNS" vRetVal = BOTTOM *case upper(m.cKey) = "DEFAULT FONT" endcase THIS.goRec( m.curRec, 'frx') select (m.curSel) return m.vRetVal ENDPROC PROCEDURE getselectedobjectcount && Returns the number of selected objects in the frx cursor. Parameter: [cFrxAlias] *======================================================= * getSelectedObjectCount( ) * *======================================================= lparameter lcFrxAlias if empty( m.lcFrxAlias ) lcFrxAlias = "frx" endif local cursel, curRec, selCount curSel = select() select (m.lcFrxAlias) curRec = recno() count for CURPOS and ; PLATFORM = FRX_PLATFORM_WINDOWS and ; OBJTYPE <> 1 ; to m.selCount go m.curRec select (m.curSel) return m.selCount ENDPROC PROCEDURE gettargettypetext && Returns a readable string version of a target Type+Code. Parameters: iObjectType, iObjectCode *======================================================= * GetTargetTypeText( OBJTYPE, OBJCODE ) * * Returns a readable string version of a target Type/Code *======================================================= lparameters nObjType, nObjCode if parameters() = 0 nObjType = -1 nObjCode = -1 endif do case case m.nObjType = FRX_OBJTYPE_MULTISELECT return TARGET_MULTISELECT_LOC case m.nObjType = FRX_OBJTYP_COMMENT return TARGET_REPORT_COMMENT_LOC case m.nObjType = FRX_OBJTYP_REPORTHEADER return TARGET_REPORT_GLOBAL_LOC case m.nObjType = 2 return TARGET_WORKAREA_LOC case m.nObjType = 3 return TARGET_INDEX_LOC case m.nObjType = 4 return TARGET_RELATION_LOC case m.nObjType = FRX_OBJTYP_LABEL return TARGET_TEXT_LABEL_LOC case m.nObjType = FRX_OBJTYP_LINE return TARGET_LINE_LOC case m.nObjType = FRX_OBJTYP_RECTANGLE return TARGET_BOX_LOC case m.nObjType = FRX_OBJTYP_FIELD return TARGET_FIELD_LOC case m.nObjType = FRX_OBJTYP_BAND do case case m.nObjCode = FRX_OBJCOD_TITLE return TARGET_TITLE_LOC case m.nObjCode = FRX_OBJCOD_PAGEHEADER return TARGET_PAGE_HEADER_LOC case m.nObjCode = FRX_OBJCOD_COLHEADER return TARGET_COL_HEADER_LOC case m.nObjCode = FRX_OBJCOD_GROUPHEADER return TARGET_GROUP_HEADER_LOC case m.nObjCode = FRX_OBJCOD_DETAIL return TARGET_DETAIL_LOC case m.nObjCode = FRX_OBJCOD_GROUPFOOTER return TARGET_GROUP_FOOTER_LOC case m.nObjCode = FRX_OBJCOD_COLFOOTER return TARGET_COL_FOOTER_LOC case m.nObjCode = FRX_OBJCOD_PAGEFOOTER return TARGET_PAGE_FOOTER_LOC case m.nObjCode = FRX_OBJCOD_SUMMARY return TARGET_SUMMARY_LOC case m.nObjCode = FRX_OBJCOD_DETAILHEADER return TARGET_DETAIL_HEADER_LOC case m.nObjCode = FRX_OBJCOD_DETAILFOOTER return TARGET_DETAIL_FOOTER_LOC otherwise return TARGET_UNKNOWN_BAND_LOC endcase case m.nObjType = FRX_OBJTYP_GROUP return TARGET_GROUPED_LOC case m.nObjType = FRX_OBJTYP_PICTURE return TARGET_PICTURE_LOC case m.nObjType = FRX_OBJTYP_VARIABLE return TARGET_VARIABLE_LOC case m.nObjType = FRX_OBJTYP_PDRIVER return TARGET_PDRIVER_LOC case m.nObjType = FRX_OBJTYP_FONTRES return TARGET_FONTRESO_LOC case m.nObjType = FRX_OBJTYP_DATAENV return TARGET_DATAENV_LOC case m.nObjType = FRX_OBJTYP_DATAOBJ return TARGET_CURSOR_LOC otherwise return TARGET_UNKNOWN_LOC endcase ENDPROC PROCEDURE gettimestampstring && Returns a readable string version of a Fox system timestamp, using current date settings. Parameter: iStamp *======================================================= * GetTimeStampString( iStamp ) * * Returns a readable string version of a Fox system * timestamp, using current date settings *======================================================= lparameter tiStamp IF EMPTY(tiStamp) OR TYPE("tiStamp") # "N" RETURN "" ENDIF LOCAL lnYearoffset,lcYear,lcMonth,; lcDay,lcHour,lcMinute,lcSecond *------------------------------------------------------- * lnYearoffset = INT(tiStamp/2^25) && bits 31-25 *------------------------------------------------------- lnYearoffset = BITRSHIFT(tiStamp,25) lcYear = STR(1980 + lnYearoffset) *------------------------------------------------------- * lcMonth = STR(INT(tiStamp/2^21) % 2^4) && bits 24-21 *------------------------------------------------------- lcMonth = STR(BITRSHIFT(tiStamp,21) % 2^4) *------------------------------------------------------- * lcDay = STR(INT(tiStamp/2^16) % 2^5) && bits 20-16 *------------------------------------------------------- lcDay = STR(BITRSHIFT(tiStamp,16) % 2^5) *------------------------------------------------------- * lcHour = STR(INT(tiStamp/2^11) % 2^5) && bits 15-11 *------------------------------------------------------- lcHour = STR(BITRSHIFT(tiStamp,11) % 2^5) *------------------------------------------------------- * lcMinute = STR(INT(tiStamp/2^5) % 2^6) && bits 10-5 *------------------------------------------------------- lcMinute = STR(BITRSHIFT(tiStamp,5) % 2^6) *------------------------------------------------------- * lcSecond = STR(INT(tiStamp%2^5) * 2) && bits 4-0 (two-second increments) *------------------------------------------------------- lcSecond = STR(BITLSHIFT(tiStamp%2^5,1)) RETURN TTOC({^&lcYear./&lcMonth./&lcDay. &lcHour.:&lcMinute.:&lcSecond.}) ENDPROC PROCEDURE getunitvaluefromfru && Returns a given unit value for a given value in FRUs, depending on the units. Parameters: nFruValue, iUnits *------------------------------------------------- * Return a given unit value for a given value in FRUs, * depending on the Units: *------------------------------------------------- lparameter nFruValue, iUnits do case case inlist( m.iUnits, FRX_RULER_INCHES, FRX_RULER_OFF) return (m.nFruValue / 10000) case m.iUnits = FRX_RULER_METRIC return (m.nFruValue / (0.3937 * 10000)) case m.iUnits = FRX_RULER_CHARACTERS *--------------------------------------------------------- * 1 char = 833.33 FRU * 1 char = 1/12 inch *--------------------------------------------------------- return (m.nFruValue / 833.33) *case THIS.units = FRX_RULER_PIXELS otherwise *--------------------------------------------------------- * Designer fixed at 96 dpi *--------------------------------------------------------- return (m.nFruValue * 96 / 10000 ) endcase ENDPROC PROCEDURE gorec && Restores record pointer with bounds checking. Parameters: i, cAlias *======================================================= * GoRec( i, cAlias ) * * restores record pointer with bounds checking *======================================================= lparameter iRec, cAlias if parameters() < 2 cAlias = alias() endif if between( iRec, 1, reccount(m.cAlias) ) go m.iRec in (m.cAlias) endif return ENDPROC PROCEDURE hasband && Returns .T. if the report has the specified band type. Calls .createBandCursor() if necessary. Parameters: iObjCode *======================================================= * HasBand( objCode ) * * Returns .T. if the report has the specified type of * band record. * Calls .createBandCursor() if necessary. *======================================================= lparameter iObjCode if not used('bands') THIS.createBandCursor() endif local curSel, lRetVal curSel = select() lRetVal = .F. select bands locate for OBJCODE = m.iObjCode if found() lRetVal = .T. endif select (m.curSel) return m.lRetVal ENDPROC PROCEDURE hasdetailheader && Returns .T. if the specified detail band has an associated detail header band. Calls .createBandCursor() if necessary. Parameters: cUniqueId *======================================================= * HasDetailHeader( UNIQUED ) * * Returns .T. if the specifed Detail band has an associated * "detail header" band. * * Calls .createBandCursor() if necessary. *======================================================= lparameter cUniqueId if not used('bands') THIS.createBandCursor() endif local curSel, lRetval curSel = select() lRetVal = .F. select bands locate for UNIQUEID = m.cUniqueId skip -1 lRetVal = (OBJTYPE = FRX_OBJTYP_BAND and OBJCODE = FRX_OBJCOD_DETAILHEADER) select (m.curSel) return m.lRetVal ENDPROC PROCEDURE hasprotectionflag && Returns .T. if the given binary data contains a specific bit set. Parameters: cBytes, iBit *======================================================= * HasProtectionFlag( cBytes, iBit ) * * Returns .T. if the given binary data contains a specific * bit set to true. * * Uses: BinstringToInt() *======================================================= lparameters cBinstring, iFlagBit local iProtFlags iProtFlags = THIS.BinstringToInt( m.cBinstring ) return bittest( m.iProtFlags, m.iFlagBit ) ENDPROC PROCEDURE Init *======================================================= * Init() *======================================================= *--------------------------------- * Determine the screen DPI: *--------------------------------- #define LOGPIXELSX 88 declare integer GetDeviceCaps in WIN32API integer HDC, integer item declare integer GetDC in WIN32API integer hWnd *declare integer DeleteDC in WIN32API integer HDC declare integer ReleaseDC in WIN32API integer hWnd, integer HDC local hdc, screenDPI hdc = GetDC(0) THIS.screenDPI = GetDeviceCaps( m.hdc, LOGPIXELSX ) ReleaseDC( 0, m.hdc ) *DeleteDC( m.hdc ) *------------------------------------ * Fixed for SP1: * The ReportBuilder client will * reset .ScreenDPI to 96 so that it is correct * for design-time report designer use, even if * at run-time the app is running on higher-res * screens. *------------------------------------ ENDPROC PROCEDURE insertband && Inserts a band record into an frx cursor. Assumes that the FRX is currently selected and that the record pointer is located appropriately. Parameter: iObjCode *======================================================= * InsertBand() * * Inserts a band into an FRX. * Assumes that the record pointer is located appropriately. *======================================================= lparameters liObjCode insert blank replace ; PLATFORM with FRX_PLATFORM_WINDOWS, ; UNIQUEID with sys(2015), ; OBJTYPE with FRX_OBJTYP_BAND, ; OBJCODE with m.liObjCode, ; NOREPEAT with .F., ; PAGEBREAK with .F., ; COLBREAK with .F., ; RESETPAGE with .F., ; PLAIN with .F., ; CURPOS with .F. return ENDPROC PROCEDURE insertdataenvrecord && Inserts a data environment object record into an FRX cursor. Assumes that the record pointer is appropriately located. Parameters: ID, NAME, EXPR, CODE *======================================================= * InsertDataEnvRecord( ID, NAME, EXPR, CODE ) * * Inserts a data-environment object record into an FRX. * Assumes that the record pointer is located appropriately. *======================================================= lparameters liObjType, lcName, lcExpr, lcMethods insert blank replace ; PLATFORM with FRX_PLATFORM_WINDOWS, ; OBJTYPE with m.liObjType, ; NAME with m.lcName, ; EXPR with m.lcExpr, ; TAG with m.lcMethods, ; ENVIRON with .F., ; CURPOS with .F. return ENDPROC PROCEDURE insertdetailband && Inserts a detail band into the frx cursor. Assumes: the record pointer is located appropriately. Parameters: none *======================================================= * InsertDetailBand() * * Inserts a detail band into an FRX. * Assumes that the record pointer is located appropriately. *======================================================= THIS.insertBand( FRX_OBJCOD_DETAIL ) return ENDPROC PROCEDURE insertdetailheaderfooter && Inserts detail header and footer bands into the frx cursor. Assumes: record pointer is located on the detail band record. Parameters: none *======================================================= * InsertDetailHeaderFooter() * * Inserts Detail Header and Footer bands into the FRX. * Assumes: we are positioned on the detail band: *======================================================= insert blank replace ; PLATFORM with FRX_PLATFORM_WINDOWS, ; UNIQUEID with sys(2015), ; OBJTYPE with FRX_OBJTYP_BAND, ; OBJCODE with FRX_OBJCOD_DETAILFOOTER skip -1 insert before blank replace ; PLATFORM with FRX_PLATFORM_WINDOWS, ; UNIQUEID with sys(2015), ; OBJTYPE with FRX_OBJTYP_BAND, ; OBJCODE with FRX_OBJCOD_DETAILHEADER skip return ENDPROC PROCEDURE insertsummaryband && Inserts a summary band into the frx cursor. Parameters: lBreakToNewPage, lPageHeader, lPageFooter *======================================================= * InsertSummaryBand( lNewPage, lPageHeader, lPageFooter ) * * Inserts a Summary band into an FRX *======================================================= lparameter lNewPage, lPageHeader, lPageFooter locate for OBJTYPE = FRX_OBJTYP_BAND and ; OBJCODE = FRX_OBJCOD_PAGEFOOTER THIS.insertBand( FRX_OBJCOD_SUMMARY ) replace ; HEIGHT with 5000.000, ; PAGEBREAK with m.lNewPage, ; EJECTBEFOR with m.lPageHeader, ; EJECTAFTER with m.lPageFooter return ENDPROC PROCEDURE inserttitleband && Inserts a title band into the frx cursor. Parameter: lBreakToNewPage *======================================================= * InsertTitleBand( lNewPage ) * * Inserts a Title band record into the FRX *======================================================= lparameter lNewPage go top *------------------------------------------------------- * will be inserted as the second record (as is appropriate) *------------------------------------------------------- THIS.insertBand( FRX_OBJCOD_TITLE ) replace ; HEIGHT with 5000.000, ; PAGEBREAK with m.lNewPage return ENDPROC PROCEDURE inttobin && Returns a binary form of an integer. Parameter: iNumber *======================================================= * IntToBin( int ) * * Returns a binary form of an integer *======================================================= LPARAMETERS tnInteger LOCAL lnInteger,lcBinary,lnDivisor,lnCount IF EMPTY(tnInteger) RETURN "0" ENDIF lnInteger=INT(tnInteger) lcBinary="" FOR lnCount = 31 TO 0 STEP -1 lnDivisor=2^lnCount IF lnDivisor>lnInteger lcBinary=lcBinary+"0" LOOP ENDIF lcBinary=lcBinary+IIF((lnInteger/lnDivisor)>0,"1","0") lnInteger=INT(lnInteger-lnDivisor) ENDFOR RETURN lcBinary ENDPROC PROCEDURE inttobinstring && Returns a string of bytes, the binary version of a given integer. *======================================================= * InttoBinString( int ) * * Returns a string of bytes, the binary version of a * given integer. * * BinChar & Integer conversion, based on code by RS *======================================================= lparameter i local cBytes, b cBytes = "" do while m.i <> 0 b = m.i % 256 i = floor( m.i/256 ) cBytes = m.cBytes + chr(m.b) enddo return m.cBytes ENDPROC PROCEDURE pixelstofru && Returns the FRU value of a given measurement in pixels. *======================================================= * PixelsToFru( int ) * * return a value in FRUs of a given pixel dimension *======================================================= lparameter nPix *------------------------------------ * Fixed for SP1: * use the .screenDPI property instead of * the hard-coded 96 dpi value. The ReportBuilder * client will reset .screenDPI to 96 so that it * is correct for design-time report designer use. *------------------------------------ *return round(( nPix * 10000 )/96 , 3 ) return round(( nPix * 10000 )/this.screenDPI , 3 ) ENDPROC PROCEDURE popprintenv && Restores the printer environment from a previously saved cursor. See .PushPrintEnvToCursor() method. Assumes: previously saved cursor is currently selected. *======================================================= * popPrintEnv() * * assumes the FRX file to pop from is selected. *======================================================= result = sys(1037,3) return ENDPROC PROCEDURE pushprintenvtocursor && Saves the current printer environment to a cursor. Parameter: cSavedInAlias *======================================================= * pushPrintEnvToCursor( ) *======================================================= lparameter cRegisterAlias local curSel curSel = select() select * ; from frx ; where .F. ; into cursor (m.cRegisterAlias) ; readwrite append Blank result = sys(1037,2) select (m.curSel) return ENDPROC PROCEDURE setcolumncount && Adds or removes columns (and column header/footer records) from the FRX cursor. Assumes: the frx cursor is selected. Parameters: iColumns *======================================================= * SetColumnCount( iCols ) * * Adds or subtracts columns (and column header/footer * records from the FRX. * Assumes: the current workarea contains the FRX cursor. * Calls: .createObjectCursor() if necessary. *======================================================= lparameter iCols local lHasColBands, curRec, cFrxAlias cFrxAlias = alias() curRec = recno( m.cFrxAlias ) locate for OBJTYPE = FRX_OBJTYP_REPORTHEADER and ; PLATFORM = FRX_PLATFORM_WINDOWS replace VPOS with m.iCols locate for OBJTYPE = FRX_OBJTYP_BAND and ; OBJCODE = FRX_OBJCOD_COLHEADER and ; PLATFORM = FRX_PLATFORM_WINDOWS lHasColBands = found() THIS.goRec(m.curRec, m.cFrxAlias) if (m.lHasColBands and m.iCols = 1) or ; (not m.lHasColBands and m.iCols > 1) THIS.createObjectCursor() do case case (m.lHasColBands and m.iCols = 1) *------------------------------------------------------- * Remove the column header/footer bands: *------------------------------------------------------- locate for OBJTYPE = FRX_OBJTYP_BAND ; and OBJCODE = FRX_OBJCOD_COLHEADER ; and PLATFORM = FRX_PLATFORM_WINDOWS if found() delete endif locate for OBJTYPE = FRX_OBJTYP_BAND ; and OBJCODE = FRX_OBJCOD_COLFOOTER ; and PLATFORM = FRX_PLATFORM_WINDOWS if found() delete endif case (not m.lHasColBands and m.iCols > 1) *------------------------------------------------------- * Insert the column header/footer bands: *------------------------------------------------------- locate for OBJTYPE = FRX_OBJTYP_BAND ; and OBJCODE = FRX_OBJCOD_PAGEHEADER ; and PLATFORM = FRX_PLATFORM_WINDOWS insert blank replace ; PLATFORM with FRX_PLATFORM_WINDOWS, ; UNIQUEID with sys(2015), ; OBJTYPE with FRX_OBJTYP_BAND, ; OBJCODE with FRX_OBJCOD_COLHEADER, ; NOREPEAT with .F., ; PAGEBREAK with .F., ; COLBREAK with .F., ; RESETPAGE with .F., ; PLAIN with .F., ; CURPOS with .F. locate for OBJTYPE = FRX_OBJTYP_BAND ; and OBJCODE = FRX_OBJCOD_PAGEFOOTER ; and PLATFORM = FRX_PLATFORM_WINDOWS insert before blank replace ; PLATFORM with FRX_PLATFORM_WINDOWS, ; UNIQUEID with sys(2015), ; OBJTYPE with FRX_OBJTYP_BAND, ; OBJCODE with FRX_OBJCOD_COLFOOTER, ; NOREPEAT with .F., ; PAGEBREAK with .F., ; COLBREAK with .F., ; RESETPAGE with .F., ; PLAIN with .F., ; CURPOS with .F. endcase *------------------------------------------------------- * Refresh the band cursor: *------------------------------------------------------- THIS.createBandCursor() *------------------------------------------------------- * Using the offsets in object cursor and the * new band heights in band cursor, re-sync the * objects' positions: *------------------------------------------------------- THIS.synchObjectPositions() THIS.goRec(m.curRec, m.cFrxAlias) endif return ENDPROC PROCEDURE stripquotes && Returns a string with embraced string delimiters removed. Parameters: cString lparameter lcValue do case case left( m.lcValue, 1 ) == ["] and right( m.lcValue, 1 ) == ["] return substr( m.lcValue, 2, len( m.lcValue ) - 2 ) case left( m.lcValue, 1 ) == ['] and right( m.lcValue, 1 ) == ['] return substr( m.lcValue, 2, len( m.lcValue ) - 2 ) otherwise return m.lcValue endcase ENDPROC PROCEDURE synchobjectpositions && Updates VPOS values in the FRX cursor for each object, based on which band the object starts in, and the current height of each band as expressed in the bands cursor. Assumes: band and object cursors exist; current alias is frx cursor; no recno restore. *======================================================= * SynchObjectPositions() * * Updates the VPOS values in the FRX for each object, * based on which band the object starts in, and the current * height of each band as expressed in the bands cursor. * * Assumes: * - bands and objects cursors have been prepared, * - current alias is an FRX cursor *======================================================= local curSel, curRec, cUID curSel = select() curRec = recno() *------------------------------------------------------- * Scan through the FRX cursor, * updating the VPOS to maintain the * same relative offset from the band it belongs to. *------------------------------------------------------- scan for inlist( OBJTYPE, ; FRX_OBJTYP_LABEL, FRX_OBJTYP_FIELD, FRX_OBJTYP_LINE, ; FRX_OBJTYP_RECTANGLE, FRX_OBJTYP_PICTURE ) and ; not deleted() and ; PLATFORM = FRX_PLATFORM_WINDOWS cUID = UNIQUEID *------------------------------------------------------- * for each object, restore the relative positions: *------------------------------------------------------- select objects locate for UNIQUEID = cUID select bands locate for UNIQUEID = objects.START_BAND_ID select (curSel) if found("bands") and found("objects") *------------------------------------------------------- * The bands and objects cursors use pixel-based math, so * convert back to FRUs: *------------------------------------------------------- replace VPOS with ; THIS.pixelsToFru( bands.P_START + objects.BAND_OFFSET ) endif endscan THIS.GoRec( m.curRec, alias() ) return ENDPROC ENDDEFINE DEFINE CLASS frxdevicehelper AS custom * *This class knows how to read printer environment information. Usage: * * x = NEWOBJECT( "frxDeviceHelper" ) * IF x.LoadDeviceInfo( cDRIVER, cDEVICE, frx.TAG2 ) * ? x.DpiX * ? x.DpiY * : * etc * *< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" /> #INCLUDE "_frxcursor.h" * *m: loaddeviceinfo && Parses out print device parameters into member properties given specific device information: Parameters: cDriver, cDevice, cDevMode. Assumes current VFP default printer if no parameters specified. *m: loadfromfrx && Loads printer device parameters from an FRX cursor header record. Restores recno and selected alias. Params: [ cFrxAlias ] (assumes "frx" if none specified.) *m: loadfromhdc *m: loadfromstrings && Loads printer device parameters from string variables. Params: cExpr, cTag *p: actualx && Physical width of page in device units *p: actualy && Physical length of page in device units *p: dpix && Logical pixels-per-inch in the X dimension *p: dpiy && Logical pixels-per-inch in the Y dimension *p: errormessage && Occurs when the Valid event returns false (.F.), and provides a means to display an error message. *p: mmx && Horizontal page size in millimeters *p: mmy && Vertical page size in millimeters *p: offsetx && Physical printable page left margin *p: offsety && Physical printable page top margin *p: orientation && 0=Portrait, 1=Landscape *p: printablex && Horizontal page width in pixels *p: printabley && Vertical page length in pixels *p: _memberdata && XML Metadata for customizable properties * * actualx = 0 actualy = 0 dpix = 0 dpiy = 0 errormessage = ("") mmx = 0 mmy = 0 Name = "frxdevicehelper" offsetx = 0 offsety = 0 orientation = 0 printablex = 0 printabley = 0 _memberdata = * PROCEDURE Init declare integer GetLastError ; in win32api declare integer SetLastError ; in win32api ; integer i declare integer CreateIC ; in gdi32 ; string lpszDriver, ; string lpszDevice, ; string lpszOutput, ; string lpdvmInit declare integer GetDeviceCaps ; in gdi32 ; integer hdc, ; integer nIndex declare integer DeleteDC ; in gdi32 ; integer hdc return .T. ENDPROC PROCEDURE loaddeviceinfo && Parses out print device parameters into member properties given specific device information: Parameters: cDriver, cDevice, cDevMode. Assumes current VFP default printer if no parameters specified. lparameters lcDriver, lcDevice, lcDEVMODE THIS.errorMessage = "" local lRetVal lRetVal = .T. if empty( m.lcDevice ) *--------------------------------------- * Use default printer settings: *--------------------------------------- lcDriver = "" lcDevice = set("PRINTER",3) lcDEVMODE = "" endif try local iHDC, vResult iHDC = CreateIC( m.lcDriver, m.lcDevice, chr(0), m.lcDEVMODE ) if m.iHDC = 0 error CREATE_IC_FAILURE_LOC else THIS.LoadFromHDC( m.iHDC ) vResult = DeleteDC( m.iHDC ) endif catch to oErr THIS.errorMessage = oErr.message lRetVal = .F. endtry return m.lRetVal ENDPROC PROCEDURE loadfromfrx && Loads printer device parameters from an FRX cursor header record. Restores recno and selected alias. Params: [ cFrxAlias ] (assumes "frx" if none specified.) lparameter lcFrxAlias THIS.errorMessage = "" local curSel, curRec, lRetVal store .F. to lRetVal if empty(m.lcFrxAlias) lcFrxAlias = "frx" endif if not used( m.lcFrxAlias ) return m.lRetVal endif *-------------------------------- * Save current data/cursor state: *-------------------------------- curSel = select() select (m.lcFrxAlias) curRec = recno() locate for PLATFORM="WINDOWS" and OBJTYPE = 1 and OBJCODE = 53 if found() *--------------------------------------------------- * Get the device info settings: *--------------------------------------------------- lRetVal = THIS.LoadFromStrings( EXPR, TAG2 ) endif *--------------------------------------------------- * Restore data/cursor state: *--------------------------------------------------- if m.curRec <= reccount() go m.curRec endif select (m.curSel) return m.lRetVal ENDPROC PROCEDURE loadfromhdc lparameters tiHDC #define HORZSIZE 4 && Horizontal size in millimeters #define VERTSIZE 6 && Vertical size in millimeters #define HORZRES 8 && Printable page width / Horizontal width in pixels #define VERTRES 10 && Printable page length / Vertical height in pixels #define LOGPIXELSX 88 && DPI / Logical pixels/inch in X dimension #define LOGPIXELSY 90 && DPI / Logical pixels/inch in Y dimension #define PHYSICALWIDTH 110 && Actual page width / Physical Width in device units #define PHYSICALHEIGHT 111 && Actual page length / Physical Height in device units #define PHYSICALOFFSETX 112 && Printable page left margin / Physical Printable Area x margin #define PHYSICALOFFSETY 113 && Printable page top margin / Physical Printable Area y margin with THIS .dpiX = GetDeviceCaps( m.tiHDC, LOGPIXELSX ) .dpiY = GetDeviceCaps( m.tiHDC, LOGPIXELSY ) .OffsetX = GetDeviceCaps( m.tiHDC, PHYSICALOFFSETX ) .OffsetY = GetDeviceCaps( m.tiHDC, PHYSICALOFFSETY ) .PrintableX = GetDeviceCaps( m.tiHDC, HORZRES ) .PrintableY = GetDeviceCaps( m.tiHDC, VERTRES ) .mmX = GetDeviceCaps( m.tiHDC, HORZSIZE ) .mmY = GetDeviceCaps( m.tiHDC, VERTSIZE ) .ActualX = GetDeviceCaps( m.tiHDC, PHYSICALWIDTH ) .ActualY = GetDeviceCaps( m.tiHDC, PHYSICALHEIGHT ) endwith return ENDPROC PROCEDURE loadfromstrings && Loads printer device parameters from string variables. Params: cExpr, cTag lparameters tcEXPR, tcTAG2 local i, cLine, cDriver, lDriver, cDevice, lDevice *--------------------------------------------------- * Read DRIVER and DEVICE values from EXPR *--------------------------------------------------- for i = 1 to memlines(m.tcEXPR) cLine = mline(m.tcEXPR,m.i) do case case m.cLine = "DRIVER=" and not m.lDriver cDriver = substr(m.cLine,8) lDriver = .T. case m.cLine = "DEVICE=" and not m.lDevice cDevice = substr(m.cLine,8) lDevice = .T. endcase if m.lDevice and m.lDriver exit endif endfor *--------------------------------------------------- * Get the device info settings: *--------------------------------------------------- return THIS.LoadDeviceInfo( m.cDriver, m.cDevice, m.tcTAG2 ) ENDPROC ENDDEFINE