Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Complex forms software to replace Delrina FF
Message
De
03/09/2004 14:14:55
 
 
À
03/09/2004 14:05:55
Information générale
Forum:
Visual FoxPro
Catégorie:
Autre
Divers
Thread ID:
00931761
Message ID:
00939258
Vues:
36
Hi Albert. I would be happy to share. I didn't figure it out on my own either, I was fortunate that some UT members were generous enough to help me out when I needed it. I am including the prg that we use and you can pull out the part you need.

I will be very interested in seeing your class when you have it finished! I have been thinking along the same lines as you, but I am still finishing up IVANS integration so I haven't been back focusing on this project yet. I will be soon though and maybe between the two of us and the UT we can develop a reasonable resolution.

Tracy
*:***************************************************************************
*: Procedure file: ACORDPRT.PRG
*:***************************************************************************
*        Purpose: Prints Acord PDF Forms
*         Reqmts: li_acord must be .t. (licensed for acord forms)
*                 li_acordview for preview and printer selection by ctrl-p
*          Usage: llreturn = acordprt([formnumber])
*                 llreturn = acordprt("61NC")
*:**************************************************************************
PARAMETERS xacordform

IF TYPE('xacordform')<>"C" .OR. EMPTY(xacordform)
	RETURN .F.
ENDIF

IF TYPE('li_acord')<>"L" .OR. !li_acord	&& no acord license
	RETURN .F.
ENDIF

IF TYPE('li_acordview')<>"L"
	RETURN .F.
ENDIF

IF TYPE('dopass') ="U"
	dopass = .F.		&& do not process password on acord pdf forms
ENDIF

PRIVATE acordalias, tempfile, pdffile, lcsetsafety, xreturn
acordalias = ALIAS()
tempfile = hdir+xacordform+'.xfdf'
pdffile  = hdir+xacordform+'.pdf'
lcsetsafety = SET('SAFETY')
xreturn = .F.

SET SAFETY OFF

IF FILE(pdffile)		&& .pdf file
	DELETE FILE (pdffile)
ENDIF
IF FILE(tempfile)		&& .xfdf file
	DELETE FILE (tempfile)
ENDIF

*---Open Tables

IF UseFile("ACORDEFN",ddir)
	IF UseFile("ACORDICT",ddir)

		DO AcordGen

		DO AcordExe
		
	ENDIF
ENDIF

*---Close Tables

IF USED("ACORDICT")	&& holds acord/policy profiler data dictionary
	USE IN ACORDICT
ENDIF
IF USED("ACORDEFN")	&& holds field definitions
	USE IN ACORDEFN
ENDIF
IF !EMPTY(acordalias) .AND. ALIAS() <> acordalias
	SELECT (acordalias)
ENDIF
IF !EMPTY(lcsetsafety)
	SET SAFETY &lcsetsafety
ENDIF

*---Cleanup

IF FILE(pdffile)		&& .pdf file
	DELETE FILE (pdffile)
ENDIF
IF FILE(tempfile)		&& .xfdf file
	DELETE FILE (tempfile)
ENDIF

RETURN xreturn

*----------------------------------------------------------------------
PROCEDURE AcordGen

*---Select Fields

SELECT Acordefn.formname, Acordefn.formfield, Acordefn.formorder,;
  Acordict.profiler, 01 AS starttag, 00 AS endtag;
 FROM ;
     acordefn ;
    LEFT OUTER JOIN acordict ;
   ON  Acordefn.formfield = Acordict.formfield;
 WHERE  Acordefn.formname = ( xacordform );
 ORDER BY Acordefn.formorder;
 INTO CURSOR Acordfields READWRITE 

SELECT Acordfields
GOTO TOP

PRIVATE m.output
m.output = FCREATE(tempfile,0)

IF m.output < 0
	=MESSAGEBOX("Could not create '+tempfile+' Acord xml file.",0+16+4096,"ERROR")
	RETURN
ENDIF

*---Initialize local variables

PRIVATE ifields, mfield, mvalue
ifields = 1
mfield = ''
mvalue = ''

DIMENSION fNames[1], fTagNames[1]
fNames = ''
fTagNames = ''

PRIVATE i, iRecCount, iRecNo, iFieldCount, iFieldNo

iRecCount = RECCOUNT()

*---Remove duplicate tags

