目中的安裝與集成實(shí)踐)
簡介這份DevExpress 14.1.3 for D7-XE7組件包面向使用Delphi 7及XE7的桌面與移動(dòng)端開發(fā)者是一套包含數(shù)據(jù)網(wǎng)格、圖表、報(bào)表、菜單、工具欄、對話框等常見VCL控件的成熟第三方組件庫能顯著提升界面開發(fā)效率與數(shù)據(jù)展示效果。Delphi 7是經(jīng)典的Windows可視化開發(fā)工具XE7則加入iOS/Android跨平臺支持該版本同時(shí)兼容兩者適用范圍廣。壓縮包為7z格式整體約190MB內(nèi)含主安裝程序以及附送的DEV漢化Demo便于中文用戶對照理解控件屬性和事件用法目前文件分類明細(xì)未額外提供但安裝后即可在IDE中集成使用。已有134人學(xué)習(xí)下載適合為老版本Delphi項(xiàng)目引入成熟控件體系或借助漢化示例快速上手的中高級開發(fā)者。該組件基于原生代碼實(shí)現(xiàn)運(yùn)行高效支持?jǐn)?shù)據(jù)綁定和多種預(yù)設(shè)主題可幫助開發(fā)者減少重復(fù)設(shè)計(jì)構(gòu)建外觀統(tǒng)一、交互流暢的專業(yè)應(yīng)用。1. 版本選型與適用場景分析1.1 為什么今天還要聊14.1.3說起DevExpress VCLDelphi圈子里應(yīng)該沒人陌生而14.1.3這個(gè)版本對不少老工程師來說既是一道坎也是一個(gè)寶。我手上維護(hù)的幾個(gè)老系統(tǒng)業(yè)務(wù)邏輯全跑在Delphi 7上界面卻年年要升級——工具欄要換膚、表格要有篩選、列表要支持拖拽客戶還總拿它跟各種新軟件比。DevExpress VCL 14.1.3就是在這種處境下被我反復(fù)選中的版本。它能在D7到XE7之間無縫銜接整個(gè)工程遷移過去不用重寫控件層這在組件界相當(dāng)難得。為什么不用更新的版本原因很直接DevExpress從15.x開始逐步收緊對老IDE的支持15.2雖然還能勉強(qiáng)裝進(jìn)D7但已經(jīng)出現(xiàn)設(shè)計(jì)器不穩(wěn)定、編譯出來的DCU體積異常等問題到16.x干脆正式移除了D7和2007的支持。所以只要是還堅(jiān)持留在D7的老項(xiàng)目14.1.3基本就是最合理的落點(diǎn)。它覆蓋Delphi 7、2005、2009、2010、XE、XE2、XE3、XE4、XE5、XE6、XE7整條產(chǎn)品線恰恰橫跨了從AnsiString到UnicodeString的完整過渡期這在選型時(shí)是個(gè)非常重要的加分項(xiàng)。1.2 D7到XE7的兼容矩陣不同IDE版本編譯出的DCU文件是互不兼容的DevExpress的做法是每個(gè)版本單獨(dú)出一套DCU和BPL。下面這張表是我實(shí)際整理過的兼容情況方便你判斷自己該用哪個(gè)安裝模式IDE版本字符串類型Win32/Win6414.1.3支持度建議DCU目錄Delphi 7AnsiStringWin32完整支持Sources\D7\Delphi 2007AnsiStringWin32完整支持Sources\D2007\Delphi 2009UnicodeStringWin32完整支持Sources\D2009\Delphi XE2UnicodeStringWin32/Win64完整支持Sources\DXE2\Delphi XE7UnicodeStringWin32/Win64完整支持Sources\DXE7\如果一臺機(jī)器上同時(shí)裝了D7和XE7安裝器會分別檢測并注冊各自的設(shè)計(jì)期包兩個(gè)IDE互不干擾。但要注意工程文件里的搜索路徑必須跟IDE版本一一對應(yīng)不能圖省事讓D7去用XE7的DCU否則編譯時(shí)報(bào)的“F2613 DCU版本不匹配”會讓你懷疑人生這一點(diǎn)在后面的排查章節(jié)我會專門展開。2. 安裝部署全流程2.1 安裝前的系統(tǒng)檢查裝DevExpress VCL之前一定先確認(rèn)三件事。第一把正在運(yùn)行的Delphi IDE全部關(guān)掉包括BDS、bds.exe的進(jìn)程設(shè)計(jì)期包注冊時(shí)要往IDE里寫注冊表IDE占用著文件會導(dǎo)致注冊失敗。第二殺毒軟件最好暫時(shí)退出或者至少把安裝目錄加入白名單14.1.3的安裝器會大量編譯生成BPL和DCU實(shí)時(shí)防護(hù)掃描會拖慢速度極端情況下還會誤刪未注冊的臨時(shí)文件。第三右鍵選擇“以管理員身份運(yùn)行”。安裝包本身建議從官網(wǎng)下載完整的離線安裝包體積通常在幾百M(fèi)B包含了所有子產(chǎn)品。如果你只需要其中的ExpressQuantumGrid和ExpressSkins安裝時(shí)選擇自定義組件即可不必全部安裝。我自己的經(jīng)驗(yàn)是先裝全家桶裝完再根據(jù)發(fā)布需求裁剪因?yàn)楹竺鎿Q膚、打印、報(bào)表說不定哪一天就用上了省得返工。2.2 安裝器自動(dòng)編譯與IDE注冊安裝器跑起來后會先解壓組件源碼到默認(rèn)目錄通常是C:\Program Files\DevExpress 14.1\VCL然后自動(dòng)檢測所有已安裝的Delphi版本并為每個(gè)版本編譯對應(yīng)的DCU、BPL再注冊到IDE里。整個(gè)安裝過程最長的是編譯環(huán)節(jié)十幾分鐘到半小時(shí)都正常期間不要切出去亂點(diǎn)。安裝完成后首次打開Delphi組件面板會多出ExpressQuantumGrid、ExpressBars、ExpressSkins、ExpressEditors等頁簽。如果打開IDE后組件面板沒有變化先別急著重裝檢查IDE的Component Install Packages列表里是否出現(xiàn)了DevExpress相關(guān)的設(shè)計(jì)期包。如果包已經(jīng)列出但控件沒顯示常見的坑是IDE緩存把%APPDATA%\Embarcadero\BDS\7.0\Closed Tools\或?qū)?yīng)版本目錄下的臨時(shí)文件清掉再重啟。安裝器在D7上的表現(xiàn)通常不如在新版XE系列上順滑因?yàn)镈7的注冊表項(xiàng)和路徑規(guī)則比較古老安裝器偶爾會漏寫Library路徑。這時(shí)不用慌用手工編譯的方式補(bǔ)上就行這正是老Delphi工程師的基本功。2.3 手工編譯的兜底方案安裝器失敗或者內(nèi)網(wǎng)環(huán)境無法用安裝器的場景我遇到過不止一次。兜底方案是手動(dòng)打開包文件編譯路徑在C:\Program Files\DevExpress 14.1\VCL\Sources\下每個(gè)子產(chǎn)品都有一個(gè)或多個(gè).dpk文件。打開一個(gè)工程組.dpg后逐個(gè)右鍵選擇Compile和Install。對于D7建議先編譯運(yùn)行時(shí)包再編譯設(shè)計(jì)期包。運(yùn)行時(shí)包的名字一般是cxLibrary.dpk、cxGrid.dpk、dxSkins.dpk這類設(shè)計(jì)期包以dcl開頭比如dclcxLibrary.dpk、dclcxGrid.dpk。編譯順序很重要先底層庫后高層控件否則會出現(xiàn)找不到cxClasses.dcu的錯(cuò)誤。手工編譯時(shí)還要確認(rèn)輸出目錄。在D7的Project Options Directories/Conditionals里把Package output directory指向一個(gè)統(tǒng)一的Bin目錄比如C:\DevExpress14\Bin然后把該目錄同時(shí)加入系統(tǒng)PATH。設(shè)計(jì)期包注冊成功后Delphi會提示“Package installed successfully”組件面板隨即刷新這一步走通后面就順暢多了。3. 工程集成與運(yùn)行時(shí)配置3.1 搜索路徑與DCU管理組件裝好只是第一步真正讓工程能編譯還得把DCU和源文件路徑配好。在D7中打開Tools Environment Options Library Library Path把DevExpress的Sources目錄加進(jìn)去。注意這里加的是Sources根目錄因?yàn)榻M件內(nèi)部有大量uses引用DevExpress把公共單元都放在Sources層按子目錄組織IDE在編譯時(shí)能自動(dòng)遞歸查找。我習(xí)慣把路徑按明確順序排列先寫Sources根目錄再寫Lib目錄避免多個(gè)版本源文件互相干擾。DCU的管理是另一個(gè)容易翻車的點(diǎn)。DevExpress 14.1.3安裝器會為每個(gè)IDE版本生成對應(yīng)的Lib\D7、Lib\DXE7這類目錄編譯輸出默認(rèn)也指向?qū)?yīng)分支。如果你手工編譯過一定要保證IDE搜索路徑里的DCU和當(dāng)前編譯器版本一致千萬別手滑把D7的DCU目錄放在了XE7工程前面否則一連串“Unit cxGrid was compiled with a different version of cxClasses”會徹底打斷你的節(jié)奏。強(qiáng)烈建議在每個(gè)IDE的Library Path里只保留當(dāng)前版本的輸出目錄并且把其他版本目錄從路徑中刪除。3.2 運(yùn)行時(shí)包的分發(fā)策略開發(fā)期用設(shè)計(jì)期包發(fā)布時(shí)則要決定用運(yùn)行時(shí)包還是靜態(tài)鏈接。運(yùn)行時(shí)包模式下exe體積小但客戶機(jī)器上必須安裝對應(yīng)的BPL和DLLDevExpress 14.1.3的運(yùn)行時(shí)包依賴關(guān)系比較復(fù)雜比如cxGrid依賴cxLibrarycxLibrary又依賴dxTheme。我踩過的坑是只拷貝了cxGrid的BPL結(jié)果客戶機(jī)器上一運(yùn)行就報(bào)“無法找到cxLibrary.bpl”。解決方法是寫一個(gè)小工具遍歷工程引用的BPL名稱然后把DevExpress Bin目錄下所有同名BPL一次性復(fù)制到程序目錄或系統(tǒng)目錄。如果不想管BPL也可以選擇靜態(tài)鏈接。在Project Options Packages中取消勾選“Build with runtime packages”編譯后所有控件代碼打進(jìn)exe體積增加十幾MB但部署簡單U盤拷走就能跑。對于老舊的D7項(xiàng)目我的經(jīng)驗(yàn)是盡量用靜態(tài)鏈接因?yàn)镈7程序在客戶那邊的運(yùn)行環(huán)境五花八門少一個(gè)外部依賴就少一個(gè)故障點(diǎn)。4. 客戶端事件與常用開發(fā)場景4.1 客戶端事件模型的理解搜索“DevExpress clientside event”經(jīng)常能看到這個(gè)詞但在VCL體系里它并不是Web開發(fā)中那種瀏覽器端事件而是指控件在應(yīng)用客戶端進(jìn)程內(nèi)觸發(fā)的事件處理機(jī)制。換句話說所有界面交互響應(yīng)都在用戶桌面端的程序里直接完成不需要請求服務(wù)器也不涉及網(wǎng)絡(luò)往返。對習(xí)慣了Web開發(fā)的人來說這個(gè)概念要注意區(qū)分別在Delphi里找什么“客戶端腳本”那是不存在的。真正重點(diǎn)掌握的是DevExpress控件的事件分類。以cxGrid為例最常用的是OnCellClick、OnCellDblClick、OnCustomDrawCell、OnCustomDrawColumnHeader以及Styles.OnGetContentStyle。這些事件的運(yùn)行機(jī)制和標(biāo)準(zhǔn)VCL事件類似但提供了更細(xì)粒度的機(jī)會比如在OnCustomDrawCell里你可以拿到ACanvas、AViewInfo直接畫底色、畫圖標(biāo)實(shí)現(xiàn)“條件高亮”這類在標(biāo)準(zhǔn)TDBGrid里要寫一堆代碼的效果。4.2 cxGrid實(shí)現(xiàn)條件高亮示例下面這段代碼是我項(xiàng)目里用了很久的條件高亮處理它會在數(shù)量小于安全庫存時(shí)把對應(yīng)行的單元格背景刷成淺紅色procedure TForm1.cxGrid1DBTableView1StylesGetContentStyle( Sender: TcxCustomGridTableView; ARecord: TcxCustomGridRecord; AItem: TcxCustomGridTableItem; out AStyle: TcxStyle); begin AStyle : nil; if ARecord nil then Exit; if AItem cxGrid1DBTableView1Qty then if ARecord.Values[cxGrid1DBTableView1Qty.Index] 10 then AStyle : cxStyleRed; // 在cxStyleRepository中預(yù)定義 end;這里的ARecord.Values[索引]是直接取單元格值無需訪問數(shù)據(jù)集效率比通過DataSet字段反查高得多。cxStyleRed可以預(yù)先放在cxStyleRepository里設(shè)好顏色和字體運(yùn)行后整行的內(nèi)容樣式都能統(tǒng)一應(yīng)用。這就是DevExpress相對標(biāo)準(zhǔn)控件的核心優(yōu)勢數(shù)據(jù)和表現(xiàn)分離事件鉤子多定制能力強(qiáng)。4.3 與老數(shù)據(jù)庫工程聯(lián)動(dòng)老工程最典型的形態(tài)是ADO連接SQLServer或Access窗體上放一個(gè)TADOTable加TDataSource再掛cxGrid。這個(gè)組合下DevExpress的DB-Aware模式依然好用把View的DataController.DataSource指向DataSource即可。一個(gè)容易忽略的點(diǎn)是當(dāng)TADOTable在D7下使用AnsiString時(shí)中文顯示容易亂碼而DevExpress已經(jīng)做了內(nèi)部Unicode轉(zhuǎn)換所以界面顯示反而比原生DBGrid更穩(wěn)定。數(shù)據(jù)刷新時(shí)建議使用cxGrid1DBTableView1.DataController.DataSource.DataSet.Refresh或者用DataController.Refresh不要直接調(diào)用GridView.Refresh后者在某些版本下會觸發(fā)設(shè)計(jì)期繪制異常。這個(gè)區(qū)別我是在一次現(xiàn)場演示時(shí)踩出來的客戶數(shù)據(jù)量大直接刷新界面閃白換成DataController刷之后就絲滑了。5. 踩坑實(shí)錄與問題排查5.1 安裝期問題速查我把這些年遇到的高頻問題整理成一張速查表方便大家直接對照報(bào)錯(cuò)或現(xiàn)象根本原因解決方案安裝器檢測不到Delphi 7注冊表IDE路徑損壞或安裝器權(quán)限不足手動(dòng)打開.dpk編譯或用管理員身份安裝組件面板無DevExpress頁簽設(shè)計(jì)期包未注冊或IDE緩存異常檢查Install Packages列表清理IDE緩存打開窗體報(bào)“Class TCxGrid not found”發(fā)布機(jī)或同事機(jī)器缺少設(shè)計(jì)期包重新安裝組件確保dcl開頭的包已注冊編譯報(bào)“無法找到cxClasses.dcu”Library Path未配置或配錯(cuò)版本目錄添加Sources根目錄核對IDE版本安裝期的問題大多數(shù)不是安裝包損壞而是路徑和權(quán)限。曾經(jīng)有一臺64位Windows Server上的D7安裝器一直無法把BPL寫到系統(tǒng)目錄后來發(fā)現(xiàn)是UAC把重定向到了虛擬存儲。解決辦法是把DevExpress Bin目錄單獨(dú)建在D盤并且給D7的快捷方式設(shè)置“以管理員身份運(yùn)行”。5.2 編譯期問題排查編譯期最讓人頭疼的是“Unit was compiled with a different version of”這類錯(cuò)誤。這個(gè)錯(cuò)誤的本質(zhì)是工程里混用了不同版本編譯出的DCU比如引用路徑中D7和XE7的DCU目錄同時(shí)存在或者舊的DCU沒有清理干凈。排查步驟可以按順序來先看Library Path里是否有多個(gè)DevExpress目錄再看工程文件里是否有絕對路徑指向舊的Lib目錄最后把整個(gè)工程里所有.dcu臨時(shí)文件刪掉重新編譯一次90%的問題能在這個(gè)環(huán)節(jié)解決。還有個(gè)隱蔽問題是在D7里用到了XPStyleManifest或者WinXP主題相關(guān)單元時(shí)如果順序不對會報(bào)F2048錯(cuò)誤。DevExpress的控件在主題支持上依賴uxtheme.dllD7下需要把Themes單元放在uses列表的最前面。老程序員通常寫成uses Windows, Messages, ...沒注意順序編譯就掛了。調(diào)整之后問題立消這個(gè)細(xì)節(jié)寫進(jìn)很多項(xiàng)目的注釋里新手往往不知道。5.3 運(yùn)行期問題記錄運(yùn)行期最經(jīng)典的問題有兩個(gè)。第一個(gè)是換膚后程序界面所有字體變小這是因?yàn)镋xpressSkins的默認(rèn)字體設(shè)置跟老工程不一致。解決方法是在程序啟動(dòng)時(shí)設(shè)置dxSkinsUserSkinPath并顯式指定GetCurrentSkin同時(shí)覆蓋每個(gè)窗體的Font.Name和Font.Size。第二個(gè)問題是網(wǎng)格在滾動(dòng)時(shí)閃爍老顯卡機(jī)器上特別明顯可以在cxGrid1DBTableView1.OptionsView里開啟OptimizedDraw性能提升立竿見影。另外提醒一句D7工程的字符串處理一定要謹(jǐn)慎。如果你在D7和XE7之間共享代碼event handler里用String(0)或直接操作PChar的地方都要標(biāo)注出來DevExpress 14.1.3完美兼容兩套字符串體系但這些邊界處理如果沒有做好在XE7下運(yùn)行時(shí)會悄悄產(chǎn)生亂碼等到客戶發(fā)現(xiàn)再來排查往往已經(jīng)過去很久。根據(jù)我個(gè)人經(jīng)驗(yàn)把這套14.1.3用順之后最值得投資的時(shí)間是仔細(xì)讀一遍cxGrid的事件說明。它值得不是安裝時(shí)看而是真正做業(yè)務(wù)時(shí)逐個(gè)驗(yàn)證明白了事件觸發(fā)順序和DataController的關(guān)系后面處理大數(shù)據(jù)量、排序、篩選、分組這些需求都會從容很多。最后再分享一個(gè)小技巧編譯發(fā)布版之前記得在Project Options Compiler里把Optimization打開老版本控件配合優(yōu)化開關(guān)在某些數(shù)據(jù)密集型界面上能有20%左右的性能提升這個(gè)收益幾乎白撿。本文還有配套的精品資源點(diǎn)擊獲取