Delphi 包的应用英文.docx
《Delphi 包的应用英文.docx》由会员分享,可在线阅读,更多相关《Delphi 包的应用英文.docx(15页珍藏版)》请在冰豆网上搜索。
Delphi包的应用英文
DynamicpackagesinDelphi -Morearticlesbythisauthor
Rating:
Ratings:
73 Rateit
Abstract:
ApaperonhowtocreateandusedynamicpackagesinDelphi.ByVinoRodrigues.
AnydiscussionofadvancedpackageuseinDelphimustraisethequestion:
Whyusepackagesatall?
Design-timepackagessimplifythetasksofdistributingandinstallingcustomcomponents.Runtimepackages,whichareoptional,offerseveraladvantagesoverconventionalprogramming.Bycompilingreusedcodeintoaruntimelibrary,youcanshareitamongapplications.Forexample,allofyourapplications--includingDelphiitself--canaccessstandardcomponentsthroughpackages.Sincetheapplicationsdon'thaveseparatecopiesofthecomponentlibraryboundintotheirexecutables,theexecutablesaremuchsmaller-savingbothsystemresourcesandharddiskstorage.Moreover,packagesallowfastercompilationbecauseonlycodeuniquetotheapplicationiscompiledwitheachbuild.
Packagesareevenbetterwhentheyareuseddynamically.Packagesofferamodularlibraryapproachtodevelopingapplications.Attimethosemodulesmaybecomeanoptionalentityofyourapplication.TakeforexampleanaccountingsystemwithanoptionalHRmodule.Forsomeinstallationsyouwillneedtoinstalljustthebaseapplication--forothersyouwillinstallboththebaseapplicationandtheHRmodule.Thislevelofmodularizationcanbeeasilyachievedbyjustincludingtheoptionalpackagetotheinstallbase.InthepastthiswasusuallyachievedwithdynamicallyloadedDLLs,butwithDelphi'spackagetechnologyitiseasytomakeyourmodularclassespartandparcelofyourapplication.Classescreatedfrompackagesbecomeapplication-ownedandthuscaninteractwithyourapplicationclasses.
Runtimepackagesandyourapplication
ManydevelopersthinkthatDelphipackagesareaplacetoputcomponent--butapackagecan(andshould)alsobeusedtomodularizeanapplication.
Toshowhowtousepackagestomodularizeyourapplicationwewillcreateanexample:
1.CreateanewDelphiapplicationwith2forms:
Form1andForm2.
2.RemoveForm2fromtheauto-createdformlistintheProject|Options|Formsmenudialog.
3.DropabuttononForm1andaddthefollowingcodetotheOnClickeventhandler:
4.withTForm2.Create(Application)do
5.begin
6.ShowModal;
7.Free;
end;
8.RemembertoaddUnit2toUnit1'susesclause.
9.Saveandruntheproject.
Wehavecreatedasimpleapplicationthatshowsaformwithabuttonthatshowsanotherformwhenitisclicked.
ButwhatifwewantedtocreateForm2inareusablemodule?
Theansweris--PACKAGES!
TocreateapackageforForm2wewill:
1.Opentheprojectmanager(View|ProjectManager)
2.Right-clickontheProjectGroupandselect"AddNewProject..."
3.Select"Package"fromthe"New"itemslist.
4.YoushouldnowseethePackageeditor.
5.Selectthe"Contains"itemandpressthe"Add"button.
6.Nowusethe"Browse..."buttontoselect"Unit2.pas."
7.Thepackageshouldnowcontaintheunit"Unit2.pas."
8.Nowsaveandcompilethepackage.
Thepackageisnowcomplete.Youshouldhaveafilecalled"package1.bpl"inyourProjectsBPLdirectory.(TheBPListheBorlandPackageLibrary;theDCPistheDelphiCompiledPackage--sortofliketheDCUofaPASfile.)
That'sallthatneedtobedonetothepackage.Wenowneedtocompiletheoriginalapplicationwiththepackageoptionswitchedon.
1.Selecttheproject"Project1.exe"fromtheProjectManagerbydouble-clickingonit.
2.Right-clickandselect"Options..."(YoucanalsoselectProject|Options...fromthemenu.
3.Selectthe"Packages"tab.
4.Checkthe"Buildwithruntimepackages"checkbox.
5.Edittheedit-boxinthe"Runtimepackages"sectiontoread:
"Vcl50;Package1"andOKtheoptions.
6.NOTE:
DonotremoveUnit2fromtheapplication.
7.Saveandruntheapplication.
Theapplicationwillrunandbehavejustlikebefore--thedifferencecanbeseeninthefilesize.Project1.exeisnowonly14Kasapposedtotheoriginal293K.IfyouusearesourceexplorertoviewthecontentsoftheEXEandtheBPLyouwillfindthatboththeDFMandthecodeforForm2nowresideinthepackage.
Delphiachievesthisbystaticallylinkinginthepackageatcompiletime.(That'swhyyoushouldn'tremovetheunitfromtheEXEproject.)
Justthinkofwhatcanbeachievedbydoingthis:
Onecouldcreatedatamodulesinpackagesandquicklymodifytheirsourceandonlydistributethenewpackagewhenourdata-accessruleshavechanged,likewhenwemovefromBDEbasedconnectivitytoADO.Or,wecouldcreateafromthatshow'sa"thisoptionisnotavailableinthisversion"messageinonepackage,andthenasimilarlynamedformthathasfunctionalityinasame-namedpackage.Wewillthenhavea"Pro"and"Enterprise"versionofourproductwithoutmucheffort.
Dynamicloadandunloadofpackages
StaticallylinkedDLLsandBPLsworkfineinmostcases,butwhatifwedecidenottodeploytheBPL?
Wewouldgeta"ThedynamiclinklibraryPackage1.bplcouldnotbefoundinthespecifiedpath..."errorandourapplicationwouldstopfunctioning.Orwhatif,inourmodularapplication,wewantedtohavenumerousplug-inlikemodules?
WeneedawaytodynamicallylinktotheBPLatruntime.
WithDLLsthisisasimpleprocessofusingtheLoadLibraryfunction.
functionLoadLibrary(
lpLibFileName:
PChar):
HMODULE;stdcall;
OncetheDLLisloadedwecancallexportedfunctionsandprocedureswithintheDLLbyusingtheGetProcAddressfunction.
functionGetProcAddress(hModule:
HMODULE;
lpProcName:
LPCSTR):
FARPROC;stdcall;
WefinallyunloadthedllbyusingtheFreeLibraryfunction.
functionFreeLibrary(hLibModule:
HMODULE):
BOOL;
stdcall;
InthisexamplewewilldynamicallyloadMicrosoft'sHtmlHelplibrary:
functionTForm1.ApplicationEvents1Help(
Command:
Word;Data:
Integer;
varCallHelp:
Boolean):
Boolean;
type
TFNHtmlHelpA=function(hwndCaller:
HWND;
pszFile:
PAnsiChar;uCommand:
UINT;
dwData:
DWORD):
HWND;stdcall;
var
HelpModule:
HModule;
HtmlHelp:
TFNHtmlHelpA;
begin
Result:
=False;
HelpModule:
=LoadLibrary('HHCTRL.OCX');
ifHelpModule<>0then
begin
@HtmlHelp:
=GetProcAddress(HelpModule,
'HtmlHelpA');
if@HtmlHelp<>nilthen
Result:
=HtmlHelp(Application.Handle,
PChar(Application.HelpFile),
Command,
Data)<>0;
FreeLibrary(HelpModule);
end;
CallHelp:
=False;
end;
DynamicallyloadedBPLs
BPLsarejustassimple.Wellalmost.
WedynamicallyloadthepackagebyusingtheLoadPackagefunction.
functionLoadPackage(constName:
string):
HMODULE;
WecreateTPersistentClassoftheclasswewishtoinstantiatebyusingtheGetClassfunction.
functionGetClass(constAClassName:
string):
TPersistentClass;
Instantiateanobjectoftheloadedclassanduseit.
Andwhenwearedone,unloadthepackageusingtheUnloadPackageprocedure.
procedureUnloadPackage(Module:
HMODULE);
Letusgobacktoourexampleandmakeafewchanges:
1.Select"Project1.exe"fromtheprojectmanager.
2.Right-clickandselect"Options..."
3.Selectthe"Packages"tab.
4.Remove"Package1"fromthe"Runtimepackages"edit-boxsectionandOKtheoptions.
5.OnDelphi'stoolbar,clickonthe"Removefilefromproject"button.
6.Select"Unit2|Form2"fromthelistandthen"OK."
7.Nowgotothe"Unit1.pas"sourceandremoveUnit2fromitsusesclause.(ThesestepsarerequiredtoremoveanylinktoUnit2andthepackagewewishtoloaddynamically.)
8.GotothesourceofButton1'sOnClickevent.
9.AddtwovariablesoftypeHModuleandTPersistentClass.
10.var
11.PackageModule:
HModule;
AClass:
TPersistentClass;
12.LoadthepackagePackage1byusingtheLoadPackagefunction.
PackageModule:
=LoadPackage('Package1.bpl');
13.CheckthatthePackageModuleisnot0(zero).
14.CreateapersistentclassusingtheGetClassfunction,passingitthenameoftheformwithinthepackageasitsparameter:
AClass:
=GetClass('TForm2');
15.Ifthepersistentclassisnotnil,createanduseaninstanceoftheclassjustabefore.
16.withTComponentClass(AClass).Create(Application)
17.asTCustomFormdo
18.begin
19.ShowModal;
20.Free;
end;
21.Finally,unloadthepackageusingtheUnloadPackageprocedure:
UnloadPackage(PackageModule);
22.Savetheproject.
HereisthecompletelistingoftheOnClickevent:
procedureTForm1.Button1Click(Sender:
TObject);
var
PackageModule:
HModule;
AClass:
TPersistentClass;
begin
PackageModule:
=LoadPackage('Package1.bpl');
ifPackageModule<>0then
begin
AClass:
=GetClass('TForm2');
ifAClass<>nilthen
withTComponentClass(AClass).Create(Application)
asTCustomFormdo
begin
ShowModal;
Free;
end;
UnloadPackage(PackageModule);
end;
end;
Unfortunatelythat'snottheendofit.
TheproblemisthattheGetClassfunctionrequirestheclasstoberegisteredbeforethefunctioncanfindit.Usuallyformclassesandcomponentclassesthatarereferencedinaformdeclaration(instancevariables)areautomaticallyregisteredwhentheformisloaded.Buttheformisn'tloadedyet.Sowhereshouldweregistertheclass?
Theanswer:
inthepackage.Eachunitinthepackageisinitializedwhenthepackageisloadedandfinalizedwhenthepackageisunloaded.
Let'sreturntoourexampleandmakeafewchanges:
1.Double-clickon"Package1.bpl"intheprojectmanager;thiswillactivatethepackageeditor.
2.Clickonthe+symbolnextto"Unit2"inthe"Contains"section.Thiswillexpandtheunittree.
3.Double-clickon"Unit2.pas"toactivatetheunit'ssourcecode.
4.Scrolldowntotheendofthefileandaddaninitializationsection.