Page 1 of 2

AV when loading from clipboard, htmlviewimporter...

Posted: Wed Dec 17, 2014 4:35 pm
by Lucian
HI,

I am using some code from the demos to import html from clipboard. Basically, I have a TWebBrowser component loaded, I copy to clipboard from it and than paste it in a TRichViewEdit using OnPaste event. Leaving aside a lot of code... I have this piece:
HTMLViewImporter.LoadFromClipboard(lRVHelper.RichView, HTMLViewer);
lRVHelper.RichView.Reformat;

the Reformat call crashes somewhere deep inside TRichView code.
Can I can forward you the email with the html-problem and you can probably use it to reproduce the crash, or do you have a different suggestion?

Thanks

Posted: Wed Dec 17, 2014 4:38 pm
by Sergey Tkachenko
Never call RVReportHelper.RichView.Format and Reformat.
RVReportHelper must be formatted by calling RVReportHelper.Init.

Posted: Thu Dec 18, 2014 7:11 am
by Lucian
Sergey Tkachenko wrote: RVReportHelper must be formatted by calling RVReportHelper.Init.
I am importing from a clipboard, "behind the scene", from a TWebBrowser component to a TRichViewEdit.

So ok ... Ok, ... TRVReportHelper.Init(ACanvas: TCanvas; APageWidth: Integer);

What is my Canvas and what is my PageWidth in this context?
Thanks

Posted: Thu Dec 18, 2014 1:12 pm
by Sergey Tkachenko
What do you want to do with this reporthelper? If you want only save it in RVF (using SaveRVFToStream) for insertion in TRichViewEdit (using InsertRVFFromStreamEd), you do not need to format the reporthelper at all.

Posted: Thu Dec 18, 2014 1:22 pm
by Lucian
1. We retrieve emails. Some are html. The html is stored to a blob and displayed using a TWebBrowser. The TWebBrowser component displays absolutely fine html, plus it's native.

2. When we reply to emails, we have to transfer the html content somehow, to a TRichViewEdit, so that it can be edited. We found that the most reliable way of doing this is copy-paste from webbrowser to the richview edit, using the clipboard and the richview OnPaste event.

This is where we have problems. My code is something like this:
procedure rvCopyHtmlFromClipboard(AOwner: TComponent; rv: THLRichViewEdit);
var
HTMLViewer: THtmlViewer;
HTMLViewImporter: TRVHTMLViewImporter;
lRVHelper: ThaRVReportHelper;
DC: HDC;
begin
lRVHelper := NewRVReportHelper(nil);
try
lRVHelper.MailDir := GetMailFolder;
HTMLViewer := THtmlViewer.Create(AOwner);
try
HTMLViewer.Parent := TWinControl(AOwner);
HTMLViewImporter := TRVHTMLViewImporter.Create(AOwner);
try
DC := GetDC(0);
rvInitializeHelper(lRVHelper, DC, 4000);
ReleaseDC(DC, 0);
HTMLViewImporter.LoadFromClipboard(lRVHelper.RichView, HTMLViewer);
lRVHelper.RichView.Reformat;
lRVHelper.RichView.SelectAll;
lRVHelper.RichView.CopyRVF;
rv.PasteRVF;
rv.Format;
finally
HTMLViewImporter.Free;
end;
finally
HTMLViewer.Free;
end;
finally
DisposeRVReportHelper(lRVHelper);
end;
end;

You are saying I should never use Reformat or format. What I can say is that you are partially right, if I use Format (after LoadFromClipBoard) the code always crashes. However, if I use Reformat, it crashes rarely. And, more important, if I don't use Reformat, my next line SelectAll crashes ALWAYS.

regards
Lucian

Posted: Thu Dec 18, 2014 2:02 pm
by Sergey Tkachenko
You use SelectAll and CopyRVF. Yes, these methods require formatted documents. But this is not the best solution, because:
1) Clipboard must not be modified "silently". The Clipboard must be changed only on explicit "Copy" or "Cut" commands from the user.
2) Formatting is the slowest method, it's highly desirable to avoid it when possible.
I suggest creating TMemoryStream (or, better, TRVMemoryStream), save RVF to it using lRVHelper.RichView.SaveRVFToStream, then reset Stream.Position := 0, then insert the content of this stream using rv.InsertRVFFromStreamEd, then free this stream.

