本章說明 本章共分十一節(jié)。闡述了與VFP工作環(huán)境有關(guān)的細(xì)節(jié)問題,其中一至七節(jié)為一般描述適用于一般使用者,第八、九兩節(jié)適用于中、高級(jí)開發(fā)者,第十節(jié)是四個(gè)具體的實(shí)例,可用于任何應(yīng)用程序,第十一節(jié)是"選項(xiàng)"對(duì)話框的說明性表格,是手冊(cè)性質(zhì)的資料。 第一節(jié) 概述 工作環(huán)境規(guī)定了 VFP 工作時(shí)的某些行為。配置工作環(huán)境意味著您可以通過某些方法使 VFP 的行為滿足自己的需要 - 必須的或者是某些個(gè)人偏好的。 與任何完善的開發(fā)工具一樣,VFP 也是一個(gè)復(fù)雜的系統(tǒng),復(fù)雜的一個(gè)方面就表現(xiàn)在它具有極大的靈活性 - 同一種工作,由于"環(huán)境"的不同,可能會(huì)產(chǎn)生不同的效果。 工作環(huán)境是個(gè)整體的概念,我們使用"環(huán)境參數(shù)"一詞來描述構(gòu)成工作環(huán)境的個(gè)體。那么就可以說,工作環(huán)境就是由一組環(huán)境參數(shù)來決定的,配置工作環(huán)境就是設(shè)置這組環(huán)境參數(shù),以滿足不同的需求。這顯然有兩方面的任務(wù),第一、您要知道有那些環(huán)境參數(shù),第二、明確怎樣配置這些參數(shù)。 工作環(huán)境涉及到很多方面,例如輸入輸出、數(shù)據(jù)處理、開發(fā)、調(diào)試等等??梢酝ㄟ^分類對(duì)所有環(huán)境參數(shù)進(jìn)行描述。所有的環(huán)境參數(shù)都有一個(gè)原始的默認(rèn)值,一般的環(huán)境配置工作,事實(shí)上只需要修改少量的環(huán)境參數(shù)即可。 有一個(gè)問題需要明確,"VFP 的工作環(huán)境"是指 Visual FoxPro 工具的開發(fā)環(huán)境。另外一種情況,使用 VFP 開發(fā)的應(yīng)用程序,在編譯成執(zhí)行文件后,工作在 VFP 運(yùn)行時(shí)的工作環(huán)境下。這兩者是有區(qū)別的,顯而易見的區(qū)別是,運(yùn)行時(shí)環(huán)境涉及的問題比開發(fā)環(huán)境少得多,例如開發(fā)、調(diào)試方面的問題。一般來講,運(yùn)行時(shí)的環(huán)境是開發(fā)環(huán)境的一個(gè)子集,但嚴(yán)格說來這是不對(duì)的,二者仍存在一些差別,不僅在環(huán)境參數(shù)的類別與數(shù)量方面,也存在于配置方法上。本文的敘述主要針對(duì)開發(fā)環(huán)境而進(jìn)行,對(duì)二者存在的差別也將被提及。 [dvnews_page=VFP 高級(jí)教程:VFP 開發(fā)技巧] 第二節(jié) 默認(rèn)的工作環(huán)境 VFP 安裝完成后,其"內(nèi)部"保存著對(duì)所有環(huán)境參數(shù)的設(shè)置,這些參數(shù)可以稱做是原始設(shè)置。您永遠(yuǎn)也不能夠去修改這些原始設(shè)置。但 VFP 提供一種機(jī)制允許您每次啟動(dòng)時(shí)用自己的設(shè)置去覆蓋這組原始設(shè)置。方法是是使用 Windows 注冊(cè)表及配置文件。 啟動(dòng)時(shí),VFP 首先會(huì)檢查 Windows 注冊(cè)表中的有關(guān)設(shè)置,然后據(jù)此修改環(huán)境參數(shù)。然后還會(huì)查找一個(gè)配置文件,該文件默認(rèn)的名字為 config.fpw,其中也存放著一些環(huán)境配置信息。VFP 將讀取這些信息,并再次修改環(huán)境參數(shù)。如果 VFP 在Windows 注冊(cè)表中沒有找到配置信息或者沒有找到配置文件,這沒有關(guān)系,VFP 將以原始配置進(jìn)行工作。您甚至可以主動(dòng)讓 VFP 在啟動(dòng)時(shí)放棄讀取注冊(cè)表及配置文件。 VFP 不會(huì)主動(dòng)把環(huán)境參數(shù)寫進(jìn) Windows 注冊(cè)表中,但它提供了一種方法使您方面地將環(huán)境參數(shù)寫進(jìn)注冊(cè)表,寫入不僅針對(duì)修改過的參數(shù),而是所有參數(shù),您沒有去修改的參數(shù)值將以原始值寫入。配置文件則不同,它只保存您寫入的參數(shù),某種意義上,它相當(dāng)是一份注冊(cè)表中的環(huán)境參數(shù)表的勘誤。 保存在 Windows 注冊(cè)表中的環(huán)境參數(shù)以及配置文件中的設(shè)置稱做"默認(rèn)工作環(huán)境" 第三節(jié) 配置文件 先讀取注冊(cè)表再查找配置文件的方法似乎有點(diǎn)復(fù)雜,但有些時(shí)候需要這樣做,例如工作在運(yùn)行時(shí)環(huán)境的應(yīng)用程序,啟動(dòng)時(shí)不去讀取注冊(cè)表,這使得配置文件成為必須。另外,配置文件創(chuàng)建于 FoxPro 的早期版本,兼容性使它必須被保留。VFP6 以前的版本在安裝時(shí)將自動(dòng)建立一個(gè)這樣的文件(在安裝目錄下),而到了 VFP6,系統(tǒng)不再自動(dòng)建立該文件,需要時(shí)由用戶自行建立。該文件是一個(gè)文本文件,可以使用任何文本編輯器來建立它。 VFP 啟動(dòng)時(shí)將按照下列路徑查找該文件: 當(dāng)前工作目錄 安裝 Visual FoxPro 的目錄 DOS 路徑中列出的目錄 配置文件有默認(rèn)的名字(config.fpw),"默認(rèn)"意味著你可以去改變它。這有利于您同時(shí)擁有多個(gè)配置文件,以便滿足不同的需要。指定另外不同于config.fpw名字的配置文件的方法是在啟動(dòng) VFP 時(shí)增加命令行開關(guān)項(xiàng),例如 VFP6.EXE -Cc:\myprg\myconfig.fpw 配置文件中不僅僅存放環(huán)境配置信息,例如可以在配置文件中設(shè)置 VFP 啟動(dòng)后立即去執(zhí)行一個(gè)程序文件。這使得您可以在配置環(huán)境方面使用一種技巧,即將環(huán)境設(shè)置命令保存在一個(gè)程序文件中,然后讓 VFP 啟動(dòng)時(shí)去執(zhí)行它。 啟動(dòng)過程也可以通過使用命令行參數(shù)來定制,通過定制啟動(dòng)過程,可以得到不同的環(huán)境默認(rèn)設(shè)置,以下是對(duì)環(huán)境配置有影響的一些情況:
[dvnews_page=VFP 高級(jí)教程:VFP 開發(fā)技巧]
第四節(jié) 更改默認(rèn)設(shè)置 VFP 啟動(dòng)完成后,工作環(huán)境被設(shè)置成默認(rèn)狀態(tài)。您可以即時(shí)地更改環(huán)境參數(shù),這有幾種方法,各種方法可能適合于不同的情況。 交互式修改 在命令窗口輸入環(huán)境設(shè)置命令,執(zhí)行后該修改會(huì)立即生效。絕大部分的環(huán)境參數(shù)是通過 SET 命令設(shè)置的,另外還有一些通過系統(tǒng)變量存儲(chǔ)以及極少數(shù)的函數(shù)設(shè)置。在早期的XBASE 工具中,例如dBASEII中,僅有 20 幾條 SET 命令,而今天,VFP 中已經(jīng)有 120 多個(gè) SET 命令了。交互式的修改方法是枯燥的,因此只用于臨時(shí)性的修改,例如調(diào)試等。 程序化執(zhí)行修改 可以將一組環(huán)境設(shè)置命令組織成一個(gè)程序文件,運(yùn)行該程序,就相當(dāng)于在命令窗口一一輸入執(zhí)行了這組命令,有些情況下是需要這樣做的,例如在開發(fā)環(huán)境下同時(shí)調(diào)試多于一個(gè)項(xiàng)目的時(shí)候??梢詫⒃摥h(huán)境設(shè)置程序存為一個(gè)過程或直接寫在項(xiàng)目的主文件中。事實(shí)上,對(duì)于應(yīng)用程序,因?yàn)樽罱K要脫離開發(fā)環(huán)境運(yùn)行,所以大部分都是這樣做的。 用命令方式讀取Windows 注冊(cè)表中的設(shè)置 讓 Visual FoxPro 再次讀取自己的注冊(cè)表設(shè)置,并且使用當(dāng)前的注冊(cè)表設(shè)置更新自己。 語法為: SYS(3056 [,1]) 說明:包含1選項(xiàng)可以只根據(jù)注冊(cè)表設(shè)置進(jìn)行更新,不包括 SET 命令和文件位置。Visual FoxPro 在 Windows 注冊(cè)表的選項(xiàng)對(duì)話框中保存設(shè)置。當(dāng)Visual FoxPro 啟動(dòng)時(shí),讀取這些設(shè)置,并利用這些設(shè)置進(jìn)行配置。SYS(3056)可更新包含有文件名和路徑的系統(tǒng)變量,而系統(tǒng)變量由SET命令和注冊(cè)表設(shè)置。當(dāng)您選擇設(shè)置為默認(rèn)值時(shí),選項(xiàng)對(duì)話框指定的設(shè)置寫入注冊(cè)表。其中一些影響Visual FoxPro環(huán)境的設(shè)置含有SET 命令,例如SET BELL,SET LOCK等。注意 SYS(3056)不更新來自Config.fpw(即 Visual FoxPro 配置文件)的設(shè)置。 有關(guān)環(huán)境設(shè)置的命令 有很多環(huán)境設(shè)置的命令,在本文的附表中,以"選項(xiàng)"對(duì)話框中的分類列出了相應(yīng)的環(huán)境設(shè)置命令,還有一些命令沒有包含在"選項(xiàng)"對(duì)話框中,但它們也是關(guān)于環(huán)境的設(shè)置命令,本文僅將它們列出來,具體的意義及語法可參見隨機(jī)文檔。
無論是交互式還是程序化執(zhí)行命令,其修改都是臨時(shí)的,只對(duì)當(dāng)前工作有效,VFP 系統(tǒng)關(guān)閉后,這種修改不能被保存,下一次運(yùn)行,如果需要同樣的設(shè)置,您不得不再一次輸入該命令或執(zhí)行該程序。要想使修改成為永久,必須將修改保存在 Windows 注冊(cè)表中或構(gòu)建配置文件。 修改注冊(cè)表 有兩種方法:直接修改 Windows 注冊(cè)表或使用 VFP 開發(fā)環(huán)境提供的"選項(xiàng)卡"對(duì)話框。對(duì)于直接修改 Windwos 注冊(cè)表的方法,沒有人會(huì)建議您這樣做,除非您首先對(duì) Windwos 注冊(cè)表的結(jié)構(gòu)非常熟悉,其次對(duì) VFP 在 Windows 注冊(cè)表中的各種參數(shù)的意義比較了解,第三有某些特殊需要以至于不能使用常規(guī)的方法完成。常規(guī)的方法,是使用 VFP 的"選項(xiàng)卡"對(duì)話框來完成環(huán)境配置。 直接修改注冊(cè)表 VFP 環(huán)境設(shè)置信息在 Windows 注冊(cè)表的目錄如下: HKEY_CURRENT_USER\Software\Microsoft\VisualFoxPro\6.0\Options 主鍵名稱在本文附表中有詳細(xì)介紹。 使用"選項(xiàng)"對(duì)話框 使用"選項(xiàng)卡"對(duì)話框來進(jìn)行系統(tǒng)的配置比直接修改 Windows 注冊(cè)表的方法至少有兩個(gè)好處,第一,很多配置參數(shù)在"選項(xiàng)卡"上是以一種"易于理解的方式"表達(dá)的,您只需在某些"問題"前打勾或者在很多答案中選擇一個(gè),這就象您填一份表格一樣來得輕松。第二,在"選項(xiàng)卡"上進(jìn)行的配置,一旦完成后,立即生效,而直接修改 Windows 注冊(cè)表的方法卻不是這樣,只能是在下一次運(yùn)行 VFP 時(shí)生效。 在開發(fā)環(huán)境下,執(zhí)行"工具"菜單中的"選項(xiàng)"菜單項(xiàng),會(huì)出現(xiàn)"選項(xiàng)"對(duì)話框。對(duì)話框上有12個(gè)卡頁,分12個(gè)方面對(duì)環(huán)境進(jìn)行配置。本文附表中詳細(xì)描述了其中的每一項(xiàng)設(shè)置。事實(shí)上,真正需要修改的并不多,很多項(xiàng)設(shè)置,原始值應(yīng)該能滿足要求?,F(xiàn)在的問題是,當(dāng)你修改完成后,可有兩種選擇,按"確定"按鈕退出對(duì)話框,您的修改只會(huì)保存在當(dāng)前環(huán)境中,隨著系統(tǒng)的關(guān)閉而失效;按"設(shè)置為默認(rèn)值"按鈕退出對(duì)話框,當(dāng)前的設(shè)置將會(huì)被寫進(jìn) Windows 注冊(cè)表從而成為新的默認(rèn)值。 第六節(jié) ON命令 ON ERROR 命令 設(shè)計(jì)得再好的程序,在運(yùn)行時(shí)也不可避免地會(huì)發(fā)生錯(cuò)誤,這些錯(cuò)誤可能是程序自身的錯(cuò)誤,也可能是系統(tǒng)環(huán)境引起的或是用戶錯(cuò)誤地操作(如錯(cuò)誤地移動(dòng)/刪除文件等)引起的等。 因此,程序員有責(zé)任編寫出可以捕捉錯(cuò)誤的程序并盡可能地處理這些錯(cuò)誤。要捕捉程序中發(fā)生的錯(cuò)誤使用 ON ERROR 命令。你可以在 ON ERROR 命令后跟隨一個(gè)錯(cuò)誤處理程序的名字:ON ERROR DO ERRORHANDLER,或者在 ON ERROR 命令后跟隨一條賦值語句:ON ERROR glError = .T.。 注意,在程序中全程使用類似于ON ERROR glError = .T.的命令是極不負(fù)責(zé)任的和令人憎惡的,這有可能會(huì)使用程序陷入死循環(huán)而使用用戶不得不強(qiáng)行退出系統(tǒng)(強(qiáng)行關(guān)斷電源等),這樣做極有可能破壞用戶的數(shù)據(jù)文件。 ON ESCAPE 命令 指定在程序或命令運(yùn)行過程中,按下 ESC 鍵時(shí)所執(zhí)行的命令。 語法為:ON ESCAPE [Command] ON SHUTDOWN 命令 指定當(dāng)試圖退出 Visual FoxPro 時(shí)所要執(zhí)行的命令。 語法為:ON SHUTDOWN [Command] 第七節(jié) 一些重要的設(shè)置 以下是幾乎每一個(gè)應(yīng)用程序都要進(jìn)行的設(shè)置: _VFP 系統(tǒng)變量 指向當(dāng)前運(yùn)行的Visual FoxPro應(yīng)用程序?qū)ο蟆? 語法 參數(shù)描述 eValue 指定屬性的值。Method指定應(yīng)用程序?qū)ο蟮姆椒ā? 說明 通過_VFP,您可以訪問對(duì)象集合(Objects collection)。 可設(shè)置的屬性有:
SET SAFETY 決定改寫已有文件之前是否顯示對(duì)話框,或者決定當(dāng)用表設(shè)計(jì)器或用 ALTER TABLE 命令對(duì)表結(jié)構(gòu)進(jìn)行修改后,是否重新計(jì)算表或字段規(guī)則、默認(rèn)值以及錯(cuò)誤信息。 語法為:SET SAFETY ON | OFF SET PROCEDURE TO 設(shè)置運(yùn)行時(shí)的命令文件 SET CLASSLIB TO 設(shè)置運(yùn)行時(shí)的類庫文件 SET MEMOWIDTH TO 指定備注字段和字符表達(dá)式的顯示寬度。 語法為:SET MEMOWIDTH TO nColumns SET MULTILOCKS ON 決定能否使用 LOCK ()或 RLOCK () 鎖定多個(gè)記錄。 語法為:SET MULTILOCKS ON | OFF 若要在程序中使用表緩存必須設(shè)置SET MULTILOCKS 為 ON。 SET HELP TO 激活或廢止 Visual FoxPro 聯(lián)機(jī)幫助或指定的幫助文件。 語法為 SET HELP ON | OFF - 或者 - SET HELP TO [FileName] SET DELETED 指定 Visual FoxPro 是否處理標(biāo)有刪除標(biāo)記的記錄,以及其他命令是否可以操作它們。 語法為:SET DELETED ON | OFF SET EXCLUSIVE 指定 Visual FoxPro 在網(wǎng)絡(luò)上以獨(dú)占方式還是共享方式打開表文件。 語法為:SET EXCLUSIVE ON | OFF SET NOTIFY 確定是否顯示某種系統(tǒng)信息。 語法為:SET NOTIFY ON | OFF SET BELL 關(guān)掉或打開計(jì)算機(jī)鈴聲,并設(shè)置鈴聲屬性。 語法為: SET BELL ON | OFF - 或者 - SET BELL TO [nFrequency, nDuration | cWAVFileName, nDuration] SET NEAR FIND 或 SEEK 查找記錄不成功時(shí),確定記錄指針停留的位置。 語法為:SET NEAR ON | OFF SET EXACT 指定比較不同長度兩個(gè)字符串時(shí),Visual FoxPro 使用的規(guī)則。 語法為:SET EXACT ON | OFF SET CONFIRM 指定是否可以用在文本框中鍵入最后一個(gè)字符的方法退出文本框。 SET ESCAPE 決定是否可以通過按 ESC 鍵中斷程序和命令的運(yùn)行。 語法為:SET ESCAPE ON | OFF SET DATE 設(shè)置日期格式 語法為:SET DATE [TO] AMERICAN | ANSI | BRITISH | FRENCH | GERMAN | ITALIAN | JAPAN | USA | MDY | DMY | YMD SET CENTURY 設(shè)置是否在日期的年中顯示世紀(jì)值 語法為:SET CENTURY ON | OFF ON SHUTDOWN DO 指定當(dāng)試圖退出 Visual FoxPro 時(shí)所要執(zhí)行的命令。 語法為:ON SHUTDOWN [Command] 第八節(jié) 進(jìn)一步訂制VFP的向?qū)Ш蜕善?/strong> 作為最好的數(shù)據(jù)庫管理系統(tǒng),VFP 給我們提供了高度的可自定義的交互式的開發(fā)環(huán)境(interactive development environment IDE)。你可以修改菜單,安裝新的生成器和向?qū)?,?shí)現(xiàn)開發(fā)工具條,修改項(xiàng)目管理器的行為,以及很多其它事來使你的IDE 更高效。這些定制甚至比我們所知道的和喜歡的VFP語言更好,連相對(duì)不熟煉的VFP 開發(fā)者都可以按他們自己的方法定制開發(fā)環(huán)境。 本節(jié)將配合實(shí)際程序示例,向你展示如何建立簡單的工具增加你和你的開發(fā)組的效率。我們將著眼于修改VFP 的向?qū)Ш蜕善鱽硖峁╊~外的或自定義功能,并使用VFP 6中的BuilderD 技術(shù)創(chuàng)建你自己的生成器。 修改VFP 的向?qū)Ш蜕善?/strong> 如果你象我一樣,你可能不常用VFP 的生成器和向?qū)?,因?yàn)樗鼈儾煌耆軡M足你的需要??赡芩鼈儾痪邆渥銐虻撵`活性或可能你只是不喜歡他們的工作方式。直到VFP 6以前,沒有辦法改變生成器和向?qū)У男袨椋驗(yàn)镸icrosoft 沒有提供源代碼。但是,現(xiàn)在我們不但獲得了生成器和向?qū)У脑创a,也獲得了類瀏覽器,組件管理器的源代碼。 生成器和向?qū)У脑创a可以在VFP主目錄下的TOOLS\XSOURCE目錄中的XSOURCE.ZIP 文件中找到。當(dāng)你解壓該文件時(shí),它建立一個(gè)VFPSOURCE 目錄,其中包含了所有的源代碼。向?qū)У脑创a 可以在WIZARDS 目錄下找到,生成器的在BUILDERS目錄下 (雖然一些WIZARDS目錄中的公共文件也被生成器使用)。 因此,現(xiàn)在我們有了源代碼,我們可個(gè)按我們的需要來修改生成器和向?qū)В瑢?duì)嗎? 好了,一個(gè)較好的辦法是建立新的生成器和向?qū)r(shí),使用源代碼中的大多數(shù)類和程序,但以派生子類并復(fù)制和修改PRGs 或建立封裝PRGs的方法來忽略他們?cè)械男袨?。本文將詳?xì)說明如何對(duì)各生成器和向?qū)н@樣做。 一但你建立了你自己的生成器和向?qū)?,怎樣告訴VFP 使用你的而不是原來的嗎? 生成器是注冊(cè)在BUILDER.DBF 且向?qū)窃赪IZARD.DBF中,兩個(gè)表都在VFP主目錄下的WIZARDS 子目錄中。這些表具有相同的結(jié)構(gòu),如下表所示。
表 1. BUILDER.DBF 和 WIZARD.DBF的結(jié)構(gòu) 當(dāng)你調(diào)用一個(gè)生成器時(shí),VFP 調(diào)用_BUILDER 系統(tǒng)變量中指定的程序 (默認(rèn)是BUILDER.APP)。BUILDER.APP 查看它所在的環(huán)境 (例如,生成器是被那一個(gè)對(duì)象調(diào)用),在BUILDER.DBF 表中查找與環(huán)境匹配的記錄 (例如,在TYPE 字段中查找對(duì)象的基類),并調(diào)用注冊(cè)后的生成器。除系統(tǒng)變量_WIZARD外,向?qū)б彩且韵嗤姆椒ㄌ幚?,_WIZARD是用于指向可在WIZARD.DBF找到的WIZARD.APP。 要告訴VFP 使用一個(gè)不同的生成器或向?qū)В迦胍粭l說明如何運(yùn)行你的生成器或向?qū)У男掠涗浀紹UILDER.DBF或 WIZARD.DBF表中。如果你想在運(yùn)行新的向?qū)Щ蛏善鞯耐瑫r(shí)也可以選擇運(yùn)行原有的生成器或向?qū)В赪IZARD.DBF表中保留原有的生成器或向?qū)в涗?。如果你想替換原有的,簡單的修改它的TYPE值為另外的值(我使用一個(gè)"X"前綴,如 "XGRID"),而不是刪除該記錄; 使用該方法,你可以簡單的以恢復(fù)TYPE 的值來恢復(fù)使用原來的生成器或向?qū)А?我們將考查創(chuàng)建一個(gè)Grid 生成器的替代物,參照完整性生成器,Upsizing 向?qū)?,和WWW 搜索頁向?qū)А? 創(chuàng)建更有用的Grid 生成器 VFP Grid 生成器提供了一種快速方法來整合grid 的列并建立你所希望的視覺外觀。但是,關(guān)于該生成器,有我所不喜歡的一些東西:
要建立一個(gè)VFP Grid 生成器的替代物,首先建立了SFGRIDBLDR 項(xiàng)目(它在你解壓該文檔所附的示例程序時(shí)建立的GRID 子目錄中) 并添加以下文件: BUILDER.VCX (在VFP 向?qū)г茨夸浿械腂UILDERS\BUILDERS 子目錄中),GRIDBLDR.VCX (在 BUILDERS\GRIDBLDR 目錄中),THERM.VCX,WIZCTRL.VCX,WIZMOVER.VCX (所有都在WIZARDS\WZCOMMON目錄中),DUMMY.PRG,和 WBGRID.PRG (在BUILDERS目錄中)。我如何知道要添加那些文件到項(xiàng)目中呢? 這很簡單:只需要查看GRIDBLDR 項(xiàng)目的內(nèi)容。 其次,派生GridBuilder 類到SFGridBuilder (在 SFGRIDBLDR.VCX類庫中) 并復(fù)蓋ResetColumns 方法,該方法用于調(diào)整選定列的寬度到適當(dāng)?shù)拇笮?(我只實(shí)現(xiàn)了該想法,未實(shí)現(xiàn)上述列表中的其它兩個(gè))。該方法的代碼在下面列出。這里要注意兩個(gè)有趣的東西。首先,我希望寫很多復(fù)雜的代碼,根據(jù)字段寬度、字體和字號(hào)來計(jì)算出列的寬度,等等。有趣的是,它放棄了生成器中已存在的任務(wù)的方法 (SetColWidth),而只是傳遞字段寬度到該方法中,生成器傳給它一個(gè)不同的值。其它事情是分配到loColumn。Width 的計(jì)算寬度被注釋了。理由是我還沒有調(diào)試好,改變列寬后,當(dāng)生成器關(guān)閉時(shí),會(huì)造成問題,所以我把列寬設(shè)置為,列寬是保存在wbaCols中。(如果你需要,wbaCols 是一個(gè)公共數(shù)組。我沒有創(chuàng)建生成器,因此不要責(zé)怪我采用這種方式) 因此,效果是當(dāng)一個(gè)字段添加網(wǎng)格中時(shí),它沒有立即獲得適當(dāng)?shù)牧袑?,但是一但你?zhí)行了一些其它操作 (添加另一個(gè)字段,轉(zhuǎn)到生成器的另一個(gè)頁面中,關(guān)閉生成器等等。)它就會(huì)取得適當(dāng)?shù)牧袑挕?
最后我為我的生成器建立了GRIDMAIN.PRG (使用了BUILDERS\GRIDBLDR 中的GRIDMAIN.PRG 的辦法) 并使它成為項(xiàng)目的主文件。該程序用SET CLASSLIB命令添加SFGRIDBLDR.VCX 到打開的類庫中,這樣它可以找到我們的SFGridBuilder 類。GRIDMAIN 也自動(dòng)注冊(cè)它自己到VFP BUILDER 表中(如果是直接運(yùn)行該APP 文件)。 要查看該生成器的行為,建立并運(yùn)行SFGRIDBLDR.APP 來作為grids生成器注冊(cè)它。如果你在運(yùn)行該APP后,觀察觀查BUILDER.DBF,你會(huì)發(fā)現(xiàn)它是"未注冊(cè)的" ,原始的grid 生成器的 TYPE 字段由"GRID" 改成了"XGRID" 并在它后面為它自己添加了一條TYPE 字段為"GRID"的新記錄。下一步,新建一個(gè)表單,拖動(dòng)grid 到表單中,并調(diào)用生成器。新的生成器看起來與原來的沒有任何區(qū)別,但是當(dāng)你添加字段到表格時(shí),你會(huì)發(fā)現(xiàn)字段寬度自動(dòng)調(diào)整到了適當(dāng)大小。 創(chuàng)建一個(gè)更好的參照完整性生成器 我有一小點(diǎn)關(guān)于VFP自身的參照完整性(RI)生成器的問題:
修正這些項(xiàng)相對(duì)容易些,因?yàn)槲覀冇蠷I 生成器的源代碼。我建立了SFRIBUILDR.APP,一個(gè) VFP RIBUILDR.APP的替換物。我沒有實(shí)現(xiàn)附加的規(guī)則 (上面提及的最后一項(xiàng)) 但是我處理了其它的所有項(xiàng)。我首先建立了SFRIBUILDR 項(xiàng)目(它在解壓后的程序的主目錄下的RI 目錄中) 并添加了VFP的RIBUILDR.VCX(在VFP向?qū)г闯绦蛩谀夸浵碌腂UILDERS\RIBUILDR 目錄中)。 接著,我派生VFP RI生成器類到 SFRIBUILDR.VCX 類庫中的SFRIBuildr。我忽視(overrode)了Load 方法以便在數(shù)據(jù)庫中有被刪除的記錄時(shí)不會(huì)發(fā)生錯(cuò)誤 (你可以參見我注釋的已存在的代碼)。我忽視了確認(rèn)按鈕的Click 方法,以便不出現(xiàn)確認(rèn)對(duì)話框和不復(fù)制當(dāng)前的儲(chǔ)存過程到RISP.OLD中,并修復(fù)了生成的代碼中的錯(cuò)誤。同時(shí),如果它檢查到NEWRI.PRG 存在于你的系統(tǒng)中 (與SFRIBUILR.APP在同一目錄),它會(huì)把該代碼放入數(shù)據(jù)庫的儲(chǔ)存代碼中而不會(huì)生成其它代碼。這個(gè)修改需要一個(gè)新的方法 RIMakeNewTr用一個(gè)不同的名字建立觸發(fā)器(__RI_Handler) 而不是原來的RI 生成器的生成的(__RI_<action>_<table>,如__RI_Delete_Customer)。因?yàn)檫@些方法中有大量的代碼,在這里就不寫出來了; 但是,如果你查看提供的源代碼,你會(huì)看見我確實(shí)只注釋了很少的代碼行,并添加了很少的代碼。 最后,我從BUILDERS\RIBUILDR目錄中復(fù)制RIMAIN.PRG 到我的生成器所在的目錄,添加它到項(xiàng)目中,并使它面為主程序。我修改了該程序所指向的類庫,使它能找到我的VFP RI 生成器類的子類所在的類庫 (SFRIBUILDR.VCX) 并自動(dòng)注冊(cè)該生成器到VFP BUILDER 表中(如果是直接運(yùn)行該APP)。 生成并運(yùn)行SFRIBUILDR.APP 導(dǎo)致該文件作為RI生成器注冊(cè)取代了通常的RIBUILDR.APP。要看這一點(diǎn),按以下步驟進(jìn)行:
創(chuàng)建一個(gè)更好的升遷(Upsizing) 向?qū)? Jim Falino 在使用升遷向?qū)r(shí)失敗了,因此他創(chuàng)建了一個(gè)具有他所希望的行為的版本。
Jim 的修改是讓用戶指定他們的要求; 你可以使用它們?nèi)绻愕男枰c之相同,或?qū)⑺麄冏鳛槟0迨褂靡员隳阕约盒薷摹? 創(chuàng)建一個(gè)更好用的WWW 搜索頁向?qū)? 在 "Visual FoxPro 6 企業(yè)開發(fā)" (Prima Tech,ISBN 0-7615-1381-7)一書中,Rod Paddock 和 John Petersen 描述了如何修改WWW 搜索頁向?qū)砣∠荒茌敵?個(gè)字段到一個(gè)網(wǎng)頁的局限。勝于修改向?qū)?,你?huì)希望派生它們。要這樣做,用我派生生成器類的相似的方法。WWW 搜索頁向?qū)У拇a在VFP 向?qū)г茨夸浵碌腤IZARDS\WZINTNET 目錄中。 第九節(jié) 創(chuàng)建你自己的向?qū)? Rod Paddock 和John Petersen 也在他們的書中也提供了一些使用VFP 向?qū)ь悂斫⒛阕约旱南驅(qū)У募?xì)節(jié)。這樣做的優(yōu)點(diǎn)是,有人已經(jīng)建立了所有的"引擎"來管理向?qū)幚?,且你的向?qū)⑴c其它的VFP向?qū)Ь哂邢嗤母杏^。 用BuilderD 創(chuàng)建生成器 在查看VFP6中的FoxPro基本類時(shí)(FFC),我注意到一件事是它們都具有叫做Builder和BuilderX的自定義屬性,并且各個(gè)類的BuilderX 是設(shè)置為= HOME() + "Wizards\BuilderD,BuilderDForm"。我知道這些屬性的作用(他們告訴VFP,這個(gè)類的生成器名),但為什么每一個(gè)類都要指定相同的生成器呢?更有趣的是,各個(gè)類以不同的選項(xiàng)調(diào)用類似的生成器表單(圖1顯示_HyperLinkLabel 類的生成器)。當(dāng)使用相同的類時(shí)將會(huì)發(fā)生什么情況呢?
首先介紹一點(diǎn)背境??赡苷竽憧赡芤庾R(shí)到的,VFP 生成器可能以多種方式調(diào)用,但最常見的是可能是在對(duì)象上右擊鼠標(biāo)并從出現(xiàn)的菜單上選擇生成器。這會(huì)使BUILDER.APP 被執(zhí)行。BUILDER.APP 檢查是否選定的對(duì)象(我們稱為"目標(biāo)對(duì)象") 具有 BuilderX 屬性,如果有,運(yùn)行該屬性指定的程序或?qū)嵗撛搶傩灾付ǖ念?如果生成器是一個(gè)類,將指定一個(gè)類庫,逗號(hào)及類名)。如果它沒有 BuilderX 屬性但有一個(gè) Builder 屬性,生成器運(yùn)行該屬性指定的程序或?qū)嵗撛搶傩灾付ǖ念?我們將看到為什么會(huì)同時(shí)用兩個(gè)屬性指定生成器)。如果兩個(gè)屬性都不存在,將使用該對(duì)象基類的默認(rèn)生成器。 你可以在你的類中建立自定義的 Builder 和 BuilderX 屬性(甚至在你的基類中) 然后為每一個(gè)類填寫適當(dāng)?shù)纳善髅帧R褂脙蓚€(gè)屬性的理由是 BuilderX 為該類指定一個(gè)自定義生成器 而Builder為一組公共的類(如comboboxe 或 grid)指定一個(gè)所需的生成器。正如我們稍后會(huì)看到的一樣,我們可以在 BuilderX 屬性中指定的生成器中,單擊一個(gè)按鈕來調(diào)出在 Builder 屬性中指定的生成器。 因此,我們可以很容易地在 Builder 和 BuilderX 屬性中指定生成器。而不是花很多時(shí)間來建立你自己的生成器,特別對(duì)于不常使用的類。 BuilderD 你可能意識(shí)到了 BuilderB 技術(shù) 用來建立生成器是容易的和快速的。BuilderB 是一組你可以派生來建立你自己的生成器的類。你可以為你想用生成器維護(hù)的目標(biāo)對(duì)象的各屬性添加一個(gè)控件到生成器子類。雖然BuilderB 使得建立生成器更容易,但你必須為每一個(gè)你想用生成器管理的類建立一個(gè)新的生成器子類。對(duì)于我們這樣的懶人來說,幸運(yùn)的是,Ken 以數(shù)據(jù)驅(qū)動(dòng)的方式增強(qiáng)了BuilderB。這種新技術(shù)叫做BuilderD ,"D" 的意思是"動(dòng)態(tài)" (Dynamic),可以在Ken 的網(wǎng)站(www.classx.com)找到,也包含在VFP 6 中(在VFP 主目錄下的WIZARDS 目錄中的BUILDERD.VCX)。 BuilderD 由一系列的類組成,但主要的一個(gè)是BuilderDForm; 這是一個(gè)數(shù)據(jù)驅(qū)動(dòng)生成器表單 (注意這是VFP6.0的基本類中指定的BuilderX類)。正如你在圖2中看到,該表單中的文本框用于輸入目標(biāo)類的名字和類名,按鈕提供的功能可以調(diào)出類瀏覽器和顯示幫助,一個(gè)頁框、兩個(gè)頁面,但沒有用于管理屬性值的控件。
以下是該表單在實(shí)例化時(shí),如何組合適當(dāng)?shù)目丶?
這些步驟的結(jié)果是,一個(gè)生成器可以管理目標(biāo)對(duì)象的一個(gè)或更多的屬性。一個(gè)指定的生成器可以事實(shí)上做得比這些還要多,例如放置代碼到目標(biāo)對(duì)象的方法或?qū)ο蟮娜萜髦?,介是目前我們只使用最簡單的方法?/p> BuilderD 表 讓我們進(jìn)一步了解生成器定義表BUILDERD.DBF,因?yàn)槔斫馑慕Y(jié)構(gòu)是建立你自己的生成器的關(guān)鍵。表2 顯示了BUILDERD.DBF表的結(jié)構(gòu); 在該表中,"property control" 意思是生成器中的、維護(hù)一個(gè)目標(biāo)對(duì)象的指定屬性的控件。
表 1. BUILDERD.DBF的結(jié)構(gòu) 表2 和 3 顯示了兩個(gè)生成器的記錄,VFP6.0的基本類_HyperLinkBase 和_HyperLinkLabel 類。我沒有顯示BUILDERD.DBF 表中的所有字段,出于空間的考慮; 僅列出與討論有關(guān)的字段。
表 2. _HyperLinkBase 和 _HyperLinkLabel 類的生成器記錄
表 3. _HyperLinkBase 和 _HyperLinkLabel 生成器管理的屬性定義記錄 在表2 中的 _HyperLinkBase記錄中,我們看見CLASSNAME 和 CLASSLIB 指定了該生成器使用的類(注意CLASSLIB 包含了一個(gè)在運(yùn)行時(shí)求值的表達(dá)式而不是一個(gè)硬編碼值),在LINKS 中列了出該生成器可管理的類的屬性。顯示在表3中的cTarget PROPERTY 記錄指明該屬性將被BuilderComboBox 控件管理,且該BuilderComboBox的RowSource 包含一個(gè) Microsoft VFP 網(wǎng)站的URL (目前是msdn.microsoft.com/vfoxpro)。cFrame 將被 BuilderTextBox 對(duì)象管理(因?yàn)樗且粋€(gè)字符串屬性且該類沒有定義),lNewWindow 將有一個(gè)BuilderCheckBox 對(duì)象(因?yàn)樗且粋€(gè)邏輯屬性)。 看起來是如此簡單,對(duì)吧? 好了,LINKS 字段事實(shí)上可以更加復(fù)雜。首先,假如在LINKS字段中指定的類記錄的ID 沒有匹配記錄,該ID 就被假設(shè)為屬性名。 這樣,你可以簡單的在CLASS記錄的LINKS字段中指定它管理的屬性來實(shí)際建立一個(gè)生成器。當(dāng)然,你必須保持屬性的 captions 和屬性的名字相同,沒有狀態(tài)條文本、默認(rèn)的類和屬性大小,但這些對(duì)于一個(gè)快速的和dirty 生成器來說都不算太壞。 第二個(gè)復(fù)雜之處是,CLASS記錄的LINKS字段中指定的ID 可以指向另一個(gè)CLASS 記錄而不是一個(gè)PROPERTY 記錄。在這種情況下,該類 "繼承"所有指定類的連接。你可以在表2中的_HyperLinkLabel 記錄中看到這一點(diǎn); 它的一個(gè)連接是_HyperLinkBase,因此它不僅用該類的生成器來管理Caption 屬性(specifically 在它的 LINKS 字段中列出),同時(shí)也管理cTarget、cFrame和lNewWindow 屬性,因?yàn)檫@些在_HyperLinkBase 的LINKS 字段中指定。 第三,PROPERTY 記錄可以連接到另一個(gè)PROPERTY 記錄。在這種情況下,記錄"繼承"連接記錄的所有非空字段。最后,如果你用@<caption> 格式指定它,LINKS 可以包含生成器中的頁框的標(biāo)題 (例如,@Properties 使用"Properties" 作為頁的標(biāo)題)。 創(chuàng)建一個(gè)生成器 讓我們?cè)赥EST.VCX類庫中創(chuàng)建一個(gè)名為TestCheck的 VFP CheckBox 的子類作為開始。在該類中添加一個(gè)叫做BuilderX 的自定義屬性并設(shè)置它的值為= HOME() + "Wizards\BuilderD,BuilderDForm"。然后在該類上右擊鼠標(biāo)并從快捷菜單中選擇生成器。我們得到一條"沒有注冊(cè)該類型的生成器"的錯(cuò)誤。這也說得通,因?yàn)槲覀冞€沒有定義它 (盡管這令人不愉快,在稍后它將自動(dòng)為我們建立一個(gè))。按以下步驟做:
酷不酷,嗯? 完全是你自己的生成器,僅在一分鐘左右就建立了! 去掉Enabled 的選擇并輸入一個(gè)不同的Caption,并可看到這些屬性已被修改。 注意不要被為屬性建立記錄所迷惑; Enabled 和 Caption 記錄已存在于 BUILDERD.DBF表中,因此我們只需重用它們,而且由于不存在 AutoSize 記錄,BuilderD 只假設(shè)我們想管理那個(gè)屬性。 讓我們?cè)俳⒁粋€(gè)并看看以多小的輸入可以得到一個(gè)可工作的生成器。在TEST.VCX類庫中創(chuàng)建一個(gè)名為TestText的 VFP TextBox 的子類,向它添加一個(gè)屬性 BuilderX 并設(shè)置它的值為 = HOME() + "Wizards\BuilderD,BuilderDForm"。在BUILDERD.DBF 中添加一條記錄并只指定 TYPE ("CLASS"),ID ("TestText"),LINKS ("ReadOnly")和 CLASSNAME ("TestText";我們可以跳過 CLASSLIB 但 CLASSNAME 是必須的)。關(guān)閉該表,然后調(diào)出該類的生成器。 這也是一個(gè)可以工作的生成器。單擊生成器中的生成器按鈕; 它調(diào)出另一個(gè)生成器(如果Builder屬性存在并非空,在Builder屬性中指定的生成器,否則就是該類的基類的默認(rèn)生成器,在此例中是 VFP TextBox 生成器)。這樣,即使我們可以為一個(gè)類指定生成器,只要愿意,我們?nèi)匀豢梢栽L問更多的普通生成器。 預(yù)置-內(nèi)建的生成器 我最近用BuilderD 建立了兩個(gè)生成器,一個(gè)為我的SFGrid 類另一個(gè)為SFPageFrame。SFGrid 生成器維護(hù)DeleteMark 和RecordMark 屬性(你可以很容易地添加其它你可能經(jīng)常修改的屬性) 但由于它們?nèi)菀自趯傩源翱谥行薷模赃@不是我要建立該生成器的真正的理由。真正的理由是因?yàn)槲蚁矚g使用grid 的columns 中的SFGridTextBox 對(duì)象(SFTextBox 的一個(gè)子類,具有一小部分不同的屬性設(shè)置,以提供它們?cè)?grid中出現(xiàn)的外觀),并盡量用SFGridTextBox對(duì)象替換一般的TextBox 對(duì)象。 因此我建立了一個(gè)按鈕(SFBUILDERS.VCX類庫中的SFGridTextBoxButton類) 來自動(dòng)進(jìn)行該工作。以下是該按鈕的 Click 方法代碼:
BuilderDForm 有一個(gè)引用到目標(biāo)對(duì)象保存在它的 oObject 屬性,因此生成器表單上的許多控件可以引用或修改目標(biāo)對(duì)象的東西。在這些代碼中,Thisform.oObject.Columns 引用grid 的Columns 集合被生成器影響。 這里有一個(gè)副作用:我怎樣才能在我的生成器表單中得到該按鈕? 我可以為我的生成器在BUILDERD表中建立一個(gè)記錄,但那會(huì)添加按鈕到頁框中的一個(gè)頁上,而我確希望該按鈕象其它的生成器按鈕一樣出現(xiàn)。 因此我建立了一個(gè) "button loader" 類 (SFBUILDERS.VCX類庫中的SFBuilderButtonLoader類),該類添加一個(gè)按鈕到生成器表單然后返回 .F. 這樣,它實(shí)際上沒有實(shí)例化。SFBuilderButtonLoader 在BUILDERD表的當(dāng)前記錄的備注字段 USER 中查找(使用類實(shí)例化的記錄) 要添加到表單的按鈕的類名和類庫(注意下面代碼中的 BUILDERD 是以 "BUILDER"別名打開的)。對(duì)于SFGridTextBoxButton,例如,我在BUILDERD表中建立一條記錄,以 "SFGridTextBoxButton" 作為它的 ID 但 "SFBuilderButtonLoader" 是一個(gè)類,并在USER字段中輸入 "SFBuilders, SFGridTextBoxButton"。這告訴 SFBuilderButtonLoader 添加一個(gè) SFGridTextBoxButton 到表單中。以下是SFBuilderButtonLoader的 Init 方法代碼:
在BUILDERD表中 SFGrid 記錄的LINKS字段中有 DeleteMark、RecordMark 和 SFGridTextBox,因此該生成器獲得這些控件。 現(xiàn)在我可以為我的SFGrid對(duì)象調(diào)出我的BuilderD 生成器,使用 VFP Grid 生成器(單擊BuilderD表單上的生成器按鈕) 來快速建立 grid中的列,然后單擊我的添加SFGridTextBox按鈕來讓這些列使用 SFGridTextBox 對(duì)象。 對(duì)于 SFPageFrame,我也希望相似的功能:一個(gè)添加代碼到頁框中各頁的RightClick方法的按鈕; 這允許在頁面上右擊鼠標(biāo)明時(shí)為頁框或整個(gè)表單提供快捷菜單。象SFGrid 生成器一樣,我在BuilderD表中建立了一個(gè)記錄來實(shí)例化一個(gè) SFBuilderButtonLoader 對(duì)象,然后添加一個(gè) SFCodePageButton 對(duì)象到生成器表單。以下是添加代碼到各頁的SFCodePageButton的Click方法:
要添加這些新的生成器到你的系統(tǒng)中,復(fù)制 SFBUILDERS.VCX 和 VCT (在本文檔的源代碼文件中可以找到) 到一個(gè)目錄,然后打開示例文件提供的NEWBUILDERS 表,并修改 CLASSLIB 字段到包含路徑的 SFBUILDERS.VCX文件名。打開 BUILDERD 表,然后 APPEND FROM NEWBUILDERS 表,添加Builder 和BuilderX 屬性到你的類中,并在BuilderX中輸入 = HOME() + "Wizards\BuilderD,BuilderDForm"。 其它生成器類 我早些時(shí)候注意到,SFBUILDERS.VCX 中的BuilderCheckBox 和 BuilderTextBox 類都是派生自同一個(gè)BuilderD 類。在附加的右擊鼠標(biāo)行為中,這兩個(gè)類具有nTop 和 nLeft 屬性,當(dāng)這些屬性改變時(shí),用assign 方法設(shè)置它們的自定義的lMoved 屬性為.T.。這允許我們查覺到什么時(shí)候一個(gè)屬性控件被移動(dòng)了(在屬性控件生成器中的Left 和Top 是綁定至 nLeft 和 nTop 而不是直接綁定到 Left 和 Top)。只有當(dāng)一個(gè)屬性控件移動(dòng)時(shí),我們保存它的its Left 和 Top 值到 BUILDERD 表。 SFBUILDERS.VCX 中的加一個(gè)類是 SFPropertyCaption。該控件用于管理屬性控件的 caption。 為什么用一個(gè)特別的類來做這件事? 為什么不用一個(gè)普通的BuilderTextBox 對(duì)象? 理由是如果屬性控件是一個(gè)BuilderCheckBox,它有一個(gè) Caption 屬性,因此控件管理該屬性。但是,如果屬性控件是一個(gè) BuilderTextBox,它沒有 Caption 屬性但確有一個(gè)組合的 label 對(duì)象,因此控件必須管理對(duì)象的對(duì)象的 Caption 屬性。由于 BuilderD 類只管理單個(gè)對(duì)象的屬性,SFPropertyCaption 不得不超越(override)少量方法來允許它處理這種情況。 SFBuilderPropertyComboBox 類是BuilderComboBox的一個(gè)子類。它提供一個(gè)目標(biāo)對(duì)象的所有可寫屬性的一個(gè)列表(用 AMEMBERS() 得到所有屬性的列表然后檢查各自的PEMSTATUS()來排除只讀的)。雖然它的主要目的是修改屬性控件的 cProperty 屬性(用于檢查要管理的屬性),它有兩個(gè)有趣的行為。 首先,如果屬性控件是一個(gè)BuilderTextBox 但你只修改了它管理的邏輯屬性(如 Enabled),它移去BuilderTextBox 及組合的label 對(duì)象,并放一個(gè) BuilderCheckBox 在這個(gè)地方。如果你改變了一個(gè)邏輯屬性為另一個(gè)類型它會(huì)做相反的事。 第二,如果你輸入了一個(gè)不存在的屬性名,你會(huì)被提示建立該屬性。如果你同意,生成器使用AddProperty 來添加新屬性到目標(biāo)對(duì)象。我的確不推薦在一個(gè)拖放到表單中的對(duì)象上這樣做,因?yàn)檫@等于實(shí)例化編程; 如果你真的需要一個(gè)新屬性,你可以考慮用子類來代替。 總之,這是一個(gè)經(jīng)一個(gè)步驟在類中建立新屬性并用生成器管理它的快速方法。 SFBuilderAddButton 是一個(gè)為了屬性控件使用 SFBuilderButtonLoader 類而添加到生成器表單的按鈕類 (派生自BuilderCommandButton)。SFBuilderAddButton 的Click方簡單地調(diào)用屬性控件所在的生成器表單的 AddPropertyControl 方法來建立一個(gè)新的屬性控件,然后轉(zhuǎn)換當(dāng)前生成器表單來管理新屬性控件。 這意味著你可以單擊添加屬性按鈕添加一個(gè)新屬性到生成器,并在生成器中管理它。這是一種添加多個(gè)屬性控件的快速方法。 試一試 讓我們看一看SFBuilderBuilderForm; 它實(shí)際上比對(duì)它的描述更易于使用。在TEST.VCX中建立一個(gè)叫做 MyTestText 的VFP TextBox 類的子類。添加一個(gè) BuilderX 屬性并設(shè)置它的值為 "SFBuilders,SFBuilderBuilderForm",然后調(diào)出該類的生成器。 注意盡管我們沒有在BUILDERD 表中建立任何記錄,我們?nèi)匀坏玫搅艘粋€(gè)生成器表單(當(dāng)然,表單上沒有控件,但我們馬上會(huì)改變這一切)。 這是因?yàn)?SFBuilderBuilderForm 在不能找到該類的記錄時(shí),自動(dòng)地為該類在BUILDERD表中建立了一個(gè) CLASS 記錄。 單擊添加屬性控件按鈕。你會(huì)注意到一個(gè)文本框和標(biāo)簽出現(xiàn)在生成器表單上,但隨后另一個(gè)生成器表單出現(xiàn)在該生成器表單的面上。這個(gè)新的表單是我們剛添加的屬性控件的生成器。在屬性 combobox中,選擇 "Tooltiptext" 并修改 Caption 為 "Tool Tip Text" 和 Width 到250。移動(dòng)該生成器表單在一旁并注意原表單上的屬性控件也同樣修改了。 單擊第二個(gè)生成器表單上的添加另一屬性按鈕并注意另一個(gè)屬性控件已添加到原生成器表單中,并且該生成器表單現(xiàn)在可以管理它了。為屬性選擇"Statusbartext" 并修改Caption 為"Status Bar Text" 和Width 到250。添加另一個(gè)屬性控件,并為該屬性選擇 "Readonly" 并修改Caption 到"Read-Only"; 這時(shí),注意原生成器屬性控制改變了checkbox。關(guān)閉新的生成器表單。圖3 顯示了我們建立的生成器,圖4 顯示了屬性控件生成器。
要修改控件的屬性,在控件上右擊鼠標(biāo)并從快捷菜單中選擇修改屬性修改控件; 你以前看到過的相同的屬性控件生成器會(huì)出現(xiàn)。要移去屬性控件,從菜單中選擇移去屬性控件。要重置目標(biāo)對(duì)象的該屬性的值為默認(rèn)值,選擇重置為默認(rèn)值。 讓我們修改生成器表單的標(biāo)題為更為合適的東西。單擊修改生成器標(biāo)題按鈕并在隨后出現(xiàn)的SFBuilderBuilder生成器表單中輸入 "我的測試文本框類生成器" 。關(guān)閉第二個(gè)生成器。 如果你在關(guān)閉生成器時(shí)沒有保存,下一次你再調(diào)用 MyTestText 對(duì)象的生成器時(shí),你的設(shè)置不會(huì)起作用。若要保存生成器的定義到 BUILDERD 表中,單擊保存生成器按鈕。如果你想導(dǎo)出生成器定義到另一個(gè)表中,單擊導(dǎo)出生成器按鈕并在出現(xiàn)的對(duì)話框中輸入文件名。然后你可以發(fā)送該表給一些人,他們可以將其導(dǎo)入他們的 BUILDERD 表并訪問你建立的生成器。 說明 因?yàn)閂FP的開放式IDE,任何人都可以很容易地定制它們的開發(fā)環(huán)境,因此他們和他們的開發(fā)組可以極大地提高編程效率。 第十節(jié) 示例 例1:在程序開始時(shí)設(shè)置系統(tǒng)環(huán)境 *-- 設(shè)置工作目錄 cCurrentProcedure = SYS(16,1) nPathStart = AT(":",cCurrentProcedure) - 1 nLenOfPath = RAT("\", cCurrentProcedure,2) - (nPathStart) SET DEFAULT TO (SUBSTR(cCurrentProcedure, nPathStart, nLenOfPath)) SET PATH TO PROGS,LIBS,MENUS,HELP,INCLUDE,FORMS,BITMAPS *-- 修改程序標(biāo)題并將屏幕放到最大,在編譯成.EXE的文件運(yùn)行時(shí),這是必須的 MODIFY WINDOW SCREEN TITLE "測試" NOCLOSE ZOOM WINDOW SCREEN MAX *-- 屏蔽系統(tǒng)菜單 SET SYSMENU OFF *--定義用于保存系統(tǒng)設(shè)置的全局變量 PUBLIC ; GcOldTalk,; gcOldPath,; gcOldDir,; gcOldClassLib,; gcOldEscape,; gcOldSafety,; gcOldProc,; gcOldStatus,; gnOldMemo,; gcOldMultiLocks,; gcOldHelp,; gcOldDeleted,; gcOldExclusive,; gcOldNotify,; gcOldBell,; gcOldNear,; gcOldExact,; gcOldIntensity,; gcOldConfirm,; gcOldOnShutDown,; gcOldCompatible *--保存原始的系統(tǒng)狀態(tài),以便在退出時(shí)恢復(fù) GcOldTalk = SET("TALK") gcOldPath = SET("PATH") gcOldDir = FULLPATH(CURDIR()) gcOldClassLib = SET("CLASSLIB") gcOldEscape = SET("ESCAPE") gcOldSafety = SET('SAFETY') gcOldProc = SET('PROCEDURE') gcOldStatus = SET('STATUS BAR') gnOldMemo = SET('MEMOWIDTH') gcOldMultiLocks = SET('MULTILOCKS') gcOldHelp = SET('HELP', 1) gcOldDeleted = SET('DELETED') gcOldExclusive = SET('EXCLUSIVE') gcOldNotify = SET('NOTIFY') gcOldBell = SET('BELL') gcOldNear = SET('NEAR') gcOldExact = SET('EXACT') gcOldIntensity = SET('INTENSITY') gcOldConfirm = SET('CONFIRM') gcOldOnShutDown = ON('SHUTDOWN') gcOldCompatible = SET("COMPATIBLE") gcOldDate = SET("DATE") gcOldCentury = SET("CENTURY") *-- 設(shè)置SET 和ON 命令 SET SAFETY OFF SET PROCEDURE TO UTILITY.PRG SET CLASSLIB TO MAIN SET MEMOWIDTH TO 120 SET MULTILOCKS ON SET HELP TO HELP\MAIN.CHM SET DELETED ON SET EXCLUSIVE OFF SET NOTIFY OFF SET BELL OFF SET NEAR OFF SET EXACT OFF SET INTENSITY OFF SET CONFIRM ON SET COMPATIBLE OFF SET DATE ANSI SET CENTURY ON SET ESCAPE OFF ON SHUTDOWN DO OnShutDown 注意:運(yùn)行上述代碼時(shí)程序文件UTILITY.PRG,OnShutDown,類庫文件MAIN及幫助文件MAIN.CHM必須存在。 例2:在程序結(jié)束時(shí)恢復(fù)系統(tǒng)環(huán)境 LOCAL luTemp SET PATH TO (gcOldPath) luTemp = gcOldClassLib SET CLASSLIB TO &luTemp luTemp = gcOldProc SET PROCEDURE TO &luTemp SET MEMOWIDTH TO gnOldMemo luTemp = gcOldMultiLocks SET MULTILOCKS &luTemp luTemp = gcOldSafety SET SAFETY &luTemp luTemp = gcOldStatus SET STATUS BAR &luTemp CD (gcOldDir) luTemp = gcOldDeleted SET DELETED &luTemp luTemp = gcOldExclusive SET EXCLUSIVE &luTemp IF FILE(gcOldHelp) SET HELP TO (gcOldHelp) ENDIF luTemp = gcOldNotify SET NOTIFY &luTemp luTemp = gcOldBell SET BELL &luTemp luTemp = gcOldNear SET NEAR &luTemp luTemp = gcOldExact SET EXACT &luTemp luTemp = gcOldIntensity SET INTENSITY &luTemp luTemp = gcOldConfirm SET CONFIRM &luTemp luTemp = gcOldOnShutdown ON SHUTDOWN &luTemp luTemp = gcOldEscape SET ESCAPE &luTemp luTemp = gcOldCompatible SET COMPATIBLE &luTemp luTemp = gcOldTalk SET TALK &luTemp luTemp = gcOldDate SET DATE &luTemp luTemp = gcOldCentury SET CENTURY &luTemp CLOSE ALL CLEAR DLLS RELEASE ALL EXTENDED CLEAR ALL 例3:程序崩潰時(shí)恢復(fù)系統(tǒng)環(huán)境 在程序設(shè)計(jì)期間,有時(shí)會(huì)因程序錯(cuò)誤而使系統(tǒng)崩潰。當(dāng)系統(tǒng)崩潰時(shí),可能會(huì)有打開的表沒有關(guān)閉,數(shù)據(jù)工作期不能釋放,表單在屏幕上不能清除,菜單沒有釋放等一系列令人心煩的事。當(dāng)你要手工地恢復(fù)系統(tǒng)到初使?fàn)顟B(tài)真還要費(fèi)不少事,但是你可以自己編寫一個(gè)過程文件來自動(dòng)完成這些工作。這樣,當(dāng)系統(tǒng)崩潰時(shí),你只需在命令窗口打入 DO XXX 即可。 *:****************************************************************************** *: *: 過程文件C:\HIGHMIS\HF.PRG *: *:****************************************************************************** ON ERROR SET PROCEDURE TO POP KEY ALL SET COLOR TO SET SYSMENU TO DEFA CLOSE ALL RELEAS ALL EXTE CLEAR DLLS CLEAR EVENTS CLEAR FIELDS CLEAR GETS CLEAR MACROS CLEAR MEMORY CLEAR MENUS CLEAR POPUPS CLEAR PROGRAM CLEAR PROMPT CLEAR READ ALL CLEAR TYPEAHEAD CLEAR WINDOWS SET DEVICE TO SCREEN CLEAR SET EXCL ON SET TALK ON SET MESSAGE ON RELEASE WINDOW 常用 SET HELP TO SET HELP ON CANCEL 例4:查看系統(tǒng)設(shè)置 *:****************************************************************************** *: *: 過程文件C:\HIGHMIS\PROGS\SYSTEST.PRG *: * 用途:查看當(dāng)前系統(tǒng)信息 ************************************************************************** PROCEDURE SYSTEST PARAMETERS T__Method, T__File RELEASE ALL EXCEPT T__* PRIVATE ALL LIKE T__* CREATE VIEW it SET TALK OFF CLOSE ALL SET SAFETY OFF SET ALTERNATE TO (IIF(EMPTY(T__File), "SysTest.TXT", T__File)) SET ALTERNATE ON SET SAFETY ON SET EXACT OFF T__IsVisual = .T. T__OutputFile = SET("ALTERNATE", 1) DEFINE WINDOW T__win FROM 0,0 TO SROWS(),SCOLS() TITLE T__OutputFile CLOSE SYSTEM ZOOM ACTIVATE WINDOW T__win ??"*** SysTest Version 2.00","日期",DATE(),"時(shí)間",TIME(),"***" T__IsError = .F. IF (EMPTY(m.T__Method) OR UPPER(m.T__Method)="SET") WAIT WINDOW NOWAIT "*** SET() ***" ? ? "*** SET() ***" ?PADR("SET(ALTERNATE)",30) + " == ", SET("ALTERNATE") ?PADR("SET(ANSI)",30) + " == ", SET("ANSI") ?PADR("SET(AUTOSAVE)",30) + " == ", SET("AUTOSAVE") ?PADR("SET(BELL)",30) + " == ", SET("BELL") ?PADR("SET(BLINK)",30) + " == ", SET("BLINK") ?PADR("SET(BLOCKSIZE)",30) + " == ", SET("BLOCKSIZE") ?PADR("SET(BRSTATUS)",30) + " == ", SET("BRSTATUS") ?PADR("SET(CARRY)",30) + " == ", SET("CARRY") ?PADR("SET(CENTURY)",30) + " == ", SET("CENTURY") ?PADR("SET(CLASSLIB)",30) + " == ", SET("CLASSLIB") ?PADR("SET(CLEAR)",30) + " == ", SET("CLEAR") ?PADR("SET(CLOCK)",30) + " == ", SET("CLOCK") ?PADR("SET(COLOR)",30) + " == ", SET("COLOR") ?PADR("SET(COMPATIBLE)",30) + " == ", SET("COMPATIBLE") ?PADR("SET(CONFIRM)",30) + " == ", SET("CONFIRM") ?PADR("SET(CONSOLE)",30) + " == ", SET("CONSOLE") ?PADR("SET(CURRENCY)",30) + " == ", SET("CURRENCY") ?PADR("SET(CURSOR)",30) + " == ", SET("CURSOR") ?PADR("SET(DATE)",30) + " == ", SET("DATE") ?PADR("SET(DEBUG)",30) + " == ", SET("DEBUG") ?PADR("SET(DECIMALS)",30) + " == ", SET("DECIMALS") ?PADR("SET(DEFAULT)",30) + " == ", SET("DEFAULT") ?PADR("SET(DELETED)",30) + " == ", SET("DELETED") ?PADR("SET(DELIMITERS)",30) + " == ", SET("DELIMITERS") ?PADR("SET(DEVELOPMENT)",30) + " == ", SET("DEVELOPMENT") ?PADR("SET(DEVICE)",30) + " == ", SET("DEVICE") ?PADR("SET(DISPLAY)",30) + " == ", SET("DISPLAY") ?PADR("SET(DOHISTORY)",30) + " == ", SET("DOHISTORY") ?PADR("SET(ECHO)",30) + " == ", SET("ECHO") ?PADR("SET(ESCAPE)",30) + " == ", SET("ESCAPE") ?PADR("SET(EXACT)",30) + " == ", SET("EXACT") ?PADR("SET(EXCLUSIVE)",30) + " == ", SET("EXCLUSIVE") ?PADR("SET(FIELDS)",30) + " == ", SET("FIELDS") ?PADR("SET(FILTER)",30) + " == ", SET("FILTER") ?PADR("SET(FIXED)",30) + " == ", SET("FIXED") ?PADR("SET(FULLPATH)",30) + " == ", SET("FULLPATH") ?PADR("SET(HEADING)",30) + " == ", SET("HEADING") ?PADR("SET(HELP)",30) + " == ", SET("HELP") ?PADR("SET(HISTORY)",30) + " == ", SET("HISTORY") ?PADR("SET(HOURS)",30) + " == ", SET("HOURS") ?PADR("SET(INTENSITY)",30) + " == ", SET("INTENSITY") ?PADR("SET(KEYCOMP)",30) + " == ", SET("KEYCOMP") ?PADR("SET(LIBRARY)",30) + " == ", SET("LIBRARY") ?PADR("SET(LOCK)",30) + " == ", SET("LOCK") ?PADR("SET(LOGERRORS)",30) + " == ", SET("LOGERRORS") ?PADR("SET(MACKEY)",30) + " == ", SET("MACKEY") ?PADR("SET(MARGIN)",30) + " == ", SET("MARGIN") ?PADR("SET(MARK)",30) + " == ", SET("MARK") ?PADR("SET(MEMOWIDTH)",30) + " == ", SET("MEMOWIDTH") ?PADR("SET(MENU)",30) + " == ", SET("MENU") ?PADR("SET(MESSAGE)",30) + " == ", SET("MESSAGE") ?PADR("SET(MOUSE)",30) + " == ", SET("MOUSE") ?PADR("SET(MULTILOCKS)",30) + " == ", SET("MULTILOCKS") ?PADR("SET(NEAR)",30) + " == ", SET("NEAR") ?PADR("SET(NOTIFY)",30) + " == ", SET("NOTIFY") ?PADR("SET(ODOMETER)",30) + " == ", SET("ODOMETER") ?PADR("SET(OPTIMIZE)",30) + " == ", SET("OPTIMIZE") ?PADR("SET(ORDER)",30) + " == ", SET("ORDER") ?PADR("SET(PALETTE)",30) + " == ", SET("PALETTE") ?PADR("SET(PATH)",30) + " == ", SET("PATH") ?PADR("SET(PDSETUP)",30) + " == ", SET("PDSETUP") ?PADR("SET(POINT)",30) + " == ", SET("POINT") ?PADR("SET(PRINTER)",30) + " == ", SET("PRINTER") ?PADR("SET(PROCEDURE)",30) + " == ", SET("PROCEDURE") ?PADR("SET(REFRESH)",30) + " == ", SET("REFRESH") ?PADR("SET(REPROCESS)",30) + " == ", SET("REPROCESS") ?PADR("SET(RESOURCE)",30) + " == ", SET("RESOURCE") ?PADR("SET(SAFETY)",30) + " == ", SET("SAFETY") ?PADR("SET(SCOREBOARD)",30) + " == ", SET("SCOREBOARD") ?PADR("SET(SEPARATOR)",30) + " == ", SET("SEPARATOR") ?PADR("SET(SHADOWS)",30) + " == ", SET("SHADOWS") ?PADR("SET(SPACE)",30) + " == ", SET("SPACE") ?PADR("SET(STATUS)",30) + " == ", SET("STATUS") ?PADR("SET(STATUS BAR)",30) + " == ", SET("STATUS BAR") ?PADR("SET(STEP)",30) + " == ", SET("STEP") ?PADR("SET(STICKY)",30) + " == ", SET("STICKY") ?PADR("SET(SYSMENU)",30) + " == ", SET("SYSMENU") ?PADR("SET(TALK)",30) + " == ", SET("TALK") ?PADR("SET(TEXTMERGE)",30) + " == ", SET("TEXTMERGE") ?PADR("SET(TOPIC)",30) + " == ", SET("TOPIC") ?PADR("SET(TYPEAHEAD)",30) + " == ", SET("TYPEAHEAD") ?PADR("SET(UDFPARMS)",30) + " == ", SET("UDFPARMS") ?PADR("SET(UNIQUE)",30) + " == ", SET("UNIQUE") ?PADR("SET(ALTERNATE,1)",30) + " == ", SET("ALTERNATE",1) ?PADR("SET(CLOCK,1)",30) + " == ", SET("CLOCK",1) ?PADR("SET(CURRENCY,1)",30) + " == ", SET("CURRENCY",1) ?PADR("SET(DELIMITERS,1)",30) + " == ", SET("DELIMITERS",1) ?PADR("SET(FIELDS,1)",30) + " == ", SET("FIELDS",1) ?PADR("SET(HELP,1)",30) + " == ", SET("HELP",1) ?PADR("SET(MESSAGE,1)",30) + " == ", SET("MESSAGE",1) ?PADR("SET(PRINTER,1)",30) + " == ", SET("PRINTER",1) ?PADR("SET(RESOURCE,1)",30) + " == ", SET("RESOURCE",1) ?PADR("SET(TALK,1)",30) + " == ", SET("TALK",1) ?PADR("SET(TEXTMERGE,1)",30) + " == ", SET("TEXTMERGE",1) ENDIF T__IsError = .F. IF (EMPTY(m.T__Method) OR UPPER(m.T__Method)="ON") WAIT WINDOW NOWAIT "*** ON() ***" ? ? "*** ON() ***" ?PADR("ON(ERROR)",30) + " == ", ON("ERROR") ?PADR("ON(ESCAPE)",30) + " == ", ON("ESCAPE") ?PADR("ON(KEY)",30) + " == ", ON("KEY") ?PADR("ON(KEY LABEL)",30) + " == ", ON("KEY LABEL") ?PADR("ON(PAGE)",30) + " == ", ON("PAGE") ?PADR("ON(READERROR)",30) + " == ", ON("READERROR") ?PADR("ON(SHUTDOWN)",30) + " == ", ON("SHUTDOWN") ENDIF T__IsError = .F. IF (EMPTY(m.T__Method) OR UPPER(m.T__Method)="MIS") WAIT WINDOW NOWAIT "其他設(shè)置" ? ? "其他設(shè)置" ?PADR("CAPSLOCK()",30) + " == ", EVALUATE("CAPSLOCK()") ?PADR("CPCURRENT()",30) + " == ", EVALUATE("CPCURRENT()") ?PADR("CPCURRENT(1)",30) + " == ", EVALUATE("CPCURRENT(1)") ?PADR("CPCURRENT(2)",30) + " == ", EVALUATE("CPCURRENT(2)") ?PADR("DISKSPACE()",30) + " == ", EVALUATE("DISKSPACE()") ?PADR("FULLPATH('')",30) + " == ", EVALUATE("FULLPATH('')") ?PADR("GETENV('COMSPEC')",30) + " == ", EVALUATE("GETENV('COMSPEC')") ?PADR("GETENV('FOXPROCFG')",30) + " == ", EVALUATE("GETENV('FOXPROCFG')") ?PADR("GETENV('FOXPROSWX')",30) + " == ", EVALUATE("GETENV('FOXPROSWX')") ?PADR("GETENV('FOXPROX')",30) + " == ", EVALUATE("GETENV('FOXPROX')") ?PADR("GETENV('PATH')",30) + " == ", EVALUATE("GETENV('PATH')") ?PADR("GETENV('TEMP')",30) + " == ", EVALUATE("GETENV('TEMP')") ?PADR("INSMODE()",30) + " == ", EVALUATE("INSMODE()") ?PADR("ISCOLOR()",30) + " == ", EVALUATE("ISCOLOR()") ?PADR("MEMORY()",30) + " == ", EVALUATE("MEMORY()") ?PADR("NUMLOCK()",30) + " == ", EVALUATE("NUMLOCK()") ?PADR("OS()",30) + " == ", EVALUATE("OS()") ?PADR("OS(1)",30) + " == ", EVALUATE("OS(1)") ?PADR("PRINTSTATUS()",30) + " == ", EVALUATE("PRINTSTATUS()") ?PADR("VERSION(1)",30) + " == ", EVALUATE("VERSION(1)") ?PADR("VERSION(2)",30) + " == ", EVALUATE("VERSION(2)") ?PADR("VERSION(3)",30) + " == ", EVALUATE("VERSION(3)") ENDIF T__IsError = .F. IF (EMPTY(m.T__Method) OR UPPER(m.T__Method)="VAR") WAIT WINDOW NOWAIT "系統(tǒng)內(nèi)存變量" ? ? "系統(tǒng)內(nèi)存變量" ?PADR("_ASCIICOLS",30) + " == ", EVALUATE("_ASCIICOLS") ?PADR("_ASCIIROWS",30) + " == ", EVALUATE("_ASCIIROWS") ?PADR("_BROWSER",30) + " == ", EVALUATE("_BROWSER") ?PADR("_BUILDER",30) + " == ", EVALUATE("_BUILDER") ?PADR("_CONVERTER",30) + " == ", EVALUATE("_CONVERTER") ?PADR("_DBLCLICK",30) + " == ", EVALUATE("_DBLCLICK") ?PADR("_GENGRAPH",30) + " == ", EVALUATE("_GENGRAPH") ?PADR("_GENMENU",30) + " == ", EVALUATE("_GENMENU") ?PADR("_GENPD",30) + " == ", EVALUATE("_GENPD") ?PADR("_GENSCRN",30) + " == ", EVALUATE("_GENSCRN") ?PADR("_GENXTAB",30) + " == ", EVALUATE("_GENXTAB") ?PADR("_PDRIVER",30) + " == ", EVALUATE("_PDRIVER") ?PADR("_PDSETUP",30) + " == ", EVALUATE("_PDSETUP") ?PADR("_SHELL",30) + " == ", EVALUATE("_SHELL") ?PADR("_SPELLCHK",30) + " == ", EVALUATE("_SPELLCHK") ?PADR("_STARTUP",30) + " == ", EVALUATE("_STARTUP") ?PADR("_TRANSPORT",30) + " == ", EVALUATE("_TRANSPORT") ?PADR("_WIZARD",30) + " == ", EVALUATE("_WIZARD") ENDIF T__IsError = .F. IF (EMPTY(m.T__Method) OR UPPER(m.T__Method)="FONT") WAIT WINDOW NOWAIT "可用字體" ? ? "可用字體" =AFONT(T__fonts) FOR T__i = 1 TO ALEN(T__fonts) T__string = T__fonts[m.T__i] + ": " IF AFONT(T__sizes, T__fonts[m.T__i]) FOR T__j = 1 TO ALEN(T__sizes) T__string = m.T__string+IIF(m.T__j==1, "", ", ")+; IIF(T__sizes[m.T__j]==-1,"scalable", LTRIM(STR(T__sizes[m.T__j]))) ENDFOR ENDIF ? m.T__string ENDFOR RELEASE T__i, T__j, T__fonts, T__sizes, T__string ENDIF T__IsError = .F. IF (EMPTY(m.T__Method) OR UPPER(m.T__Method)="CONFIG") FOR T__i = 1 TO 3 DO CASE CASE m.T__i==1 T__File = SYS(2019) IF EMPTY(m.T__File) T__File = SYS(2004)+"CONFIG.FPW" ENDIF CASE m.T__i==2 T__File = "C:\CONFIG.SYS" CASE m.T__i==3 T__File = "C:\AUTOEXEC.BAT" ENDCASE WAIT WINDOW NOWAIT "配置文件" ? DO CASE CASE m.T__i==1 T__File = SYS(2019) IF EMPTY(m.T__File) T__File = SYS(2004)+"CONFIG.FPW" ? "*** " + "配置文件" + SYS(2004) + " CONFIG.FPW ***" ELSE ? "*** " + "配置文件" + SYS(2019) + " CONFIG.FPW ***" ENDIF CASE m.T__i==2 T__File = "C:\CONFIG.SYS" ? "*** " + "配置文件" + "C:\CONFIG.SYS ***" CASE m.T__i==3 T__File = "C:\AUTOEXEC.BAT" ? "*** " + "配置文件" + "C:\AUTOEXEC.BAT ***" ENDCASE IF FILE(m.T__File) T__handle = FOPEN(m.T__File) IF m.T__handle>-1 DO WHILE NOT FEOF(m.T__handle) ? FGETS(m.T__handle) ENDDO =FCLOSE(m.T__handle) ELSE ? "不能打開文件." ENDIF ELSE ? "不能找到文件." ENDIF ENDFOR RELEASE T__File, T__handle, T__i ENDIF SET CONSOLE OFF ? "完成" SET CONSOLE ON CLOSE ALL T__handle = FOPEN(T__OutputFile, 2) IF NOT m.T__handle==-1 =FSEEK(m.T__handle, -1, 2) IF FREAD(m.T__handle,1)==CHR(26) =FCHSIZE(m.T__handle, FSEEK(m.T__handle, -1, 2)) ENDIF =FCLOSE(m.T__handle) ENDIF ACTIVATE SCREEN SET TALK OFF SET MESSAGE TO "檢查完成,結(jié)果已寫至" + T__OutputFile WAIT CLEAR ZOOM WINDOW T__win MAX MODIFY COMMAND (T__OutputFile) NOEDIT WINDOW T__win NOMENU RELEASE WINDOW T__win SET VIEW TO it.vue DELETE FILE it.vue SET MESSAGE TO " " RETURN
包含了有關(guān) Visual FoxPro 中聲音、程序設(shè)計(jì)、數(shù)據(jù)輸入的選項(xiàng)以及其它選項(xiàng)。
包含控制表中數(shù)據(jù)的選項(xiàng)。
遠(yuǎn)程數(shù)據(jù) 包含了有關(guān)遠(yuǎn)程 (ODBC) 視圖和連接默認(rèn)值的選項(xiàng)。
文件位置 包含了 Visual FoxPro 使用文件的目錄位置和名字??梢灾苯釉诿總€(gè)框中鍵入路徑和文件名,也可以單擊對(duì)話框按鈕激活對(duì)話框設(shè)置相應(yīng)的選項(xiàng)。
表單 包含“表單設(shè)計(jì)器”的選項(xiàng)。
項(xiàng)目 包含了有關(guān)“項(xiàng)目管理器”的選項(xiàng)。
控件 包含了為指定“選項(xiàng)”對(duì)話框中“表單”選項(xiàng)卡上的模板類而登記可視類庫的選項(xiàng)。這些選項(xiàng)也指定“表單控件”工具欄上“查看類”按鈕中可以選擇的內(nèi)容,這可以簡化向表單中添加用戶自定義控件的工作。
區(qū)域
調(diào)試 通過設(shè)置選項(xiàng)來定制 Visual FoxPro 調(diào)試器窗口。
語法著色 包含的選項(xiàng)可以指定顏色及字體,用來區(qū)分 Visual FoxPro 的程序元素,比如關(guān)鍵字和注釋。這些程序元素在命令窗口或所有編輯窗口(除用 MODIFY FILE 或 MODIFY MEMO 命令打開的編輯窗口之外)中使用。
字段映象
|
|