Siêu thị PDFTải ngay đi em, trời tối mất

Thư viện tri thức trực tuyến

Kho tài liệu với 50,000+ tài liệu học thuật

© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

1001 Things You Wanted To Know About Visual FoxPro phần 8 potx
MIỄN PHÍ
Số trang
47
Kích thước
566.7 KB
Định dạng
PDF
Lượt xem
1588

1001 Things You Wanted To Know About Visual FoxPro phần 8 potx

Nội dung xem thử

Mô tả chi tiết

Chapter 10: Non-Visual Classes 321

Reading the data from the specified source into the form's cursor is handled by the custom

ReadFile() method as follows:

LOCAL ARRAY laTfer[1,2]

LOCAL lcSceFile, lcOldFile

WITH ThisForm

*** Check the source file, clear cursor if a new file is being created

IF .chkSource() > 0

IF EMPTY( ALLTRIM( .txtFName.Value ) )

*** Creating a new file - just return

ZAP IN curIniFile

.RefreshForm()

RETURN

ENDIF

ELSE

*** Source file check failed!

RETURN

ENDIF

*** Specified source is OK, so gather full path and file name

lcSceFile = ALLTRIM( ADDBS( .txtDir.Value )) + ALLTRIM( .txtFName.Value )

IF JUSTEXT( lcSceFile ) = "DBF"

*** It's a table, so just read it into an array

SELECT heading, item FROM (lcSceFile) ORDER BY sortorder INTO ARRAY laTfer

ELSE

*** It's an INI File (maybe). So read it

goIniMgr.ReadIniFile( @laTfer, lcSceFile )

ENDIF

*** Clear Cursor and Copy results in

ZAP IN curIniFile

INSERT INTO curIniFile FROM ARRAY laTfer

*** Strip off heading "[]" - they will be re-written anyway

REPLACE ALL heading WITH CHRTRAN( heading, '[]','') IN curIniFile

.RefreshForm()

ENDWITH

Writing the data out from the cursor is handled in the custom WriteFile() method as

follows:

LOCAL ARRAY laTfer[1,2]

LOCAL lcOldFile, lcDestFile

WITH ThisForm

*** Must have a destination

IF EMPTY( .txtDestFName.Value )

MESSAGEBOX( 'An output file must be specified!', 16, 'Unable to Continue')

.txtDestFName.SetFocus()

RETURN

ENDIF

*** We have a destination

lcDestFile = ALLTRIM(ADDBS(.txtDestDir.Value)) + ALLTRIM(.txtDestFName.Value)

*** Delete the File if it already exists

IF ! FILE( lcDestFile )

DELETE FILE (lcDestFile)

ENDIF

*** Now create a new, empty file ready for writing to

*** We need to do this to ensure that deletions get made properly

lnHnd = FCREATE( lcDestFile )

322 1001 Things You Always Wanted to Know About Visual FoxPro

IF lnHnd < 0

MESSAGEBOX( 'Unable to create new file ' + CHR(13) ;

+ lcDestFile, 16, 'Cannot Contuinue')

RETURN

ELSE

FCLOSE(lnHnd)

ENDIF

*** Now write the new file - ignore empty "heading" fields

SELECT * FROM curinifile WHERE ! EMPTY(heading) INTO ARRAY laTfer

WITH goIniMgr

*** Write file contents

.WriteIniFile( @laTfer, lcDestFile )

ENDWITH

*** Clear Cursor

ZAP IN curIniFile

.RefreshForm()

ENDWITH

How to select a different work area, OOP style! (Example:

ChgArea.prg)

One of the most frequently written snippets of code, in almost any application, looks

something like this:

*** Save Current work area

lnSelect = SELECT()

*** Select Required Area

IF ! USED( <Alias> )

USE <table> IN 0 AGAIN ALIAS <Alias>

ENDIF

SELECT <New Work Area>

*** Do Something There

<commands>

*** Return to original work area

SELECT (lnSelect)

Now, admittedly, this is not really very difficult, but it or some variant is repeated many

times in an application. We really should be able to do better than this now that we have all the

power of Object Orientation behind us and indeed we can.

Overview

The SelAlias class is designed to accept the alias name of a table as a parameter and switch to

that table's work area. If the table is not open it will open the table for us. More importantly it

will 'remember' that it opened the table and will, by default, close it when it is destroyed. The

class provides support for an additional parameter which can be used to specify an alias name

when it is necessary to open a table with an alias other than the real name of the table.

