Work with linked images to manage 1000 [C++Builder demo]

    • Offizieller Beitrag

    WPTools can handle very many images in one document - but only if not all are loaded at the same time.

    So it is required to load the images only when they are needed. They should be removed from memory when they are not used anymore. We suggest to create an image cache which frees the images depending on the time of there last use.

    To link in such an image a TWPTextObj should be created. The property Source is ideal to store the name of the image. When the file is loaded or saved the names will be stored, too. Other RTF reader will not be able to 'see' an image - so we will also deal with exporting compatible RTF format.

    This code in used to insert an image:

    Code
    void __fastcall TForm1::InsertClick(TObject *Sender){     TWPTextObj *obj = WPRichText1->TextObjects->InsertNewObject(wpobjImage);     obj->Source = "LOGO";     obj->Width  = 1000;     obj->Height = 1000;    WPRichText1->InputString("\r",0); // new paragraph    WPRichText1->DelayedReformat();}

    To display the object we use an event handler for the event OnTextObjectPaint. Othwise just a red box would be displayed.

    In this example we simply use a TImage a source for the image data.

    Code
    void __fastcall TForm1::WPRichText1TextObjectPaint(TObject *Sender,      TWPTextObj *pobj, TCanvas *toCanvas, int XRes, int YRes, int X,      int Y, int W, int H, int BASE, TWPVirtPage *PageRef,      TWPTextObjectPaintModes Modes,      const TWPPaintExtraParams &CanvasExtraAttr,      TWPTextObjectPaintResult &ContinueMode){    if(CompareText(pobj->Source,"LOGO")==0)    {       toCanvas->StretchDraw(Rect(X,Y,X+W,Y+H),          Image1->Picture->Graphic);       ContinueMode = ContinueMode >> wpobjPaintRedCross // remove                                   << wpObjPaintContents; // add;    }}

    You will need to add #include "WPRTEPaint" and #include "WPObj_Image".
    If you need to assign the event handler at runtime please note that you have to assign it to the 'Memo' object. The Linker will otherwise report an error.

    Code
    WPRichText1->Memo->OnTextObjectPaint = &WPRichText1TextObjectPaint;

    So, how can we export a valid RTF file?

    We use the events OnPrepareImageforSaving and AfterImageSaving to temporarily assign a TWPOImage which contains the data.

    This code will be executed before the writer tries to save an image:

    Code
    void __fastcall TForm1::WPRichText1PrepareImageforSaving(      TWPRTFDataCollection *RTFData, TWPCustomTextWriter *Writer,      TWPTextObj *TextObject, bool &DontSave){  if(ExportingFile)  {     if(CompareText(TextObject->Source,"LOGO")==0)     {       TWPOImage *tempobj = new TWPOImage(WPRichText1->HeaderFooter);       tempobj->LoadFromFile(ImageLink->Caption);       TextObject->ObjRef = tempobj;       // Make sure the RTFData is written, not just the link!       // The link would be saved since the property 'Source' was used!       Writer->StoreOptions = Writer->StoreOptions<<soAlwaysEmbedFilesInRTF;     }  }}

    This code will be executed after the saving - we use it to remove the image.

    If you intend to save HTML files simple change the property 'SOURCE' to the filename of the image. You can use the property 'Params' to save the original ID.

    You can download the C++Builder example source here:
    http://www.wpcubed.com/faqimg/ImageLinkCPP.zip