国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Home 類(lèi)庫(kù)下載 Other libraries Why use dynamic packages in Delphi

Why use dynamic packages in Delphi

Nov 21, 2016 am 11:34 AM
delphi

Why use bags?

The answer is simple: because of the powerful functions of the package. Design-time packages simplify the release and installation of custom components; run-time packages inject fresh power into traditional programming. Once you compile reusable code into a runtime library, you can share it among multiple applications. All applications can access standard components through packages, which is how Delphi itself does it. Because the application does not have to copy a separate component library in the executable file, this greatly saves system resources and disk space. Additionally, packages reduce the time spent on compilation because you only need to compile application-specific code.

If the package can be used dynamically, then we can get more benefits. Packages provide a novel modular approach to developing applications. Sometimes you may want to make certain modules optional components of the application, such as an accounting system that comes with an optional HR module. In some cases, you only need to install the basic application, while in other cases you may need to install additional HR modules. This modular approach can be easily implemented through package technology. In the past, this could only be achieved by dynamically loading a DLL, but using Delphi's packaging technology, you can "package" each module type of the application into bundles. In particular, class objects created from packages are owned by the application and can therefore interact with objects in the application.

Runtime Packages and Applications

Many developers only think of Delphi packages as a place to put components. In fact, packages can (and should) be used in modular application design.

To demonstrate how to use packages to modularize your application, we create an example:

1. Create a new Delphi program with two forms: Form1 and Form2;

2. Automatically create a form from Form2 Remove from the list (Project | Options | Forms);

3. Place a button on Form1, and enter the following code in the button's OnClick event handler:

with TForm2.Create(Application) do
begin
ShowModal;
Free;
End;

4. Remember to add Unit2 to the uses child of Unit1 In the sentence;

5. Save and run the project.

We created a simple application that displays a form with a button. Clicking this button will create and display another form.

But if we want to include Form2 in the above example into a reusable module and make it still work normally, what should we do?

The answer is: Bao!

To create a package for Form2, the following work is required:

1. Open the Project Manager (View | Project Manager);

2. Right-click the Project Group and select "Add NewProject...";

3. In " New" project list, select "Package";

4. Now you should be able to see the package editor;

5. Select the "Contains" project, and then click the "Add" button;

6. Then click "Browse. .." button and select "Unit2.pas";

7. The package should now contain the "Unit2.pas" unit;

8. Finally save and compile the package.

Now we have completed the package. There should be a file named "package1.bpl" in your ProjectBPL directory. (BPL is the abbreviation of Borland Package Library, and DCP is the abbreviation of Delphi CompiledPackage.)

This package has been completed. Now we need to turn on the package options

and recompile the original application.

1. Double-click "Project1.exe" in the project manager to select the project;

2. Right-click and select "Options..." (you can also select Project | Options... from the menu);

3. Select the "Packages" option page;

4. Select the "Build with runtime packages" check box;

5. Edit the "Runtime packages" edit box: "Vcl50;Package1", and click the "OK" button;

6. Note: Do not remove Unit2 from the application;

7. Save and run the application.

The application will run as before, but the difference can be seen in the file size.

Project1.exe is now only 14K in size, compared with 293K before. If you use the Resource Browser to view the contents of the EXE and BPL files, you will see that the Form2 DFM and code are now saved in the package.

