Visit Gigasoft's Web Site
ProEssentials v8 Help

Chapter 5: Serialization

 

Serialization is the process of storing all the objects data in an efficient binary format. The ProEssentials API includes a variety of functions to implement serialization.

 

.NET Related Function

SaveObjectToFile

LoadObjectFromFile

SaveObjectToStream

LoadObjectFromStream

 

ActiveX and SDK/DLL Functions

PEsavetofile

PEloadfromfile

PEstore

PEload   

PEstorepartial

 PEloadpartial

 

The developer can utilize these functions to add chart persistence to their applications.

 

PEsavetofile and PEloadfromfile store and retrieve data from a file. Care must be taken to make sure that the correct object type (Graph, Scientific Graph, 3D Scientific Graph, Polar Object or Pie Chart Object) is used with PEloadfromfile as was used with PEsavetofile. Generally you will name files in a method which identifies which type of object is stored.

 

PEstore and PEload store and retrieve data from a global memory object. The Windows API function GlobalAlloc creates a global memory object. GlobalLock gives you a pointer to the data.

 

PEstorepartial and PEloadpartial function much the same way as PEstore and PEload except that they exclude the large data properties such as YData and XData. This is useful if you want to store the chart's characteristics without saving the chart's data.

 

The developer can use these functions to save an objects data to a file or into a Memo field of a database record. Another feature that could be implemented is an undo feature. Maintain the returned global handle from PEstore as long as the application is active. No need to deference it with GlobalLock, but use the handle with PEload in order to undo changes the user may have made.

 

 

Examples of using PEstore and PEload

 

Within .NET, these function are generally not needed as SaveObjectToStream provides similar functionality.

 

The following is example code which stores and reloads an objects data via serialization to a file. PEstorepartial and PEloadpartial work in an identical fashion. You can use this information if you need more control than what PEsavetofile and PEloadfromfile provides.

 

Examples are in C, VB, Delphi, and Builder.

 

C / C++ Example

The handle hWndPE points to a global variable specifying an object previously created.

 

void FAR*  lpdata;

DWORD  dwWritten;

OFSTRUCT MyOF;

HFILE   hFile;

HGLOBAL hGlobal = 0;

DWORD   dwSize = 0;

 

/* to store the data */

if (!PEstore (hWndPE, &hGlobal, &dwSize))

{ /* error handler */ }

 

/* hGlobal now contains a valid handle

and dwSize specifies the size stored.

Use GlobalLock to get a pointer to data

and then call GlobalUnlock when finished

with the pointer. */

 

lpdata = GlobalLock(hGlobal);

/* open file */

hFile = OpenFile("Test.dat", &MyOF, OF_CREATE|OF_READWRITE);

/* save size so we know how much to allocate later when loading */

dwWritten = hwrite(hFile, dwSize, 4);

/* save actual data */

dwWritten = hwrite(hFile, lpdata, dwSize);

lclose(hFile);

GlobalUnlock(hGlobal);

GlobalFree(hGlobal);

 

/* to later retrieve the data */

HGLOBAL hGlobal;

DWORD   dwSize;

void FAR*  lpdata;

DWORD  dwRead;

OFSTRUCT MyOF;

HFILE   hFile;

 

/* open file */

hFile = OpenFile("Test.dat", &MyOF, OF_READ);

/* read size to allocate correct amount */

dwRead = hread(hFile, dwSize, 4)

/* allocate memory */

hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwSize);

lpdata = GlobalLock(hGlobal);

/* read in actual data */

dwRead = hread(hFile, ByVal lpdata, dwSize);

GlobalUnlock(hGlobal);

lclose(hFile);

/* load data from global memory object */

PEload(hWndPE, hGlobal);

GlobalFree(hGlobal);

/* reinitialize to newly loaded data */

PEreinitialize (hWndPE);

PEresetimage (hWndPE, 0, 0);

 

 

Visual Basic Example

The PEstore function creates a global handle and Visual Basic has no simple means to deference the handle to manipulate the binary data. However, you can use these functions to store and load data to disk. Once in a file you could manipulate the binary data.

 

The following example shows how you can call the PEstore and PEload serialization functions in Visual Basic to save and load the object from a file.

 

PEGraph1 is a 32 bit OCX Graph Object placed into a form.

 

' to store data

Dim hGlobal As Long

Dim lpdata As Long

Dim dwSize As Long

Dim dwWritten As Long

Dim MyOF As OFstruct

Dim hFile As Long

Dim test As Long

 

hGlobal = 0

dwSize = 0

test = PEstore(PEGraph1, hGlobal, dwSize)

lpdata = GlobalLock(hGlobal)

 

'4098=CREATE+READWRITE, 0=READ, 1=WRITE

hFile = OpenFile("Test.dat", MyOF, 4098)

 

'save size so we know how much to allocate later

dwWritten = hwrite(hFile, dwSize, 4)

 

'save actual data

dwWritten = hwrite(hFile, ByVal lpdata, dwSize)

test = lclose(hFile)

test = GlobalFree(hGlobal)

 

 

' to later retrieve the data

Dim hGlobal As Long

Dim lpdata As Long

Dim dwSize As Long

Dim dwRead As Long

Dim MyOF As OFstruct

Dim hFile As Long

Dim test As Long

 

'open file, 0=READ, 1=WRITE, 2=READWRITE

hFile = OpenFile("Test.dat", MyOF, 0) '0=READ, 1=WRITE, 2=READWRITE

 

'read size to allocate correct amount

dwRead = hread(hFile, dwSize, 4) 'get size to allocate

 

'allocate memory

hGlobal = GlobalAlloc(2, dwSize)