You can see how it is implemented in RichViewActions.
Open RichViewActions.pas, see the procedure PasteHTML.

Posted: Thu Dec 18, 2014 3:26 pm
by Lucian
I did the memorystream stuff, it worked. However, I still have an AV when freeing the TRVReportHelper, or more exactly when this component frees its own RichView... This AV happened all the time.

Posted: Thu Dec 18, 2014 3:32 pm
by Lucian
Sergey Tkachenko wrote: 1) Clipboard must not be modified "silently".
Yeah ... well .... do you have an alternative for moving data from a TWebBrowser to a TRichViewEdit ? LIke I said, we are using the TWebBrowser because it displays html a lot better. I tried initially having everything in rvf format, however, first time when converting HTML to RVF is when data gets broken.

Give me you best solution to save html emails in RVF format that will display as close to the original html as possible. And I am not talking about little test html like "This is Arial text, font size 9, bold, underline, fuchsia". I am talking about advertising emails with tons of pics, tables and lots of html crap. If you want I can forward to you an email like that, and you import it in RVF than send me a screenshot.

Posted: Thu Dec 18, 2014 3:56 pm
by Lucian
I don't know how to upload pics here, so please go to this link:
http://www.ez-delphi.com/trichview.htm

In the left side is the TWebBrowser component.
In the right side is the TRichViewEdit after importing the html.
And it is not the ugliest part.

My boss, kind of he doesn't like it.

Posted: Thu Dec 18, 2014 4:13 pm
by Sergey Tkachenko
As I understand, you use the scheme
HTML -> WebBrowser -> Clipboard -> HTMLViewer -> ReportHelper -> Clipboard -> RichViewEdit

In this scheme, WebBrowser is not necessary.
The same result will be if you load HTML directly in HTMLViewer.
When you call HTMLViewImporter->LoadFromClipboard, HTMLViewer imports HTML from the Clipboard. It would be more rational to load it directly from HTML string.

I.e., the scheme should be:
HTML -> HTMLViewer -> ReportHelper -> Stream -> RichViewEdit.

The results must be identical with your scheme.

Code: Select all

HTMLViewer.LoadFromStream(...) // or LoadFromString
RVHTMLViewImporter.ImportHtmlViewer(HTMLViewer, lRVHelper.RichView);
NormalizeRichView(lRVHelper.RichView.RVData); // from RichViewActions, highly recommended here
Stream := TRVMemoryStream.Create;
lRVHelper.RichView.SaveRVFToStream(Stream, False);
Stream.Position := 0;
rv.InsertRVFFromStreamEd(Stream);
Stream.Free;

Posted: Fri Dec 19, 2014 8:27 am
by Lucian
Hi,

No, the results will not be the same. The html comes from a blob where is uploaded from Indy mail components. The charset can be anything ... however the TWebBrowser component, when you execute a copy to clipboard is guaranteed to be UTF-8 (at least that's what Microsoft says). For example, without the TWebBrowser component we get garbage instead of german umlauts. We found out that only with UTF-8 all this chain of components works fine (TRichView, html importer, html view importer, report helper, etc).

In any case, I will mention now second time that I get an AV when freeing the TRVReportHelper object, after importing. It can be reproduced if I forward to you an html email and you try to import it with the methods I use (or if you have a better way, you could let me know how you do it). It would be very nice of you if you could try to fix this AV, it happens in TRichView code. Let me know how you want me to submit this problem.

Regards

Posted: Fri Dec 19, 2014 9:22 pm
by Sergey Tkachenko
Your code sample in this topic does not include procedures for creating, initializing and freeing a reporthelper. Can you create a compilable project (as simple as possible) and send it to richviewgmailcom?
Also, please send HTML email sample.

Posted: Sat Dec 20, 2014 8:17 am
by Lucian
I do have a test case project. Where do you want me to upload it?
Thanks
Lucian

Posted: Sat Dec 20, 2014 8:18 am
by Lucian
ok, I did not see the email address :-)

Posted: Tue Jan 06, 2015 10:18 am
by Lucian
Any news on this issue?
Thanks