Dynamic Link Library (DLLS) is developed from the concept of C language function libraries and the Pascal library unit. All C language standard library functions are stored in a function library, while users can also create their own libraries with the LIB program. During the link application, the linker is copied from the function code called in the library file and adds these function code to the executable. This method is more conducive to the code based on the function stored in the compiled .Obj file. However, with the emergence of multi-tasking environment such as Windows, the method of the library is too cumbersome. If the screen output, message processing, memory management, dialog, etc., each program has to have its own function, then the Windows program will become very large. Windows development requirements allow several programs that are running to share a single copy of a set of functions. The dynamic link library is in this case. Dynamic Link Library does not need to be compiled or linked, once loaded, the DLLS function can be used by any running application software in the system without having to load another copy of the DLLS function into memory. 10.1.1 Dynamic Link Library Working Principle "Dynamic Link" These words indicate how DLLs work. For conventional libraries, the linker copies all library functions they need and transmits the exact function address to the program called these functions. For DLLS, the function is stored in a separate dynamic link library file. When you create a Windows program, the link process does not link the DLLS file to the program. The program requires the address of this function until the function runs and calls a function in a DLLS. At this point, Windows looks for the called function in DLLS and transmits its address to the calling program. With this method, DLLS reaches the limit of multiplexing code. Another convenience of the dynamic link library is that the modifications of functions in the dynamic link library can be automatically propagated into all programs that call it without having to make any changes or processing. DLLs not only provides a function reuse mechanism, but also provides a mechanism for data sharing. Any application can share the memory resource block managed by the DLLS loaded in memory. DLLs containing only shared data are called resource files. Such as font files such as Windows, etc. 10.1.2 Dynamic Link Link Library of Windows Systems It is supported by a large number of dynamic link libraries. This includes Windows API functions (KRNLX86.EXE, USER.EXE, GDI.EXE, ...), various driver files, all kinds of font resource files with .fon and .fot extensions. Windows also provides dedicated DLLs for a certain feature, such as DDE programming DDEML.DLL, Ver.dll, etc. Although the DLLS must be involved when writing a Windows program, but use Delphi, users will not notice this at most. This aspect is because Delphi provides a rich function to enable users to use Windows API directly; on the other hand, even if the Windows API is used, because Delphi reorganizes the API function and other Windows DLLS functions, it is not necessary. Use special call formats. So this chapter focuses on writing and calling user-defined DLLs. Using a traditional Windows programming method to create and use a DLLS is a very headache, as the traditional Windows programming method itself is the same. Users need a series of modifications to define files, engineering files to accommodate the need to create and use DLLs. Delphi's emergence, in this respect, just as in many other respects, the burden of the developer is reduced. More exciting is that Delphi uses DLLS to realize the reuse mechanism of the form. Users can store their own forms in a DLLS and call it at any time when needed. 10.2 DLLS Writing and Call 10.2.1 DLLS Writing in the Delphi environment, writing a DLLS and writing a general application is not much different.
In fact, as a DLL function of the DLLS body, in addition to the management of memory and resources, there is no need for other special means. The real difference is on the project file. In most cases, the user is almost less than the existence of the project file, as it is generally not displayed on the screen. If you want to view the project file, you can open the View menu to select the Project Source item. At this point, the code of the project file will appear in the Code Editor (Code Editor) of the screen. The format of the general engineering document is: Program project title; USES clause; program body and DLLS engineering file format is: library project title; USES clause; exprots clause; program body, there are two points: 1. General The header of the project file with the Program keyword, while the DLLS project file header uses library keywords. Different keyword notification compilers generate different executables. Generating a .exe file with the Program keyword, and use the library keyword is .dll file; 2. If DLLS wants to output functions or procedures for other applications, these functions must be listed in Exports. In the sentence. These functions or process itself must compile with Export compilation instructions. According to the function completed by DLLS, we divide the DLLs three categories: 1. Complete the general function DLLS; 2. DLLS for data exchange; 3. DLLS for the form reuse. In this section, we only discuss DLLs that complete the general functions, and other content will be discussed in the two sections behind. 10.2.1.1 Steps to Write a general DLLS Write the steps of general DLLS as follows: 1. Use the Delphi's application template to create a DLLS program framework. For users of Delphi 1.0, because there is no DLLS template,: (1). Create a general application and open the project file; (2). Remove the form and the corresponding code unit; (3). In the project file In the middle, the Program is changed to library, remove the Forms in the USES clause, and add the appropriate library unit (generally sysutils, classes is required), and cut out all the code between the begin ... End. 2. Keep the file with the appropriate file name. At this time, the library will automatically modify the library name; 3. Enter the process, function code. If procedure, the function is prepared for other application calls, then adds Export compilation instructions after the process, the function head; 4. Create an Exports clause, including functions and process names for other application calls. You can use standard instructions Name, Index, Resident to facilitate calls for the process / function; 5. Enter the library initialization code. This step is optional; 6. Compiler, generate dynamic link library files. 10.2.1.2 Standards in Dynamic Link Library Indicates the output section of the dynamic link library for three standard instructions: Name, Index, Resident. 1.Name Name After connecting a string constant, as the output name of the process or function. Such as: exports instr name myinstr; other applications will call the process or function with a new name (Myinstr). If you still use the original name (INSTR), a system error is triggered when the program is executed. 2. Index INDEX indicates a sequence number as a process or function. If you do not use index instructions, the compiler is assigned in order. The scope of the number after INDEX is 1 ... 32767. Use Index to accelerate the calling process.
3.Resident uses resident, then the specific output information is always in memory when the DLLS is loaded. This allows for other applications to call the process, it can reduce time overhead than using the name of the DLL. For those processes or functions to be called for those other applications, using the Resident indication is appropriate. For example: Exports Instr Name Myinstr Resident; 10.2.1.3 Variables in DLLS and Segment A DLLS has its own data segment (DS), so any variables it declares are all private. The module that calls it cannot use the variable it defines directly. To use the process or function interface to complete. For DLLS, it will never have a chance to use variables declared in the module that calls it. A DLLS does not have its own stack (SS), which uses the stack of the application that calls it. Therefore, the process in the DLL, the function is absolutely not to assume DS = SS. Some languages have this assumption in small mode compilation, but this is to avoid this. Delphi will never produce code of DS = SS, and any runtime library process / function of Delphi does not make this assumption. It is to be noted that if the reader wants to embed the assembly language code, never log in to the same value for SS and DS. 10.2.1.4 Running time faults in DLLS Due to the operation of the DLLS can't control the operation of the application, it is difficult to perform an exception handling, so it is very careful when writing DLLs to ensure that it can be implemented normally when called. When a runtime error occurs in the DLLS, the corresponding DLLS does not necessarily move from memory (because other applications may be in use with it), and the program of the DLLS is abnormal. The problem caused by this is that when the DLLS has been modified, the memory remains may still be the previous version, and the modified program is not verified. For this problem, there are two solutions: 1. Explicit the DLL out of the memory in the program's exception handling part; 2. Fully exit Windows, then restart, run the corresponding program. Compared with the usual application, the processing of running time in DLL is difficult, and the consequences of the cause are more serious. Therefore, the programmer must be sufficient and thoughtful when writing code. 10.2.1.5 Writing of the Library Ethnified Code The writing of the dynamic link library in the traditional Windows, requires two standard functions: libmain and WEP for launching and closing the DLL. In libmain, the unlocking DLL data segment can be performed, allocate memory, initialization variables, etc., and WEP is called before the DLLS is removed from the memory, which is generally used to make the necessary cleanup work, such as release memory. Delphi implements the functionality of these two standard functions with its own unique way. This is the initialization code to the Begin ... End section in the project file. Compared to traditional Windows programming methods, its main feature is: 1. Initialization code is optional. Some necessary work (such as unlocking data segments) can be done automatically by the system. So most cases the user does not involve; 2. Multiple exit procedure can be set, and then call in sequence when exiting; 3.Libmain and WEP are transparent to the user, and the system is automatically called. The main task of initialization code is: 1. Initialization variables, allocate global memory blocks, login window objects, and the like initialization work. In the (10.3.2) section "Data Transfer between DLLS Realization Application", the global memory block for data sharing is allocated in the initialization code. 2. Set the execution process when DLLS exits. Delphi has a predefined variable EXITPROC to point to the address of the exit process. Users can assign their process names to Exitproc.
The system automatically invokes the WEP function, assigns the address pointing to the exitProc to the WEP execution until EXITPROC is NIL. A program below contains an exit process and a period of initialization code to explain how to properly set the exit process. {$ S-} Uses Wintypes, WinProcs; Var SaveExit: Pointer; ProcedureLibexit; FAR; Begin if EXITCODE = WEP_SYSTEM_EXIT THEN BEGIN {The corresponding process of the system is shut down} ELSE begin {DLL to remove the corresponding processing} End; EXITPROC: = SaveExit; {Restore the original exit process pointer} end; begin {DLL initialization work} saveexit: = exitproc; {Save the original exit process pointer} EXITPROC: = @libexit; {Install new exit process} End. In the initialization code, first save the original exit process pointer to a variable, and then assign the new exit process to EXITPROC. At the end of the custom exit process, the value of ExitProc recovers. Since EXITPROC is a system global variable, it is necessary to recover the original exit process at the end. The exit process libexit uses a system definition variable EXITCODE to log out the status. The value and significance of EXITCODE is as follows: Table 10.1 EXITCODE's value and meaning ━━━━━━━━━━ 取 取 意━━━━━━━ 取 - - --━━━━━━ - - ---------- ----------- WEP_SYSTEM_EXIT Windows Close WEP_FREE_DLLX DLLS is unloaded ━━━━━━━━ 退 退━━━━━━━━ 退 退 必须 必须 必须 必须 必须 必须 必须 必须 必须 必须 必须 必须 必须 必须 必须,,,,,, Set the compilation indication {$ S-}. 10.2.1.6 Application Writing General DLLS Example In the following program, we store a function of a string operation to a DLLS to call it when it is required. It should be noted that in order to ensure that this function can be called by the program written by other languages, the string passed as a parameter should be a character array type (ie, PCHAR type), not the end of Object Pascal. SRTING type. The list is as follows: library example; uses sysutils, classes; {Return characters in the string position} Function INSTR (SourceStr: PCHAR; CH: CHAR): Integer; Export; Var Len, i: integer; begin len: = Strlen (Fundstr); for i: = 0 to len-1 do if sourceStr [I] = ch dam result: = i; exit; end; result: = -1; end; exports instr index 1 name 'Myinstr' resident; Begin end. 10.2.2 Calling DLLs There are two ways to call a process stored in a DLLS. 1. Static calls or display the load uses an external statement clause to put the DLLS to be loaded before the application starts execution. For example: Function INSTR (SourceStr: Pchar; Check: char); Integer; Far; External 'UseStr'; Using this method, the program cannot determine the call of DLLs in the runtime. If a specific DLLS cannot be used at runtime, the application will not be executed.
2. Dynamic calls or implicit load Use the Windows API function loadLibray and getProcAddress to dynamically load DLLS in the runtime and call the process. If the program only calls the DLLS process, or which DLLS is used, which process is used to call it needs to be judged according to the actual status of the program, then the use of dynamic call is a good choice. Using dynamic calls, even if you load a DLLS fails, the program can continue to run. 10.2.3 Static call When you call a process or function in a DLLS in static call, External Indicates an addition to the declaration statement of the process or function. The called process or function must be used for a long modulation mode. This can be compiled using the FAR procedure or a {$ f }. Delphi supports three calls in traditional Windows dynamic link library programming, which are: ● By process / function name ● Through the alias of the process / function ● Call the alias from the process / function, give the user Programming provides flexibility, and the load speed of the corresponding DLL can be improved by sequence number (index) call. 10.2.4 Dynamic Call 10.2.4.1 There are three Windows API functions used in dynamic calls in dynamic calls, namely: LoadLibrary, GetProcaddress, and Freelibrary. 1.LoadLibrary: Missing the specified library module into the memory syntax as: function loadlibrary (libfilename: pchar): Thandle; libfilename Specifies the file name to load DLLS, if the libfilename does not contain a path, Windows looks in the order: (1) Current directory; (2) Windows directory (including win.com directory). Function getWindowdirectory returns the path to this directory; (3) Windows system directory (including system files such as gdi.exe directory). The function getSystemDirectory returns the path to this directory; (4) Contains a directory of the current task executable file. Using the function getModuleFileName can return the path of this directory; (5) Column (5) The directory of the PATH environment variable; (6) The image directory list of the network. If the function is successful, return the instance handle of the loader module. Otherwise, returns a less than the error code for Hinstance_ERROR. The meaning of the error code is as follows: Table 10.2 LoadLibrary The meaning of the error code is ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━ Error code meaning -------------------------------------- 0 system memory is not enough, Executing files are destroyed or calling illegal 2 files that are not found 3 paths that are not found 5 attempts to dynamic links A task or have a shared or network protection error 6 library requires the separation of separate data segments 8 without sufficient memory boot application Program 10 Windows version is incorrect 11 Executive file illegal. Or is not a Windows application, or in the .exe image, there is an error 12 application for a different operating system design (such as OS / 2 program) 13 application is MS DOS4.0 design 14 executable type of executable 15 Trying to load a real mode application (for early Windows version designs) 16 Attempt to load the executable of the executable of multiple data segments containing writable, try to load a compressed executable.
The file must be decompressed before it can be installed 20 dynamic link library file illegal 21 applications require 32-bit extension ━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━ 假 假 If the application is called with LoadLibrary to call a module, the other application has put the module into the memory, then LoadLibrary does not load another example of the module, but makes the module. "Quote count" plus 1. 2.GetProcadDress: Picking the address syntax of the function in a given module is: function getProcaddress (Module: thandle; procname: tfarProc; module contains the handle of the called function library module, which is returned by LoadLibrary. If you set the module to NIL, it means to reference the current module. ProcName is a pointer to a string that contains a function name with NIL, or may be the secondary value of a function. If the procName parameter is a secondary value, if the function of the order value does not exist in the module, GetProcAddress returns a non-NIL value. This will cause confusion. Therefore, in most cases the function name is a better choice. If you use a function name, the spelling of the function name must be consistent with the corresponding spelling in the dynamic link library file Exports section. If getProcAddress is successful, return the address at the entry in the module, otherwise returns NIL. 3.Freelibrary: From the middle of the memory module syntax as: Procedure Freelibrary; Module is the handle of the library module. This value is returned by LoadLibrary. Since the library module is only loaded in memory, the free Ibrary first reduces the reference number of the library module. If the reference count is reduced to 0, the module is removed. Each time the loadLibrary should call a freeLibray to ensure that there will be no excess library module remains in memory after the application is over. 10.2.4.2 Dynamic call example For dynamic calls, we got the following simple example. The system contains two edit boxes. Enter a string in the first editing box, then enter the character in the second editing box. If the character is included in the string of the first edit box, the label box displays information: "Located in the nth.", Otherwise the information: "Does not include this character.". As shown in the figure, the program's run interface. Figure 10.1 DLL Dynamic Calling Example Runput Input Check Features Implementation in Edit2's OnkeyPress event processing, the program list is as follows.
Procedure tform1.edit2keypress (Sender: Tobject; var); var order: integer; txt: pchar; pfunc: txt: pchar; pfunc: tfarproc; moudle: thandle; begin moudle: = loadingLibrary ('c: /dlls/example.dll'); If Moudle> 32 Then Begin Edit2.Text: = '; PFUNC: = GetProcaddress (Moudle,' Instr '); txt: = stralloc (80); txt: = Strpcopy (txt, edit1.text); Order: = Tinstr (PFUNC) (TXT, Key); if Order = -1 Then Label1.caption: = 'does not include this character' else label1.caption: = 'is located in' INTOSTR (ORDER 1) 'bit'; END; Freelibrary; END; Mandatory type conversion must be made when using the function pointer returned with getProcadDess: Order: = Tinstr (PFUNC) (TEXT, Key); Tinstr is a defined function type: TYPE TINSTR = Function Source: Pchar; Check: Char): Integer; 10.3 Using DLLS to implement data transfer 10.3.1 Global memory Windows in DLLs specifies: DLLs do not have any files it open or any global memory block therefor. These objects are owned by applications that are directly or indirectly call DLLs. Thus, when the application is aborted, the open file it has automatically turned off, and its global memory block is automatically released. This means that the files and global memory block variables stored in the DLLS global variable becomes illegal in the case where the DLLs are not notified. This will cause difficulties to other applications that use this DLLS. In order to avoid this, the file and global memory block handle should not be used as a global variable of DLLS, but is passed to the DLLS used as a parameter in the DLLS process or function. Calling DLLS applications should be responsible for their maintenance. However, in certain circumstances, DLLS can also have its own global memory block. These memory blocks must be assigned with GMEM_DDESHARE properties. Such a memory block is maintained until it is released by DLLS to release or DLLS exits. The global memory block managed by DLLS is another way to perform data transfer between applications. Here we will discuss this issue. 10.3.2 Using DLLS to implement data transmission between applications Using DLLS to implement data transmission between applications: 1. Write a DLLS program, which has a global memory block allocated with GMEM_DDESHARE attributes; 2. Server program call DLLS Write data to the global memory block; 3. The client program calls DLLs to read data from the global memory block. 10.3.2.1 Writing of DLLs for implementing data transmission For DLLs for implementing data transmission, the same is basically the same as general DLLs, in which the particular place is: 1. Define a global variable handle: var hmem: thandle; 2. Define one The process returns the handle of the global variable. This process is included in the Exports clause.
Such as: thandle; export; begin result: = HMEM; END; 3. Allocate global memory blocks in the initialization code: Program list is as follows: Begin Hmem: = GlobalLoc (GMEM_MOVEABLE AND GMEM_DDESHARE, NUM); if HMEM = 0 THEN Messagedlg ('Could Not Allocate Memory', MTWARNING, [Mbok], 0); End. NUM is a predefined constant. The Windows API function GLOBALLOC is used to allocate a memory from the global memory stack and return the handle of the memory block. This function includes two parameters, the first parameter is used to set the allocation flag of the memory block. The allocation marks that can be used are shown in the following table. Table 10.3 Global memory block allocation markers ━━━━━━━━━━━━━━━━━━━━━ 标 标 标 标━━━━━━ - - - 标 - ------- -------------------------- GMEM_DDESHARE assignment can be shared by the application Memory GMEM_DISCARDABLE assigns abandoned memory (only with GMEM_MOVEABLE) GMEM_FIXED Assign fixed memory GMEM_MOVEABLE Allocate Movable Memory GMEM_NOCompact This full stack cannot be compressed or discarded GMEM_NODISCARD This full stack cannot be discarded GMEM_NOT_BANKED assignment cannot be subjected to memory GMEM_NOTIFY notification function. When the memory is abandoned, call the GlobalNotify function GMEM_ZEROINIT to initialize the content of the allocated memory block to zero, ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━ There are two predefined common combinations: ghnd = GMEM_MOVEABLE AND GMEM_ZEROINIT GPTK = GMEM_FIXED AND GMEM_ZEROINIT second parameter to set the number of bytes to be assigned. The allocated byte must be a multiple of 32, so the actually allocated byte number may be larger than the set. Since the module allocated with GMEM_DDeshare is automatically abandoned when the module is terminated, it is not necessary to call GlobalFree Explicitly release memory. 10.3.2.2 Writing Server Programs of Server Programs must include call code to DLL, such as function getGlobalmem: thandle; far; external 'c: / dlls / glbmem'; the server can obtain the handle of the global memory block by calling the function. Before writing to the data, the server must lock global memory to avoid the location of Windows mobile the memory block during writing. Function GlobalLock locks global memory and returns a pointer to the memory block: PMEM: = Globalock (HMEM); any modifications to PMEM are reflected in the global memory block. After the memory block is operated, the GlobalUnlock is called to unlock. The memory block is subsequently unlocked as soon as possible, which is conducive to Windows to take full advantage of memory resources. The implementation code of the server write data is as follows.
Var HMEM: THANDLE; PMEM: PCHAR; Begin Hmem: = getGlobalMem; {Getting a global memory block handle} if hmem <> 0 THEN BEGIN PMEM: = Globalock (HMEM); {lock global memory block} if PMem <> nil THEN BEGIN STRPCOPY (PMEM, Memo1.Text); {Write data to the global memory block} GlobalUnlock (HMEM); {Unlock global memory block} Else Messagedlg ('COULDNOT LOCK MEMORY BLOCK', MTWARNING, [Mbok], 0) END; 10.3.2.3 Customer programming client is almost turned into the server program. The only difference is that one is write data and one is downloading data. Below is a list of procedures for customers from global memory blocks. Var HMEM: THANDLE; PMEM: PCHAR; Begin Hmem: = getGlobalMem; {Getting a global memory block handle} if hmem <> 0 THEN BEGIN PMEM: = Globalock (HMEM); {lock global memory block} if PMem <> nil THEN BEGIN MEMO1.TEXT: = STRPAS (PMEM); {read data from the global memory block} GlobalUnlock (HMEM); {Unlock global memory block} Else Messagedlg ('COULDNOT LOCK MEMORY BLOCK', MTWARNING, [Mbok], 0 ); END; server program and customer program simultaneous running screen displays as shown below. Figure 10.2 Screen display using DLLs to implement data transfer 10.4 Using DLLS implementation Windows Reuse Implementation Form Restaged is a leading feature in the Delphi DLLS function. When you create a universal form that makes yourself, you can use it in different applications, especially when you can use it in a non-Delphi application, it is most appropriate to make the form in a dynamic link library. This is also possible to call it using applications developed with other tools, such as C , Visual Basic, etc.. The DLLs containing the form has a component library (Component Library) overhead. This overhead can be minimized by compiling several forms into a DLLS. Different forms in the DLL can share parts libraries. 10.4.1 Using DLLS to implement Form Reuse Using DLLS to implement the form Reuse step: 1. In the Integrated Development Environment (IDE), you need to design a form according to your needs; 2. Write an export Function or process. In this function or process, the design of the design is instantiated; 3. Repeat steps 1, 2 until all reuse forms are completed; 4. Open the project file, modify it to accommodate the need to generate .dll file: (1). Set the reserved word Program to library; (2). Remove the Forms unit from the USES clause; (3). Remove all code between Begin, End; (4). Under the USES clause, Begin ... End block, add a reserved word exprots. After Exports is the output function name or process name. 5. Compilation Generate DLLS files; 6. Call reuse forms in other applications. The call to the reuse form is completely consistent with the usual DLLS function or process, and will not be described again. Readers can refer to the example below. 10.4.2 Form Reusal Example The following we describe the design process for the window body weight through a specific example. We store a password setting window and a password check window in a file called Passform.dll. Then, after a program written in a Delphi and a program written in a VB.
It turns out that this method is completely feasible. 10.4.2.1 Forms Reuse DLLS Design Forms Reuse DLLS Design in accordance with the steps described in (10.4.1). Two forms in DLLs are used to set and check the password, respectively. Their design interface is shown in the figure. Figure 10.3 Password Settings Window SetPasswordForm Design Interface Figure 10.4 Password Check Window GetPasswordForm Design Interface Forms TsetPasswordForm Defines two data members Verified and Password to record password confirmation status and setting passwords. TSetPassWordForm defined as follows: type TSetPassWordForm = class (TForm) Label1: TLabel; Edit1: TEdit; OKBtn: TBitBtn; CancelBtn: TBitBtn; procedure FormCreate (Sender: TObject); procedure Edit1KeyPress (Sender: TObject; var Key: Char); private {Private declarations} Verified: Boolean; public {public declarations} PassWord: PChar; end; time window generation of data members and member state initialization: procedure TSetPassWordForm.FormCreate (Sender: TObject); begin Verified: = False; PassWord: = Stralloc (40); okbtn.enabled: = false; label1.caption: = 'prom; button okbtn When the enabled property is set to false when the program is started until the password is set correctly after setting the enabled attribute to return to True. This ensures that only the password is set correctly, the password setting window can be turned off. Otherwise, only the CANCEL button will be canceled. A output function setPassword is defined in the password setting code unit, which is used to generate a password setting window and return a password: function setPassword (PCHAR): Boolean; var setpasswordform: tsetpasswordform; begin result: = false; setPasswordform: = tsetpasswordform .Create (Application); try with SetPasswordForm do if ShowModal = mrOK then begin StrCopy (PWord, StrUpper (password)); Result: = True; end; finally SetPasswordForm.Free; end; end; password is successfully set, the value of passWord Copy to the PWORD output and return true. It should be noted that because the PWORD itself is a pointer type, pointing to a string address, although PWORD is used to output, but is still a transmission parameter in the parameter table, not an in-range parameter. In addition, the function strPy is called, requiring PWORD to be allocated in front of incoming, otherwise a general protection is deflated. Try ... finally used to protect the memory resources to be used normally in any case, readers can refer to Chapter 12. In the password setting window, in order to ensure that the user remembers the set password, after the user inputs and press the Enter key, it is required to confirm again.
Only the user re-entered the string is the same as the original setting password, the password setting window can be turned off. Otherwise, the original setting password is emptied, requiring the user to enter again. The above function is implemented during the ONKEYPRESS event processing of the edit box. procedure TSetPassWordForm.Edit1KeyPress (Sender: TObject; var Key: Char); begin if Edit1.text = '' then Exit; if Key = # 13 then begin if Verified then if StrPas (PassWord) = Edit1.text then begin OKBtn.Enabled : = True; edit1.enabled: = false; okbtn.setfocus; end else begin verified: = false; messagedlg ('password is invalid.', Mtwarning, [mbok], 0); edit1.text: = '; Password : = ''; Label1.caption: = 'please input password: = true; strpcopy (password, edit1.text); edit1.text: ='; label1.caption: = 'please verify Password: '; end; key: = # 0; end; end; password check window is relatively simple, only one output function getPassword is used to generate the password check window and return the password check. function GetPassword (Password: PChar): Boolean; var GetPasswordForm: TGetPasswordForm; begin Result: = False; GetPasswordForm: = TGetPasswordForm.Create (Application); try with GetPasswordForm do if ShowModal = mrOK then if UpperCase (Edit1.Text) <> StrPas (Strupper (Password)) Then Messagedlg ('Invalid Password', MtWarning, [Mbok], 0) Else Res: = true; finally passwordform.free; end; end; password is the input parameter, can not be empty, by call or above The program is responsible for maintenance. In the window, the user input command is returned to the character in the screen, and the PasswordChar property of the edit box is determined. In the DLLS project file, write the two output functions into the Exports clause.
Library passform; uses getPass in 'getPass.pas' {passwordform}, setpass in 'setPass.pas' {setpasswordform}; exports getpassword, setpassword; begin end. 10.4.2.2 Delphi application call Reuse forms Call in Delphi applications Reuters, first, you must first include two output functions of Passform.dll: Function getPassword (Password: pchar): boolean; far; external 'C: / dlls / passform'; Function setPassword (Password: pchar): boolean; far; External 'C: / DLLS / Passform'; this is located in the IMPLEMentation section of the program unit. Then call the corresponding function in the process to implement the settings and inspections of the password. The interface after the program is running as shown. Figure 10.5 Delphi Application Call Reuse Form Run Interface Password Setting Site Implementation Code: Procedure TFORM1.SetButtonClick (Sender: TOBJECT); begin password: = stralloc (40); if setpassword (password) = false Then Messagedlg ('Password Is Not set ', Mtinformation, [Mbok], 0); END; first assigning memory for password string. When the password setting form is canceled by the CANCEL button, the corresponding information is displayed. The password check section is: Procedure TFORM1.TestButtonClick (Sender: TOBJECT); begin if password = NIL THEN BEGIN Messagedlg ('set password first', mtinformation, [mbok], 0); setButton.Setfocus; If getPassword (password) THEN Label1.caption: = 'YOU ARE Wellcome: =' sorry, you are invalid user. '; end; according to the result of the password check, the corresponding information is displayed in the tab box. 10.4.2.3 VB Application Call Reuse Form VB is a visual development tool recommended by Microsoft. Although it does not support the creation of dynamic link libraries, you can call standard Windows API dynamic link libraries and dynamic link libraries written in other languages. To verify the universality of the generated DLLS, we develop a simple program with VB to call the form stored in PassForm.dll. The running interface of the VB program is as shown in the figure, and the Delphi program (10.5) is basically consistent. Figure 10.6 VB Application Call Reusal Form Run Under the full code of the VB program, the corresponding part of the Delphi program is basically consistent.