tblobstream

Project aaa.exe raised exception class EInvalidCast with message 'Invalid class typecast'. Process stopped. Use Step or Run to continue. This is the error message prompt by delphi or c++builder enviroment when debugging the program. This is always caused by the incorrect typecast.

Let us see an example attached by c++builder to show how to read the data from a memo field into a blob stream and display it in a memo control. To run this program, do not use a BDE data engine to connect to the database.

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    int MemSize;
    char *Buffer;
    TBlobStream *Stream;
    if (!Query1->Eof)
    Query1->Next();

    //Error message would raise on the following code line.
    Stream = new TBlobStream((TBlobField *)Query1->FieldByName("Notes"), bmRead);

    try
    {
        MemSize = Stream->Size + 1; // add one for null terminator
        Buffer = new char[MemSize]; // Allocate the memory.
        try
        {
            Stream->Read(Buffer, MemSize); //Read Notes field into buffer.
            Memo1->SetTextBuf(Buffer);  // Display the buffer's contents.
        }
        catch (...)
        {
            delete Buffer;
            throw;
        }
        delete Buffer;
    }
    catch (...)
    {
        delete Stream;
        throw;
    }
    delete Stream;
}

The error message mention above would raise on this line: Stream = new TBlobStream((TBlobField *)Query1->FieldByName("Notes"), bmRead);

When you use a BDE data engine to connect to the database, the error would not raised, because TBlobStream was designed to use for the BDE data engine. When we use an ADO or other data engine to connect to the database, we should use the proper component to access to the blob field.

If we use the ado, we should use a TADOBlobStream, while use the clientdataset, we should use a TClientBlobStream replace. For detail, see the article here.

Also, to avoid this error raise, we could use a common statement: "CreateBlobStream". This is the case: 
    TStream *Stream   =   ADOQuery1->CreateBlobStream((TBlobField *)Query1->FieldByName("Notes"),  bmReadWrite);

 

First, we assume you have a table with a blobfield named "image", then you could use the following codes to read or write the contents from or to the "image" field.

void __fastcall ReadBlobField()
{
    TBlobField* pField = (TBlobField*)pQuery->FieldByName("Image");  
    TBlobStream* pmem = new TBlobStream(pField, bmRead);  
    pmem->Seek(0, soFromBeginning);  
    Graphics::TBitmap* pBitmap = new Graphics::TBitmap();  
    pBitmap->LoadFromStream(pmem);  
    Image1->Picture->Assign(pBitmap);  
    delete pBitmap;  
    delete pmem;
}

void _fastcall WriteBlobField()
{
    pQuery->Edit();  //or pQuery->Insert() or pQuery->Append() ;
    TBlobField* pField = (TBlobField*)pQuery->FieldByName("Image");
    TBlobStream* pmem = new TBlobStream(pField, bmWrite);  
    pmem->Seek(0, soFromBeginning);  
    Graphics::TBitmap* pBitmap = new Graphics::TBitmap();  
    pBitmap->Assign(Image1->Picture->Graphic->Bitmap);  
    pBitmap->SaveToStream(pmem);  
    delete pBitmap;  
    delete pmem;  
    pQuery->Post();   
}

When you are using an ado connection, you should use the TADOBlobStream to access the database.

void __fastcall adoReadBlobField()

    TBlobField* pField = (TBlobField*)pQuery->FieldByName("Image");  
    TADOBlobStream* pmem = new TADOBlobStream(pField, bmRead);  
    pmem->Seek(0, soFromBeginning);  
    Graphics::TBitmap* pBitmap = new Graphics::TBitmap();  
    pBitmap->LoadFromStream(pmem);  
    Image1->Picture->Assign(pBitmap);  
    delete pBitmap;  
    delete pmem;   
}

void __fastcall adoWriteBlobField()
{
    pQuery->Edit();   //or pQuery->Insert() or pQuery->Append() ;
    TBlobField* pField = (TBlobField*)pQuery->FieldByName("Image");  
    TADOBlobStream* pmem = new TADOBlobStream(pField, bmWrite);  
    pmem->Seek(0, soFromBeginning);  
    Graphics::TBitmap* pBitmap = new Graphics::TBitmap();  
    pBitmap->Assign(Image1->Picture->Graphic->Bitmap);  
    pBitmap->SaveToStream(pmem);  
    delete pBitmap;  
    delete pmem;  
    pQuery->Post();
}

When you are using the TClientDataSet to connect to the database, you should use TClientBlobStream to access the database field.

void __fastcall clientReadBlobField()

    TBlobField* pField = (TBlobField*)pQuery->FieldByName("Image");   
    TClientBlobStream* pmem = new TClientBlobStream(pField, bmRead);  
    pmem->Seek(0, soFromBeginning);  
    Graphics::TBitmap* pBitmap = new Graphics::TBitmap();  
    pBitmap->LoadFromStream(pmem);  
    Image1->Picture->Assign(pBitmap);  
    delete pBitmap;  
    delete pmem;   
}

void __fastcall clientWriteBlobField()
{
    pQuery->Edit();   //or pQuery->Insert() or pQuery->Append() ;
    TBlobField* pField = (TBlobField*)pQuery->FieldByName("Image");   
    TClientBlobStream* pmem = new TClientBlobStream(pField, bmWrite);  
    pmem->Seek(0, soFromBeginning);  
    Graphics::TBitmap* pBitmap = new Graphics::TBitmap();  
    pBitmap->Assign(Image1->Picture->Graphic->Bitmap);  
    pBitmap->SaveToStream(pmem);  
    delete pBitmap;  
    delete pmem;  
    pQuery->Post();
}

Have a good luck! Well, you maybe have interesting in these articles:
How to use an ini file in C++Builder .
An example on how to use GetFormImage() and Assign() functions in C++Builder .
An example on using scanline to access bitmap pixels in C-Builder .
How to convert an icon to a bitmap in C++Builder .
Use the TWebBrowser as an html editor in delphi .
Draw a flowing line like photoshop selection tools .