lpdata = GlobalLock(hGlobal)

 

'read in actual data

dwRead = hread(hFile, ByVal lpdata, dwSize)

test = GlobalUnlock(hGlobal)

test = lclose(hFile)

 

'load data from global memory object

test = PEload(PEGraph1, hGlobal)

test = GlobalFree(hGlobal)

 

'reinitialize to newly loaded data

PEGraph1.PEactions = 0 'reinitialize after PEload

 

 

Delphi Example

The following example shows how you can call the PEstore and PEload serialization functions in Delphi to save and load the object from a file.

 

PEGraph1 is a VCL Graph Object placed into a form.

 

{-----------------------------------------------------

DECLARATIONS NEEDED

Add Pegrpapi unit to your uses clause. This unit holds declarations.

 

FUNCTION TO SAVE OBJECT TO DISK

------------------------------------------------------}

 

procedure TForm1.Button1Click(Sender: TObject);

var

hGlobal: Longint;

lpdata: Pointer;

dwSize: Longint;

dwWritten: Longint;

MyOF: TOFStruct;

hFile: Longint;

begin

hGlobal := 0;

dwSize := 0;

if (PEstore(PEGraph1.hObject, @hGlobal, @dwSize) <> 0) then

begin

lpdata := GlobalLock(hGlobal);

hFile := OpenFile('c:\Test.dat', MyOF, OF_CREATE+OF_READWRITE);

dwWritten := _hwrite(hFile, @dwSize, 4);

dwWritten := _hwrite(hFile, lpdata, dwSize);

_lclose(hFile);

GlobalUnlock(hGlobal);

GlobalFree(hGlobal);

end;

end;

 

 

{-------------------------------------------------------

FUNCTION TO LOAD OBJECT FROM DISK

-------------------------------------------------------}

procedure TForm1.Button2Click(Sender: TObject);

var

hGlobal: Longint;

lpdata: Pointer;

dwSize: Longint;

dwRead: Longint;

MyOF: TOFStruct;

hFile: Longint;

begin

hFile := OpenFile('c:\Test.dat', MyOF, 0);

dwRead := _lread(hFile, @dwSize, 4);

hGlobal := GlobalAlloc(GMEM_MOVEABLE, dwSize);

lpdata := GlobalLock(hGlobal);

dwRead := _lread(hFile, lpdata, dwSize);

GlobalUnlock(hGlobal);

_lclose(hFile);

PEload(PEGraph1.hObject, @hGlobal);

GlobalFree(hGlobal);

PEGraph1.PEactions := gReinitAndReset;

end;

 

 

 

Builder Example

The following example shows how you can call the PEstore and PEload serialization functions in Builder to save and load the object from a file.

 

PESGraph1 is a VCL Graph Object placed into a form.

This examples uses both Windows file handling and TFileStream.

 

 

//-----------------------------------------------------------

void __fastcall TForm3::Button1Click(TObject *Sender)

{

 

// ** Saving to Disk ** //

 

HGLOBAL hGlobal;

LPVOID lpdata;

unsigned long dwSize;

unsigned long dwWritten;

OFSTRUCT MyOF;

HANDLE hFile;

 

hGlobal = 0;

dwSize = 0;

 

PEstore((HWND) PESGraph1->hObject, &hGlobal, &dwSize);

lpdata = GlobalLock(hGlobal);

 

TFileStream* tfs;

tfs = new TFileStream("c:\\test.dat", fmCreate);

tfs->WriteBuffer(&dwSize, 4);

tfs->WriteBuffer(lpdata, dwSize);

delete tfs;

 

// The following code does the same as above but without

// the use of TFileStream.

/*

// '4098=CREATE+READWRITE, 0=READ, 1=WRITE

hFile = (HANDLE) OpenFile("c:\Test.dat", &MyOF, 4098);

 

// 'save size so we know how much to allocate later

WriteFile(hFile, &dwSize, 4, &dwWritten, NULL);

 

// 'save actual data

WriteFile(hFile, lpdata, dwSize, &dwWritten, NULL);

 

_lclose((HFILE)hFile);

*/

 

GlobalFree(hGlobal);

}

 

 

//-----------------------------------------------------------

void __fastcall TForm3::Button2Click(TObject *Sender)

{

 

// ** Loading From Disk ** //

 

HGLOBAL hGlobal;

LPVOID lpdata;

unsigned long dwSize;

unsigned long dwRead;

OFSTRUCT MyOF;

HANDLE hFile;

 

hGlobal = 0;

dwSize = 0;

 

TFileStream* tfs;

tfs = new TFileStream("c:\\test.dat", fmOpenRead);

tfs->ReadBuffer(&dwSize, 4);

 

// ** If not using TFileStream

// ** 0=READ, 1=WRITE, 2=READWRITE

//hFile = (HANDLE) OpenFile("c:\Test.dat", &MyOF, 0);

// ** read size to allocate correct amount

//ReadFile(hFile, &dwSize, 4, &dwRead, NULL);

 

hGlobal = GlobalAlloc(2, dwSize);

lpdata = GlobalLock(hGlobal);

 

tfs->ReadBuffer(lpdata, dwSize);

 

// ** If not using TFileStream, read in actual data

//ReadFile(hFile, lpdata, dwSize, &dwRead, NULL);

 

GlobalUnlock(hGlobal);

delete tfs;

 

// ** If not using TFileStream

//_lclose((HFILE)hFile);

 

PEload((HWND) PESGraph1->hObject, &hGlobal);

GlobalFree(hGlobal);

 

// ** reinitialize after PEload

PESGraph1->PEactions = sgReinitAndReset;

}