Chapter 10: Non-Visual Classes 323

The class has no exposed properties or methods and does all of its work in its Init and

Destroy methods. By creating an object based on this class, and scoping it as LOCAL, we need

never write code like that shown above again.

A word on creating the selector object

A selector object may be created in the usual way by first loading the procedure file into

memory and then using the CreateObject() function whenever an instance is needed. However,

Version 6.0 of Visual FoxPro introduced an alternative method, using the NewObject()

function, which allows you to specify the class library from which a class should be

instantiated as a parameter. While it is marginally slower, it does mean that you do not need to

load and retain procedure files in memory and is useful when you need to create an object 'on

the fly', like this one. The syntax for both methods is given below. (Note that with

NewObject(), if the class is not a visual class library, Visual FoxPro expects both a 'module or

program' name as the second parameter and either an application name or an empty string or a

NULL value as the third.)

*** Using CreateObject()

SET PROCEDURE TO selalias ADDITIVE

loSel = CREATEOBJECT( 'xSelAlias', <Alias>, [|<Table Name>])

*** Using NewObject()

loSel = NEWOBJECT( 'xSelAlias', 'selalias.prg', NULL, <Alias>, [|<Table Name>])

One word of caution – if you use multiple instances of this class in the same procedure or

method to open tables, either ensure that all objects are created from the same work area or that

they are released in the reverse order to that in which they were instantiated. If you do not do

this you could end up in a work area that was selected as a result of opening a table but which

is now empty.

How the selector class is constructed

As mentioned in the overview this class has no exposed properties or methods and does all of

its work in its Init or Destroy methods. Internally it uses three protected properties to record:

• the work area in which it was instantiated

• the alias of the table it is managing

• whether the table was already open on instantiation

The selector class Init method

The Init method does four things. First it checks the parameters. An alias name is the

minimum that must be passed, and in the absence of the optional second parameter – the table

name, it assumes that the table is named the same as the alias. If passed, the table name may

include an extension and may also include a path. (Notice the use of ASSERT in this part of the

method. The objective here is to warn developers of errors that may arise in the calling syntax

without impacting the run time code.)

324 1001 Things You Always Wanted to Know About Visual FoxPro

PROCEDURE INIT( tcAlias, tcTable )

LOCAL llRetVal

*** No Alias Passed - Bail Out

IF ! VARTYPE( tcAlias ) = "C"

ASSERT .F. MESSAGE "Must Pass an Alias Name to Work Area Selector"

RETURN .F.

ENDIF

tcAlias = UPPER( ALLTRIM( tcAlias ))

IF VARTYPE( tcTable ) # "C" OR EMPTY( tcTable )

tcTable = tcAlias

ELSE

tcTable = UPPER( ALLTRIM( tcTable ))

ENDIF

Next, it checks the currently selected alias. If this is already the required alias, it simply

returns a value of .F. and the object is not instantiated. The reason is simply that if the table is

already open and selected, there is nothing for the object to do anyway:

*** If already in correct work area - do nothing

IF UPPER(ALLTRIM( ALIAS() )) == tcAlias

RETURN .F.

ENDIF

Then it determines whether the required alias is already in use and, if not, tries to open the

table under the specified alias. If it succeeds it sets its 'lWasOpen' property to .F. This allows

the same table to be opened more than once under different aliases. If the table cannot be

opened, a value of .F. will be returned and the object will not be instantiated. (NOTE: A

"production" version of this class should also check that the file exists, and that it is a valid

Visual FoxPro table, before attempting to open it with a USE command. Such code has already

been covered elsewhere and has been deliberately omitted from this class to keep it as simple

as possible. See the ISDBF() function in Chapter 7, "How to compare the structures of two

tables" for one solution.)

*** If Specified Alias not open - Open it

IF ! USED( tcAlias )

USE (tcTable) AGAIN IN 0 ALIAS (tcAlias) SHARED

*** And Check!

llRetVal = USED( tcAlias )

*** If Forced Open, Note the fact

IF llRetVal

This.lWasOpen = .F.

ENDIF

ELSE

llRetVal = .T.

ENDIF

Finally it stores the currently selected work area number and the alias name to its

'nOldarea' and 'cAlias' properties and switches to the required work area. The object is,

therefore, only instantiated when everything has worked as expected:

*** IF OK, save current work area and

*** Now Move to the specified Work Area

Tải ngay đi em, còn do dự, trời tối mất!