Data delivery between programs with Delphi

xiaoxiao2021-03-06  42

Data delivery between programs with Delphi

In practical applications, we often need multiple programs to cooperate with each other to complete certain features. For example, synchronization, mutual exclusion between two applications; the application automatically passes the parameters when the application is in the second instance. To implement these features, you must implement data transfer between the program.

Some special advanced technologies can deliver data between different programs, such as clipboards, dynamic data exchange, and OLE automation, but have conditional restrictions and relatively complicated. Here, I introduced three effective underlying technology, I hope to help program enthusiasts.

Use WM_COPYDATA message

Using this message involves a pointer to a TcopyDataStruct structure type. There are three members in this structure:

DWDATA is a 32-bit additional parameter

CBData indicates the size of the data area to be transmitted

LPDATA indicates a pointer to the data area to be passed

Let's take an example. This example consists of two programs, which are SendData and GetData, respectively.

The SendData program sends a message to the getData program and transmits the string in Edit1; getData accepts the character string sent by SendData after receiving the message and displayed in the corresponding Edit1.

Senddata program:

VAR

FORM1: TFORM1;

IMPLEMENTATION

{$ R * .dfm}

Proceduretform1.button1click (sender: TOBJECT);

VAR

DS: tcopydatastruct;

HD: thandle;

Begin

Ds.cbdata: = Length (edit1.text) 1;

GetMem (DS.LPDATA, DS.CBDATA); // Assign memory for the transferred data area

Strcopy (DS.LPDATA, PCHAR (EDIT1.TEXT));

HD: = FindWindow (NIL, 'FORM2'); // Get the handle of the receiving window

IFHD <> 0Then SendMessage (HD, WM_COPYDATA, HANDLE,

Cardinal (@ds)) // Send WM_COPYDATA message

Else

SHOWMESSAGE ('"target window is not found!');

FreeMem (DS.LPDATA); // Release Resources

END;

GetData program:

TFORM2 = Class (TFORM)

EDIT1: TEDIT;

Private

{Privateeclarations}

public

ProcedureMyMessage (VART: TWMCopyData); MessageWM_CopyData;

{PublicDeclarations}

END;

VAR

Form2: TFORM2;

IMPLEMENTATION

Proceduretform2.mymessage (VART: TWMCOPYDATA);

Begin

Edit1.Text: = StrPas (T.copyDataStruct ^ .lpdata); // Accept data and display.

END;

Using this method is the easiest way to interact with Win32 applications.

Use the global atom

In the Win32 system, in order to achieve information sharing, the system maintains a global atomic table. Some shared data is stored in each atom. About the operation of the atom, there is a set of special API functions:

GlobalAddatom adds global atoms in the table

GlobalDeleTom deletes global atoms in the table

GlobalFindatom searches for global atoms in the table

GlobalGetAMname Gets the global atom from the table

The author uses this method to avoid programs secondary start, but transmit parameters of the second start-up belt to the first instance to perform corresponding processes. Basic processing is as follows:

In the project file:

Programpvdde;

Uses

Forms, shellapi, windows, dialogs, ddein'dde.pas' {form1}; {$ r * .res}

Begin

Ifglobalfindatom (Pchar ('PDDE_IS_Running')) = 0then

/ / Avoid secondary startup

Begin

K: = GlobalAddatom (Pchar ('PDDE_IS_RUNNING');

Application.INITIALIZE;

Application.createform (TFORM1, FORM1);

Application.run;

end

Else

Begin

/ / Parameter to the first instance when passing the second start

H: = FindWindow (Pchar ('TForm1'), PCHAR ('Data Confidential Prohibition of Outer Transmission ");

IFParamcount> 0Then

Begin

L: = GlobalAddatom (Pchar (Pramstr (1)));

IFH <> 0then

SendMessage (H, WM_MYMESSAGE, 0, L);

{Pass atom handle}

GLOBALDETEATOM (L); {Release after use}

END;

Application.Terminate;

END;

End.

Add the processing of custom messages WM_MYMESSAGE in the corresponding window unit Dde.PAS:

Proceduretform1.mymessage (VART: TMESSAGE);

{Processing WM_MYMESSAGE message}

VAR

P: array [0..255] OFCHAR;

Begin

GlobalGetaMname (T.LPARAM, P, 255); {Accept data to p array}

END;

Use storage image files

This approach is relatively complicated.

When Win95 with Winows

NT When loading a file in memory, a special global memory area is used. In this area, the application's virtual memory address and the corresponding position in the file correspond together. Since all processes share a global memory area for storing the image file, they can actually share their execution code in memory when the two processes are loaded with the same module (application or DLL file).

The author uses a CREATEFILEMAPPING function with special parameters to indirectly reach the purpose of sharing memory. The following is briefly explained.

HandlecreateFilemapping (Handlehfile, //) Handle

LPSecurity_attributeslpfilemappingAttributes, // Optional Security Properties

DWORDFLPROTECT, / / ​​Image file protection

DWordDwmaximumumsizeHigh, / / ​​The bottom value of the image file area

DWORDDWMAXIMUMSIZELOW, / / ​​The value of the image file area

LPCTSTRLPNAME / / The name of the image file);

If hfile is 0xfffffffff, you must specify dwmaximumsizehigh in the call program.

And the value of the dwmaximumsizelow parameter to determine the size of the image file. By specifying such parameters, the function creates a special logical image file supported by the operating system page file instead of a logical image file supported by the actual operating system. This logical image file can be shared by copying, inheriting, or by name. For a detailed description of other parameters, please see online help.

After the image file is created, we can access its memory by calling another API function MapViewOffile, which returns a specific pointer to the shared memory block.

LPVOIDMAPVIEWOFFILE

HandlehfilemappingObject, // Image File Handle

DWORDDWDESIREDACCESS, // Access method

DWordDWFileOffSethigh, / / ​​The bottom value of the image file area

DWORDDWFILEOFFSETLOW, // Image of the image of the image file DWORDDWNUMBEROFBYTOSTOMAP // Map Biostament

);

If dwnumberofbytestomap is 0, map the entire file.

The following example shows:

Private

Hmapfile: thandle;

MapFilePointer: Pointer;

public

{PublicDeclarations}

END;

VAR

FORM1: TFORM1;

IMPLEMENTATION

{$ R * .dfm}

Proceduretform1.formcreate (Sender: TOBJECT);

Begin

Hmapfile: = CreateFilemapping

$ Fffffff, // special memory map handle

NIL, Page_Readwrite, 0,10000, 'DDHDHDEMAPPEDFILE'); // File Name

IFHMAPFILE <> 0then

MapFilePointer: = MapViewoffile (HmapFile, / / ​​Handle of the Image File

FILE_MAP_ALL_ACCESS, 0, 0, 0) // Access the entire image file

Else

ShowMessage ('hmapfile = 0');

ifmapfilepointer = nilthen

ShowMessage ('MapFilePointer = nil');

END;

Proceduretform1.btnWriteClick (Sender: TOBJECT);

Begin

Stropy (pchapfilepointer),

Pchar (editwrite.text)); // write content to shared memory

END;

Proceduretform1.btnreadclick (sender: TOBJECT);

VAR

String;

Begin

S: = pchar (mapfilepointer); // read the content from the shared memory

EditRead.Text: = S;

END;

In this way, data can be shared between different programs, but also share data between different examples of the same program. In order to inform other changes in other process sharing data, you can customize a user message, and is implemented by sending a message, and details will not be described here.

转载请注明原文地址:https://www.9cbs.com/read-51387.html

New Post(0)