FOR iRecNo = 1 TO iRecCount

	GOTO iRecNo

	*---Expand field name

	mfield = Acordfields.formfield

	ifields = OCCURS('.', mfield) + 1
	
	DIMENSION fNames[ifields]
	fNames = ''
	
	FOR i = 1 TO ifields
		IF OCCURS('.', mfield) > 0
			fNames[i] = SUBSTR(mfield, 1, AT('.', mfield))
			mfield = SUBSTR(mfield, AT('.', mfield)+1)
		ELSE
			fNames[i] = mfield
			mfield = ''
		ENDIF
	NEXT

	*---Initialize EndTag
	
	REPLACE AcordFields.endtag WITH ifields

	*---Step through the field names.  Skip the last one

	iFieldCount = ifields - 1

	FOR iFieldNo = 1 TO iFieldCount

		IF fNames[iFieldNo] = '*.'
			LOOP
		ENDIF

		GOTO iRecNo

		SKIP

		SCAN REST

			*---Expand field name

			mfield = Acordfields.formfield

			ifields = OCCURS('.', mfield) + 1
	
			DIMENSION fTagNames[ifields]
			fTagNames = ''

			FOR i = 1 TO ifields
				IF OCCURS('.', mfield) > 0
					fTagNames[i] = SUBSTR(mfield, 1, AT('.', mfield))
					mfield = SUBSTR(mfield, AT('.', mfield)+1)
				ELSE
					fTagNames[i] = mfield
					mfield = ''
				ENDIF
			NEXT

			*---Check for Duplicates
			
			IF TYPE('fTagNames[iFieldNo]') <> 'U'
				IF fNames[iFieldNo] == fTagNames[iFieldNo]
					IF iFieldNo = 1
						fTagNames[iFieldNo] = '*.'
						REPLACE Acordfields.starttag WITH Acordfields.starttag + 1
					ELSE
						IF fTagNames[iFieldNo-1] = '*.'
							fTagNames[iFieldNo] = '*.'
							REPLACE Acordfields.starttag WITH Acordfields.starttag + 1
						ENDIF
					ENDIF
				ELSE
					EXIT
				ENDIF
			ELSE
				EXIT
			ENDIF

			*---Save Record
	
			mfield = ''
			FOR i = 1 TO ifields
				IF !EMPTY(fTagNames[i])
					mfield = mfield + fTagNames[i]
				ENDIF
			NEXT
			
			REPLACE Acordfields.formfield WITH mfield

		ENDSCAN
		
	NEXT

	*---Set EndTag

	GOTO iRecNo

	SKIP
	
	IF !EOF('Acordfields')

		ifields = OCCURS('*', AcordFields.formfield)

		SKIP -1	
		REPLACE AcordFields.endtag WITH AcordFields.endtag - ifields
	ENDIF

NEXT

*---Write Header

=FWRITE(m.output, '<?xml version="1.0" encoding="UTF-8"?>'+CHR(10))
=FWRITE(m.output, '<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">'+CHR(10))
=FWRITE(m.output, '<f href="'+xacordform+'.pdf"/>'+CHR(10))
=FWRITE(m.output, '<fields>'+CHR(10))

*---Loop through records

GOTO TOP

SCAN

	*---Expand field name

	mfield = Acordfields.formfield

	ifields = OCCURS('.', mfield) + 1
	
	DIMENSION fNames[ifields]
	fNames = ''
	
	FOR i = 1 TO ifields
		IF OCCURS('.', mfield) > 0
			fNames[i] = SUBSTR(mfield, 1, AT('.', mfield)-1)
			mfield = SUBSTR(mfield, AT('.', mfield)+1)
		ELSE
			fNames[i] = mfield
			mfield = ''
		ENDIF
	NEXT

	*---Write Tags

	FOR i = 1 TO ifields
		IF i >= Acordfields.starttag
			=FWRITE(m.output, '<field name="'+RTRIM(fNames[i])+'">'+CHR(10))
		ENDIF
	NEXT

	*---Write Value

	mvalue = ''
	*--TCH 04/12/2004 check for no value
	*--TCH 05/06/2004 check for .null. value
	IF !ISNULL(AcordFields.profiler) .and. !EMPTY(ALLTRIM(Acordfields.profiler))
		mvalue = EVALUATE(Acordfields.profiler)
	ENDIF
	
	*--TCH 05/05/2004 Strip out reserved words in xml to avoid parsing errors
   *--for example the & in Carrier or Agency name, etc.
	mvalue = XmlEncode(mvalue)
	
	=FWRITE(m.output, '<value>'+RTRIM(mvalue)+'</value>'+CHR(10))

	*---Write End Tags of Last record
	
	FOR i = 1 TO Acordfields.endtag
		=FWRITE(m.output, '</field>'+CHR(10))
	NEXT

