A
aLeXanDer.. schrieb:
Erhalte ich die Fehlermeldungen das ich auf TPicture::Height nicht zugreifen darf, sowie das ich net auf __Fastcall TPicture::LoadFromStream nicht zugreifen darf
In puncto LoadFromStream habe ich mich geirrt; die Funktion kann ja nicht wissen, welchen Dateitypen sie zu laden versucht, daher geht das so nur über LoadFromFile.
Blobs dürften in der Lage sein, Daten aller Art zu speichern und nicht nur Bitmaps. Allerdings mußt du zugleich die Information vermerken, in welchem Dateiformat das Bild abgespeichert wurde. Unglücklicherweise ist die Liste der registrierten Graphikformate ein Implementationsdetail von Graphics.pas, und es existiert keine öffentliche Schnittstelle, um ein Format z.B. nach dem Klassennamen zu finden - TFileFormatsList.FindExt tut genau das, ist aber leider in der implementation-Sektion von Graphics.pas deklariert. Daher wird dir nicht viel mehr übrig bleiben, als sämtliche in Frage kommenden Graphikklassen manuell zu registrieren.
Das könnte z.B. so aussehen:
GraphicsSerializer.hpp:
#ifndef GraphicsSerializerHPP
#define GraphicsSerializerHPP
#include <Graphics.hpp>
void saveGraphicsToStream (TPicture* picture, TStream* stream);
void loadGraphicsFromStream (TPicture* picture, TStream* stream);
#endif // GraphicsSerializerHPP
GraphicsSerializer.cpp:
#include <Graphics.hpp>
#include <map>
#include <utility>
#include <stdexcept>
#pragma hdrstop
#include "GraphicsSerializer.hpp"
#pragma package(smart_init)
typedef TObject* (*createfunc_t) (void);
template <class T>
TObject* createObjectStatic (void)
{ return new T; }
struct classinfo_t
{
TMetaClass* metaclass;
createfunc_t createfunc;
classinfo_t (TMetaClass* _metaclass, createfunc_t _createfunc)
: metaclass (_metaclass)
{ createfunc = _createfunc; }
template <class T>
static classinfo_t get (void)
{ return classinfo_t (__classid (T), createObjectStatic <T>); }
};
template <typename T, unsigned I>
unsigned ArraySize (T(&)[I])
{ return I; }
// not thread-safe!
static std::map <String, classinfo_t*> graphicClasses;
static void registerGraphicClasses (void)
{
static classinfo_t classes[] = {
classinfo_t::get <Graphics::TBitmap> (),
classinfo_t::get <TIcon> (),
classinfo_t::get <TMetafile> (),
// insert more graphic classes here
};
for (classinfo_t* i = classes, * e = classes + ArraySize (classes);
i != e; ++i)
graphicClasses.insert (std::pair <String, classinfo_t*> (
i->metaclass->ClassName (), i));
}
#pragma startup registerGraphicClasses
void saveGraphicsToStream (TPicture* picture, TStream* stream)
{
String classname = picture->Graphic->ClassName ();
unsigned len = classname.Length ();
// write class name first
stream->Write (&len, sizeof (len));
stream->Write (classname.c_str (), len * sizeof (Char));
picture->Graphic->SaveToStream (stream);
}
void loadGraphicsFromStream (TPicture* picture, TStream* stream)
{
String classname;
unsigned len;
stream->Read (&len, sizeof (len));
classname.SetLength (len);
stream->Read (classname.c_str (), len * sizeof (Char));
std::map <String, classinfo_t*>::const_iterator i
= graphicClasses.find (classname);
if (i == graphicClasses.end ())
throw std::runtime_error (AnsiString ().Format (
"Graphic class '%s' not found", ARRAYOFCONST ((classname))).c_str ());
// use a dynamic_cast so that an exception is thrown if the object's
// type does not match
picture->Graphic = &dynamic_cast <TGraphic&> (*i->second->createfunc ());
picture->Graphic->LoadFromStream (stream);
}
main.cpp:
#include <vcl.h>
#include <tchar.h>
#include <memory>
#include <map>
#include <cstdio>
#pragma hdrstop
#include "GraphicsSerializer.hpp"
int _tmain (void)
{
std::auto_ptr <TPicture> picture (new TPicture);
std::auto_ptr <TStream> stream (new TMemoryStream);
// Create a bitmap object (which happens implicitly by accessing
// TPicture::Bitmap) and change its size.
picture->Bitmap->SetSize (256, 256);
// Save the bitmap into the stream.
saveGraphicsToStream (picture.get (), stream.get ());
// Remove the old TPicture object and create a new one.
picture.reset (new TPicture);
// Now load our graphic from the stream again.
stream->Position = 0;
loadGraphicsFromStream (picture.get (), stream.get ());
std::_putts (Format ("The class name is '%s'",
ARRAYOFCONST ((picture->Graphic->ClassName ()))).c_str ());
return 0;
}