Delphi completes static linking of packages during compilation. (This is why you can't remove Unit2 from the EXE project.)

Think about what you can gain from this: you can create a data access module in the package, and when changing the data access rules (such as switching from BDE connection for ADO connections), modify it slightly and republish this package. Alternatively, you could create a form in one package that displays the message "This option is not available in the current version" and then create a fully functional form in another package with the same name. Now we have the product in “Pro” and “Enterprise” versions without any effort.

Dynamic loading and unloading of packages

在大多數(shù)情況下,靜態(tài)連接的DLL或BPL已經(jīng)可以滿(mǎn)足要求了。但是如果我們不想發(fā)布BPL呢? “在指定目錄中找不到動(dòng)態(tài)鏈接庫(kù)Package1.bpl”,這是在應(yīng)用程序終止前,我們所能得到 的唯一消息?;蛘撸谀K化應(yīng)用程序程序中,我們是否可以使用任意數(shù)量的插件?

我們需要在運(yùn)行期動(dòng)態(tài)連接到BPL。

對(duì)于DLL 來(lái)說(shuō),有一個(gè)簡(jiǎn)單的方法,就是使用LoadLibrary函數(shù):

function LoadLibrary(lpLibFileName: Pchar): HMODULE;stdcall;

裝載了DLL之后,我們可以使用GetProcAddress函數(shù)來(lái)調(diào)用DLL的導(dǎo)出函 數(shù)和方法:

function GetProcAddress(hModule: HMODULE; lpProcName:LPCSTR): FARPROC; stdcall;

最后,我們使用FreeLibrary卸載DLL:

function FreeLibrary(hLibModule: HMODULE): BOOL;stdcall;

下面這個(gè)例子中我們動(dòng)態(tài)裝載Microsoft的HtmlHelp庫(kù):

function TForm1.ApplicationEvents1Help(Command: Word; Data: Integer; var CallHelp: 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');
if HelpModule <> 0 then
begin
@HtmlHelp := GetProcAddress(HelpModule, &#39;HtmlHelpA&#39;);
if @HtmlHelp <> nil then
Result := HtmlHelp(Application.Handle,Pchar(Application.HelpFile), Command,Data) <> 0;
FreeLibrary(HelpModule);
end;
CallHelp := False;
end;

動(dòng)態(tài)裝載BPL

我們可以用同樣簡(jiǎn)單的方法來(lái)對(duì)付BPL,或者應(yīng)該說(shuō)基本上同 樣簡(jiǎn)單。

我們可以使用LoadPackage函數(shù)動(dòng)態(tài)裝載包:

function LoadPackage(const Name: string): HMODULE;

然后使用GetClass 函數(shù)創(chuàng)建一個(gè)TPersistentClass類(lèi)型對(duì)象:

function GetClass(const AclassName: string):TPersistentClass;

完成所有操作后,使用UnLoadPackage(Module:HModule);

讓我們對(duì)原來(lái)的代碼作一些小小的改動(dòng):

1、 在工程管理器中選中“Project1.exe”;

2、 右擊之并選擇“Options...”;

3、 選中“Packages”選項(xiàng)頁(yè);

4 、 從“Runtime packages”編輯框中移除“Package1”,并點(diǎn)擊OK按鈕;

5、 在Delphi的工具欄中,點(diǎn)擊“Remove file from project”按鈕;

6、 選擇“Unit2 | Form2”,并點(diǎn)擊OK;

7、 現(xiàn)在在“Unit1.pas”的源代碼中,從uses子句中移除Unit2;

8、 進(jìn)入Button1 的OnClick時(shí)間代碼中;

9、 添加兩個(gè)HModule和TPersistentClass類(lèi)型的變量:

var

PackageModule: HModule;

AClass: TPersistentClass;

10、使用LoadPackage 函數(shù)裝載Pacakge1包:

PackageModule := LoadPackage('Package1.bpl');

11、檢查PackageModule是否為0;

12、使用GetClass函數(shù)創(chuàng)建一個(gè)持久類(lèi)型:

AClass := GetClass('TForm2');

13、如果這個(gè)持久類(lèi)型不為nil,我們就可以向從前

一樣創(chuàng)建并使用該類(lèi)型的對(duì)象了:

with TComponentClass(AClass).Create(Application) as TcustomForm do
begin
ShowModal;
Free;
end;

14、最后,使用UnloadPackage 過(guò)程卸載包:

UnloadPackage(PackageModule);

15、保存工程。

下面是OnClick事件處理器的完整清單:

procedure TForm1.Button1Click(Sender: Tobject);
var
PackageModule: HModule;
AClass: TPersistentClass;
begin
PackageModule := LoadPackage(&#39;Package1.bpl&#39;);
if PackageModule <> 0 then
begin
AClass := GetClass(&#39;TForm2&#39;);
if AClass <> nil then
with TComponentClass(AClass).Create(Application) as TcustomForm do
begin
ShowModal;
Free;
end;
UnloadPackage(PackageModule);
end;
end;

不幸的是,并不是這樣就萬(wàn)事大吉了。

問(wèn)題在于,GetClass函數(shù)只能搜索到已經(jīng)注冊(cè)的類(lèi)型。 通常在窗體中引用的窗體類(lèi)和組件類(lèi)會(huì)在窗體裝載時(shí)自動(dòng)注冊(cè)。但是在我們的例子中,窗體無(wú)法提前裝載。那么我們?cè)谀睦镒?cè)類(lèi)型呢?答案是,在包中。包中的每 個(gè)單元都會(huì)在包裝載的時(shí)候初始化,并在包卸載時(shí)清理。

現(xiàn)在回到我們的例子中:

1、 在工程管理器雙擊“Package1.bpl”;

2、 點(diǎn)擊“Contains”部分“Unit2”旁的+號(hào);

3、 雙擊“Unit2.pas”激活單元源代碼編輯器;

4、 在文件的最后加入initialization部分;

5、 使用RegisterClass過(guò)程注冊(cè)窗體的類(lèi)型:

RegisterClass(TForm2);

6、 添加一個(gè)finalization部分;

7、 使用UnRegisterClass過(guò)程反注冊(cè)窗體的類(lèi) 型:

UnRegisterClass(TForm2);

8、 最后,保存并編譯包。

現(xiàn)在我們可以安全的運(yùn)行“Project1”,它還會(huì)像從前 一樣工作,但是現(xiàn)在你可以隨心所欲的裝載包了。

尾聲

記住,無(wú)論你是靜態(tài)還是動(dòng)態(tài)的使用包,都要打開(kāi)Project | Options | Packages | Build with runtime packages 選項(xiàng)。

在你卸載一個(gè)包之前,記得銷(xiāo)毀所有該包中的類(lèi)對(duì)象,并反注冊(cè)所有已注冊(cè)的類(lèi)。下面的過(guò)程可能會(huì)對(duì)你有所幫助:

procedure DoUnloadPackage(Module: HModule);
var
i: Integer;
M: TMemoryBasicInformation;
begin
for i := Application.ComponentCount - 1 downto 0 do
begin
VirtualQuery(GetClass(Application.Components[i].ClassName), M, Sizeof(M));
if (Module = 0) or (HMODULE(M.AllocationBase) = Module) then
Application.Components[i].Free;
end;
UnregisterModuleClasses(Module);
UnloadPackage(Module);
end;

在裝載包之前,應(yīng)用程序需要知道所有已注冊(cè)類(lèi)的名字。改善這一情況的方法是建立一個(gè)注冊(cè)機(jī)制,以便告訴應(yīng)用程序所有 由包注冊(cè)的類(lèi)的名字。

實(shí)例

多重包:包不支持循環(huán)引用。也就是說(shuō),一個(gè)單元不能引用一個(gè)已經(jīng)引用了該單元的單元(嘿嘿)。這使得調(diào)用窗體中的某 些值難以由被調(diào)用的方法設(shè)置。

解決這個(gè)問(wèn)題的方法是,創(chuàng)建一些額外的包,這些包同時(shí)由調(diào)用對(duì)象和包中的對(duì)象引用。設(shè)想一下我們?nèi)绾问笰pplication成為所有窗體的擁有者?變量Application創(chuàng) 建于Forms.pas 中,并包含在VCL50.bpl包 中。你大概注意到了你的應(yīng)用程序既要將VCL50.pas編譯進(jìn)來(lái),也同時(shí)你的包也需要(require) VCL50。

In our third example, we design an application to display customer information and customer orders (dynamically) on demand.

So where can we start? Like all database applications

programs, we need to connect. We create a main data module containing a TDataBase connection. Then we encapsulate this data module in a package (cst_main).

Now in the application, we create a customer form and reference DataModuleMain (we statically link VCL50 and cst_main).

Then we create a new package (cst_ordr), which contains the customer order form, and require cst_main. Now we can dynamically load cst_ordr in the application. Since the main data module already exists before dynamic packaging is loaded, cst_ordr can directly use the application's main data module instance.

The picture above is a functional diagram of this application:

Interchangeable Package: Another application example of packages is the creation of interchangeable packages. Implementing this functionality does not require the dynamic loading capabilities of the package. Suppose we want to release a time-limited trial version of a program. How do we achieve this?

First we create a "Splash" form, usually a picture with the word "Trial", and display it during the application startup process. Then we create an "About" form to provide some information about the application. Finally, we create a function that tests whether the software is out of date. We encapsulate these two forms and this function into a package and release it with the trial version of the software.

For the paid version of the software, we also create a "Splash" form and an "About" form - with the same class names as the previous two forms - and a test function (does nothing), and Encapsulate them into a package with the same name.

What what? Is this useful, you ask? Well, we can release a trial version of the software to the public. If a customer purchases the app, we only need to send the non-trial package. This greatly simplifies the software release process, as only one installation and one registration package upgrade are required. The

package opens another door to modular design for the Delphi and C++ Builder development communities. With packages you no longer need to pass window handles around, no more callback functions, no more other DLL technology. This also shortens the development cycle of modular programming. All we have to do is let Delphi's packages work for us.


Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

PHP Tutorial
1502
276