ENDSCAN

*---Write Footer and close the file
=FWRITE(m.output, '</fields>'+CHR(10))
=FWRITE(m.output, '</xfdf>'+CHR(10))

=FCLOSE(m.output)

USE IN Acordfields

RETURN

*----------------------------------------------------------------------
PROCEDURE AcordExe

PRIVATE cAppName, lcresult, lcline, llacordok, lcACORDdef
PRIVATE lnpos, lcpath, lcshort

cAppName = ''
lcresult = ''
lcline = ''
llacordok = .T.
lcACORDdef = SYS(5)+SYS(2003)
lnpos = 0
lcshort = ''
lcpath = ''

IF FILE(tempfile)

	IF UseFile("ACORDFRM",ddir,"FORMNAME")
		IF INDEXSEEK(UPPER(ALLTRIM(xacordform)),.T.,'ACORDFRM','FORMNAME')
			=STRTOFILE(ACORDFRM.FORMDATA,pdffile)
		ELSE
			=MESSAGEBOX("Cannot locate form:"+UPPER(ALLTRIM(xacordform))+" in forms table.",0+16+4096,"ERROR - Form Missing in Form Table.")
		ENDIF
		USE IN ACORDFRM
	ENDIF

	IF FILE(pdffile)

		DO DECLexewait

		*--Look for the file in known locations

		lcresult = Acrofind()

		IF EMPTY(lcresult)

			*--Look for AcroRd32.exe first in the registry

			lcresult = readregistrykey()
			IF OCCURS('"',lcresult)>0
				IF TYPE('lcresult')="C" .AND. !EMPTY(lcresult)
					m.cAppName=SUBSTR(lcresult,2,AT('"',lcresult,2)-2)
				ELSE
					m.cAppName = ''
				ENDIF
			ELSE
				m.cAppName = lcresult+"AcroRd32.Exe"
			ENDIF
		ELSE
			m.cAppName = lcresult
		ENDIF

		IF FILE(m.cAppName)	&& AcroRd32.exe

			lcline = " /p /h "
			IF li_acordview	&& preview in acrobat reader so user can select printer by ctrl-p
				lcline = ""
			ENDIF

			SET DEFAULT TO LEFT(hdir,RAT("\",hdir)-1)
			lnpos=(RAT("\",m.cAppName)+1)	&& one position to the right of
			lcshort=''
			lcpath=''
			IF lnpos > 0
				lcshort = UPPER(SUBSTR(m.cAppName,lnpos))	&& grab from lnpos to end
				lcpath  = UPPER(LEFT(m.cAppName,RAT("\",m.cAppName)-1))			&& strip off the extension
			ENDIF

			IF !EMPTY(lcshort) .AND. !EMPTY(lcpath)
				lcpath = "'"+lcpath+"'"
				SET DEFAULT TO &lcpath
				llacordok = ExeWait(lcshort,lcline+hdir+xacordform+'.xfdf',lcpath)
			ELSE
				llacordok = ExeWait( m.cAppName, lcline+xacordform+'.xfdf',hdir)
			ENDIF

			IF !llacordok
				=MESSAGEBOX("Unable to print Acord Form.",0+16+4096,"ERROR")
			ELSE
				WAIT WINDOW "Finished Printing" NOWAIT
			ENDIF

			SET DEFAULT TO &lcACORDdef

		ELSE
			=MESSAGEBOX('Unable to locate Acrobat Reader. Please install and try again',0+16+4096,'ERROR - Acrobat Reader Missing.')
		ENDIF
	
		DO RELexewait
	
	ELSE
		=MESSAGEBOX("Unable to create Acord Form.",0+16+4096,"ERROR - PDF or XFDF Missing.")
	ENDIF
ELSE
	=MESSAGEBOX("Unable to create Acord Form.",0+16+4096,"ERROR - PDF or XFDF Missing.")
ENDIF

xreturn = .T.

RETURN




*---PROCEDURE BELOW SHOULD BE PART OF A CLASS

*---Create ShowMessage method for using the MESSAGEBOX.




*----------------------------------------------------------------------
PROCEDURE DECLexewait  && load required dlls for exewait function

=ADLLS(dllarray)
IF ASCAN(dllarray,'CREATEPROCESS') = 0
	DECLARE INTEGER CreateProcess IN kernel32;
		INTEGER lpAppName, STRING lpCmdLine, INTEGER lpProcAttr,;
		INTEGER lpThrAttr, INTEGER bInhHandles, INTEGER dwCrFlags,;
		INTEGER lpEnvir, INTEGER lpCurDir, ;
		STRING @lpStInfo, STRING @lpProcInfo
ENDIF
IF ASCAN(dllarray,'GETLASTERROR') = 0
	DECLARE INTEGER GetLastError IN kernel32
ENDIF
IF ASCAN(dllarray,"CLOSEHANDLE") = 0
	DECLARE INTEGER CloseHandle IN kernel32 INTEGER hObject
ENDIF
IF ASCAN(dllarray,"GETEXITCODEPROCESS") = 0
	DECLARE INTEGER GetExitCodeProcess IN WIN32API INTEGER hProcess, INTEGER @lpExitCode
ENDIF
IF ASCAN(dllarray,"SLEEP") = 0
	DECLARE Sleep IN kernel32 INTEGER dwMilliseconds
ENDIF

RETURN

*----------------------------------------------------------------------
PROCEDURE RELexewait  && release dlls for exewait function

CLEAR DLLS CreateProcess
CLEAR DLLS GetLastError
CLEAR DLLS CloseHandle
CLEAR DLLS GetExitCodeProcess
CLEAR DLLS Sleep

RETURN

*----------------------------------------------------------------------
FUNCTION buf2dword(lcBuffer)

RETURN ASC(SUBSTR(lcBuffer, 1,1)) + ;
	ASC(SUBSTR(lcBuffer, 2,1)) * 256 +;
	ASC(SUBSTR(lcBuffer, 3,1)) * 65536 +;
	ASC(SUBSTR(lcBuffer, 4,1)) * 16777216

*----------------------------------------------------------------------
FUNCTION readregistrykey

#DEFINE HKEY_CLASSES_ROOT           -2147483648
#DEFINE HKEY_CURRENT_USER           -2147483647
#DEFINE HKEY_LOCAL_MACHINE          -2147483646
#DEFINE HKEY_USERS                  -2147483645

#DEFINE REG_SZ 				1	&& String
#DEFINE REG_BINARY 			3	&& Binary data
#DEFINE REG_DWORD 			4	&& 32bits int

#DEFINE ERROR_SUCCESS		0	&& OK

*Start of Code
LOCAL nKey, cSubKey, cValue, cValueRead
*nkey = HKEY_CLASSES_ROOT
nKey = HKEY_LOCAL_MACHINE
*nKey = HKEY_CURRENT_USER
*cSubKey = "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
*cSubKey = "Applications\AcroRd32.EXE\Shell\Open\command"
cSubKey = "Software\Microsoft\Windows\CurrentVersion\App Paths\AcroRd32.exe"
cValue = "Path"

cValueRead = ReadREG_SZ(nKey, cSubKey, cValue)
IF EMPTY(cValueRead)
	cValueRead = ''
ENDIF

RETURN cValueRead

*----------------------------------------------------------------------
FUNCTION ReadREG_SZ
* This function reads a REG_SZ value from the registry. If successful,
* it will return the value read. If not successful, it will return an empty string.
PARAMETERS  nKey, cSubKey, cValue
* nKey The root key to open. It can be any of the constants defined below.
*  #DEFINE HKEY_CLASSES_ROOT           -2147483648
*  #DEFINE HKEY_CURRENT_USER           -2147483647
*  #DEFINE HKEY_LOCAL_MACHINE          -2147483646
*  #DEFINE HKEY_USERS                  -2147483645
* cSubKey The SubKey to open.
* cValue The value that is going to be read.

* Constants that are needed for Registry functions
*   #DEFINE REG_SZ   1

* WIN 32 API functions that are used
DECLARE INTEGER RegOpenKey IN Win32API ;
	INTEGER nHKey, STRING @cSubKey, INTEGER @nResult
DECLARE INTEGER RegQueryValueEx IN Win32API ;
	INTEGER nHKey, STRING lpszValueName, INTEGER dwReserved,;
	INTEGER @lpdwType, STRING @lpbData, INTEGER @lpcbData
DECLARE INTEGER RegCloseKey IN Win32API INTEGER nHKey

* Local variables used
LOCAL nErrCode      && Error Code returned from Registry functions
LOCAL nKeyHandle    && Handle to Key that is opened in the Registry
LOCAL lpdwValueType && Type of Value that we are looking for
LOCAL lpbValue      && The data stored in the value
LOCAL lpcbValueSize && Size of the variable
LOCAL lpdwReserved  && Reserved Must be 0

* Initialize the variables
nKeyHandle = 0
lpdwReserved = 0
lpdwValueType = REG_SZ
lpbValue = ""

nErrCode = RegOpenKey(nKey, cSubKey, @nKeyHandle)
* If the error code isn't 0, then the key doesn't exist or can't be opened.
IF (nErrCode # 0) THEN
	RETURN ""
ENDIF

lpcbValueSize = 1
* Get the size of the data in the value
nErrCode=RegQueryValueEx(nKeyHandle, cValue, lpdwReserved, @lpdwValueType, @lpbValue, @lpcbValueSize)

* Make the buffer big enough
lpbValue = SPACE(lpcbValueSize)
nErrCode=RegQueryValueEx(nKeyHandle, cValue, lpdwReserved, @lpdwValueType, @lpbValue, @lpcbValueSize)

=RegCloseKey(nKeyHandle)

CLEAR DLLS RegOpenKey
CLEAR DLLS RegQueryValueEx
CLEAR DLLS RegCloseKey

IF (nErrCode # 0) THEN
	RETURN ""
ENDIF

lpbValue = LEFT(lpbValue, lpcbValueSize - 1)
RETURN lpbValue

*----------------------------------------------------------------------
FUNCTION Acrofind
PRIVATE WNetGetConnection, lpszLocalname, lpszRemoteName, ;
	sLen, Lni, DRIVE, Dtype, llfound, Lni
PRIVATE ARRAY afilesfound(1,3)
DIMENSION afilesfound(1,3)
afilesfound(1,1)=" "
llfound = .F.
Lni = 0
DECLARE INTEGER WNetGetConnection IN win32api ;
	STRING lpszLocalName,;
	STRING lpszRemoteName,;
	INTEGER @ lpchBuffer && Declare the external WNetGetConnection ;
	API FUNCTION
slpRemoteName = SPACE(254) && Initialize variables
sLen = LEN(slpRemoteName) && Initialize variables
*--Populate the one dimensional array with valid drive letters
FOR I = 1 TO 26 && Loop through drive letters A thru Z
	DRIVE = CHR(I + 64)
	Dtype = DRIVETYPE(DRIVE) && Determine drive type
	DO CASE
		CASE Dtype = 3 && Hard drives
			Lni=Lni+1
			DIMENSION adrivelist(Lni,3)
			adrivelist(Lni,1)=DRIVE
			adrivelist(Lni,2)=.F.
			adrivelist(Lni,3)=.F.
		CASE Dtype = 4 && Removable or network drives
			iSuccess = WNetGetConnection(DRIVE + ;
				":",@slpRemoteName,@sLen)
			IF iSuccess = 0
				Lni=Lni+1
				DIMENSION adrivelist(Lni,3)
				adrivelist(Lni,1)=DRIVE
				adrivelist(Lni,2)=.F.
				adrivelist(Lni,3)=.F.
			ENDIF
	ENDCASE
ENDFOR
llfound = .F.
FOR Lni = 1 TO ALEN(adrivelist,1)
	FOR ib = 10 TO 1 STEP -1
		lcacrofile = adrivelist(Lni,1)+":"+"\Program Files\Adobe\Acrobat "+ALLTRIM(STR(ib))+".0\Reader\AcroRd32.Exe"
		IF FILE(lcacrofile)
			llfound = .T.
			EXIT
		ENDIF
	ENDFOR
	IF llfound
		EXIT
	ENDIF
ENDFOR

CLEAR DLLS WNetGetConnection

IF llfound
	RETURN lcacrofile
ELSE
	RETURN ''
ENDIF

*----------------------------------------------------------------------
*--Uses GetExitcodeProcess instead of waitforsingleobject
PROCEDURE  ExeWait (lcApp, lcCmdLine, lcdir)
PRIVATE lntimes
lntimes = 0
IF _VFP.AUTOYIELD = .F.
	llsetback = .T.
ELSE
	llsetback = .F.
ENDIF
_VFP.AUTOYIELD = .T.
PRIVATE lnclosepass
lnclosepass = 0
#DEFINE INFINITE  0xFFFFFFFF
LOCAL lcStartupInfo, lcProcInfo, hProcess, ;
	lnPrio, lnIBelieve1
lnIBelieve1 = 1   && Don't remember what that was
lnPrio = 32 && Priority of Process=Normal
lcStartupInfo = CHR(68) + REPLI(CHR(0), 67)
lcProcInfo = REPLI(CHR(0), 16)
IF CreateProcess(0, m.lcApp+" "+m.lcCmdLine+CHR(0), 0,0,;
		m.lnIBelieve1, m.lnPrio,;
		0, 0, @lcStartupInfo, @lcProcInfo) <> 0
	* process and thread handles returned in ProcInfo structure
	hProcess = buf2dword(SUBSTR(lcProcInfo, 1,4))
	hThread = buf2dword(SUBSTR(lcProcInfo, 5,4))
	* waiting until the termination of the program
	DOEVENTS
	IF !li_acordview						&& printing only
		DO stopadobe
	ELSE
		DO WHILE .T.
			exitcode = 0					&& initialize return value to 0
			= GetExitCodeProcess(hProcess, @exitcode)	&& try to obtain process exit code
			IF exitcode # 259				&& not still busy
				EXIT							&& fall out of loop
			ELSE
				*--Attempt to close the password window up to 3 times
				IF dopass .and. lnclosepass < 3 .AND. PassWin('Password')
					= Sleep (1000)			&& wait 1 seconds
					lnclosepass = lnclosepass + 1
				ENDIF
			ENDIF
			= Sleep (100)					&& wait .1 seconds
		ENDDO
	ENDIF
	= CloseHandle(hThread)
	= CloseHandle(hProcess)
ELSE
	IF llsetback
		_VFP.AUTOYIELD = .F.
	ENDIF
	RETURN .F.
ENDIF
IF llsetback
	_VFP.AUTOYIELD = .F.
ENDIF
RETURN

*----------------------------------------------------------------------
FUNCTION PassWin
PARAMETER tcTitle

* Routine which sees if an application is active by looking for its
* Window title
* expC1 Window title

DECLARE INTEGER FindWindow IN Win32API AS FindWindow STRING, STRING

lnwindow = FindWindow(0,tcTitle)

IF lnwindow > 0
	#DEFINE WM_SETFOCUS 				0x0007
	#DEFINE KEYEVENTF_KEYUP      	2
	#DEFINE VK_SHIFT          		0x10

	DECLARE SHORT PostMessage IN user32;
		INTEGER   HWND,;
		INTEGER   Msg,;
		STRING   wParam,;
		INTEGER   LPARAM
	DECLARE INTEGER SetForegroundWindow IN Win32API;
		INTEGER HWND
	DECLARE INTEGER SetActiveWindow IN Win32API;
		INTEGER HWND
	DECLARE keybd_event IN Win32API;
		INTEGER bVk, INTEGER bScan,;
		INTEGER dwFlags, INTEGER dwExtraInfo

	HWND = lnwindow
	ReturnValue = PostMessage(HWND, WM_SETFOCUS, 0, 0)

	lcsentence = "~PASSWORD"+CHR(13) && change to valid form password
	= SetActiveWindow(HWND)
	= SetForegroundWindow(HWND)
	FOR Lni = 1 TO LEN(lcsentence)
		lcchar = SUBSTR(lcsentence, Lni, 1)
		IF lcchar <> "~"
			llshift = ISUPPER(lcchar)
			lnchar = ASC(UPPER(lcchar))
			IF llshift
				= keybd_event(VK_SHIFT, 0, 0, 0)
			ENDIF
			= keybd_event(lnchar, 0, 0, 0)
			= keybd_event(lnchar, 0, KEYEVENTF_KEYUP, 0)
			IF llshift
				= keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0)
			ENDIF
		ELSE
			lnchar = 192
			= keybd_event(VK_SHIFT, 0, 0, 0)
			= keybd_event(lnchar, 0, 0, 0)
			= keybd_event(lnchar, 0, KEYEVENTF_KEYUP, 0)
			= keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0)
		ENDIF
	NEXT

	CLEAR DLLS PostMessage
	CLEAR DLLS SetForegroundWindow
	CLEAR DLLS SetActiveWindow
	CLEAR DLLS keybd_event
	CLEAR DLLS FindWindow

	RETURN .T.
ELSE

	CLEAR DLLS FindWindow
	
	RETURN .F.
ENDIF


*----------------------------------------------------------------------
PROCEDURE stopadobe
PARAMETERS hThread

DECLARE Sleep IN kernel32 INTEGER dwMilliseconds
DO WHILE !Passwin('Password') .and. lnclosepass < 10
	lnclosepass = lnclosepass + 1
	=SLEEP(300)
ENDDO
=Sleep(5000)
*DECLARE INTEGER TerminateThread IN WIN32API INTEGER hThread, INTEGER uExitCode
*=TerminateThread(hThread,99)
*RETURN

LOCAL awin_apps, vfp_handle, ln_current_window,ln_window_count
* Dimension array awin_apps to store running apps
DIMENSION awin_apps[1,2]
* Initialize variable to store handle for current application
vfp_handle=0
* Declare API Functions
DECLARE INTEGER FindWindow ;
	IN win32api ;
	INTEGER nullpointer, ;
	STRING cwindow_name
DECLARE INTEGER GetWindow ;
	IN win32api ;
	INTEGER ncurr_window_handle, ;
	INTEGER ndirection
DECLARE INTEGER GetWindowText ;
	IN win32api ;
	INTEGER n_win_handle, ;
	STRING @ cwindow_title, ;
	INTEGER ntitle_length
* End of API function declarations
* Get handle for current application
vfp_handle=FindWindow(0,_SCREEN.CAPTION)
* Store handle of current app to a variable
ln_current_window=vfp_handle
* Initialize a count variable used to dimension array of running apps
ln_window_count=0
DO WHILE ln_current_window>0
	*  Initialize variable to store application title
	lc_window_title=SPACE(255)
	* Call to GetWindowText to fetch window caption
	ln_length=GetWindowText(ln_current_window, ;
		@lc_window_title,LEN(lc_window_title))
	* Note that the lc_window_title variable is used as a buffer to
	* receive text from the call to GetWindowText
	IF ln_length>0
		lc_window_title=STRTRAN(TRIM(lc_window_title),CHR(0),"")
	ELSE
		lc_window_title=""
	ENDIF
	IF ln_current_window>0 .AND. !EMPTY(lc_window_title)
		* Increment the window count and re-dimension the array of running
		* applications
		ln_window_count=ln_window_count+1
		DIMENSION awin_apps(ln_window_count,2)
		awin_apps[ln_Window_Count,1]=lc_window_title
		awin_apps[ln_Window_Count,2]=ln_current_window
	ENDIF
	* Call to GetWindow to fetch handle of running applications.
	ln_current_window=GetWindow(ln_current_window,2)
ENDDO
PRIVATE it
FOR it = 1 TO ALEN(awin_apps,1)
	IF "Adobe" $ awin_apps(it,1)
		IF TYPE('awin_apps(it,2)')="N"
			=close2(awin_apps(it,2))
		ENDIF
	ENDIF
ENDFOR

RETURN .T.

*----------------------------------------------------------------------
PROCEDURE close2
PARAMETERS HWND
#DEFINE WM_CLOSE 16
#DEFINE WM_SETFOCUS 0x0007

DECLARE SHORT PostMessage IN user32;
	INTEGER   HWND,;
	INTEGER   Msg,;
	STRING   wParam,;
	INTEGER   LPARAM
DECLARE INTEGER SetForegroundWindow IN Win32API;
	INTEGER HWND
DECLARE INTEGER SetActiveWindow IN Win32API;
	INTEGER HWND

=PostMessage(HWND, WM_SETFOCUS, 0, 0)
=PostMessage(HWND, WM_CLOSE, 0, 0)

RETURN .T.

*-----------------------------------------------------------------------
FUNCTION XmlEncode
LPARAMETERS teExpression

*-- Transfrom 5 Known reserved XML characters only

LOCAL lcReturn
lcReturn = TRAN(teExpression)

IF VARTYPE(teExpression) = 'C'
	lcReturn = ALLTRIM(lcReturn)
	lcReturn = STRTRAN(lcReturn, '&', '&')
	lcReturn = STRTRAN(lcReturn, '<', '&lt;')
	lcReturn = STRTRAN(lcReturn, '>', '>')
	lcReturn = STRTRAN(lcReturn, '"', '"')
	lcReturn = STRTRAN(lcReturn, "'", '&apos;')
ENDIF 

RETURN lcReturn

*-------------------------------------------------------------------------
FUNCTION XMLDeCode
LPARAMETERS cTXT
LOCAL i,ch
FOR i=1 TO 255
  ch=ALLTRIM(STR(i))
  cTXT=STRTRAN(cTXT,"&#"+ch+";",CHR(i))
ENDFOR 
RETURN cTXT
>Hi again Tracy,
>
>I have downloaded the trial versions of both Acrobat Pro 6.0 and the Designer 6.0 products. Acrobat Pro 6.0 seems to do what I need and is mostly working fine - I miss having the "micro-positioning" controls that I had in FormFlow (a toolbar that shows you the absolute position on the page that you could then change - I cannot seem to always line up things with just "nudging" them). I started off by scanning the app (the partners hear said that that would work best - this time around - as no need then to get legal okay from the LifeCos) and then am now working on overlaying the fields. It does not seem like the LifeCos will release .xdf type files to us - in fact only 2 of the 5 publish their forms in .pdf to start with - so I don't think this will be an option for us. I tried firing up the Designer product and loading the .pdf and it said that the "automatic" conversion proceeded but then the program crashed because it said it was so large that it would "affect performance". My
>guess is that it is breaking up the scanned image into many pieces and this has bloated the .xdf so much that it could not load.
>
>Because the fields can vary so much between the 5 different apps (e.g. 1 app has a "M/F" text box and another has two different check boxes), I am going to build some sort of "transformer" object in between my VFP data that exports the xml depending upon the app. Am still in "think" mode as to how to do this in a way that is somewhat maintainable and "visual" enough that I can "see" what I am doing. I am thinking of a base (custom) class that has methods for each of the main "sections" of the app and then I would subclass it for each of the 5 apps and set properties based upon whether male/female is one character box or 2 check boxes etc. We'll see - if you have any ideas, please share.
>
>The other reason for writing is I am wondering if you could send me a code snippet of what you have to do in #4 below: I am sure I could have fun figuring out the Windows functions below :-) but I would rather save a bit of time. All the other steps are straightforward enough so no need for code on them.
>
>Thanks,
>Albert
>
>
>>Currently, the forms already exist in .pdf format but without fillable fields. We use Acrobat 6 to add the fields to the forms. Once that is done we:
>>
>>1) Enter dummy data onto a form in Acrobat 6 and export the data to .xfdf format. The .xfdf file is an xml file. When you open Adobe Reader and point to an .xfdf file and there are both a .pdf file (form image) and an .xfdf file (data) Adobe Reader launches the .pdf form and populates the fields with the data in the .xfdf file. Use the .xfdf file created when you exported the dummy data to determine the xml values required to populate the fields on the fly.
>>2) Stuff the .pdf into a memo field in a table of all forms using FILETOSTR().
>>3) When the user prints a form, we create both the .pdf and the appropriate .xfdf file on the fly. We use STRTOFILE() to create the .pdf form.
>>4) If the user has Adobe Reader on their hard drive (we search for it programmatically by checking registry associations and locations on the hard drive if necessary) then we launch Adobe Reader programmatically from within our VFP app pointing to the .xfdf file we created and Adobe Reader loads with the pdf and the fields populated with the data from our VFP app. We use CreateProcess and GetExitCodeProcess to launch Adobe Reader and wait for it to exit.
>>5) When Adobe Reader closes (we suspend processing in our app until it is exited) we delete both the .xfdf and the .pdf file
>>
>>The newest format at Adobe is the new xdp format and the Form Designer is called Adobe Form Designer and costs 449.00 It allows you to create the pdf from scratch and add the controls to the form. I would download their evaluation version of it and create a form and see if it does what you need.
>>
>>We are currently researching with Adobe how to implement what we are already doing with the newer format and tools. In September, ACORD will provide us the forms in the newer .xdp format (the form and the data are in one file instead of two) and we will need to use the new FORM DESIGNER to modify them. They can still be read and printed using the latest version of Adobe Reader though.
>>
>>If you have to create the forms yourself from scratch (not just add the fields to the form) then you will need to either use the newer Form Designer ( a single package that allows you to create a pdf form from scratch AND add fields to it) or a separate form designer WITH Acrobat 6. The newer Form Designer costs 449.00. You only need a server product if you plan on mapping the form fields from within Adobe to a backend directly which it provides odbc connections for.
>>
>>HTH,
>>
>>Tracy
>>
.·*´¨)
.·`TCH
(..·*

010000110101001101101000011000010111001001110000010011110111001001000010011101010111001101110100
"When the debate is lost, slander becomes the tool of the loser." - Socrates
Vita contingit, Vive cum eo. (Life Happens, Live With it.)
"Life is not measured by the number of breaths we take, but by the moments that take our breath away." -- author unknown
"De omnibus dubitandum"
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform