Using offscreen TRichViewEdit
-
- Posts: 131
- Joined: Mon Aug 29, 2005 12:03 pm
Using offscreen TRichViewEdit
Hi there,
I've been experimenting with using offscreen RichViewEdit and RVStyle components, created on the fly and positioned offscreen (with negative left and top values) on the application's main form. I'm trying to use these components to read blocks of XHTML code and turn it into RVF, which I then store and stream in and out of RichView controls which are visible.
However, I'm having trouble getting the offscreen controls to function properly; when I read in data, then get the RVF, it's empty. In contrast, when I use exactly the same code but targetted at existing RVEs and RVSs that are visible on forms, the reading operations work correctly. I'm wondering if there is some error I'm making in creating and initializing the controls, or perhaps there's something intrinsic to RV controls which makes them function differently when they're offscreen (and therefore invisible, although Visible = True for the RVE). Here's the code I'm using to initialize the controls:
FRVE := TRichViewEdit.Create(Application.MainForm);
FRVE.Parent := TWinControl(Application.MainForm);
FRVS := TRVStyle.Create(Application.MainForm);
with FRVE do
begin
//Put it off-screen
Width := 500;
Height := 500;
Left := -600;
Top := -600;
Style := FRVS;
DoInPaletteMode := rvpaCreateCopies;
ReadOnly := False;
Options := [rvoAllowSelection, rvoScrollToEnd, rvoShowPageBreaks,
rvoTagsArePChars, rvoAutoCopyText, rvoAutoCopyRVF,
rvoAutoCopyImage, rvoAutoCopyRTF, rvoFormatInvalidate,
rvoDblClickSelectsWord, rvoRClickDeselects,
rvoFastFormatting];
RTFReadProperties.UnicodeMode := rvruOnlyUnicode;
RTFReadProperties.TextStyleMode := rvrsAddIfNeeded;
RTFReadProperties.ParaStyleMode := rvrsAddIfNeeded;
RTFReadProperties.UseHypertextStyles := True;
RVFOptions := [rvfoSavePicturesBody, rvfoSaveControlsBody,
rvfoSaveBinary, rvfoSaveTextStyles, rvfoSaveParaStyles,
rvfoSaveDocProperties, rvfoLoadDocProperties];
end;
with FRVS do
begin
if TextStyles.Count > 0 then
for i := 0 to TextStyles.Count-1 do
TFontInfo(TextStyles).Unicode := True;
DefUnicodeStyle := 0;
end;
I've been experimenting with using offscreen RichViewEdit and RVStyle components, created on the fly and positioned offscreen (with negative left and top values) on the application's main form. I'm trying to use these components to read blocks of XHTML code and turn it into RVF, which I then store and stream in and out of RichView controls which are visible.
However, I'm having trouble getting the offscreen controls to function properly; when I read in data, then get the RVF, it's empty. In contrast, when I use exactly the same code but targetted at existing RVEs and RVSs that are visible on forms, the reading operations work correctly. I'm wondering if there is some error I'm making in creating and initializing the controls, or perhaps there's something intrinsic to RV controls which makes them function differently when they're offscreen (and therefore invisible, although Visible = True for the RVE). Here's the code I'm using to initialize the controls:
FRVE := TRichViewEdit.Create(Application.MainForm);
FRVE.Parent := TWinControl(Application.MainForm);
FRVS := TRVStyle.Create(Application.MainForm);
with FRVE do
begin
//Put it off-screen
Width := 500;
Height := 500;
Left := -600;
Top := -600;
Style := FRVS;
DoInPaletteMode := rvpaCreateCopies;
ReadOnly := False;
Options := [rvoAllowSelection, rvoScrollToEnd, rvoShowPageBreaks,
rvoTagsArePChars, rvoAutoCopyText, rvoAutoCopyRVF,
rvoAutoCopyImage, rvoAutoCopyRTF, rvoFormatInvalidate,
rvoDblClickSelectsWord, rvoRClickDeselects,
rvoFastFormatting];
RTFReadProperties.UnicodeMode := rvruOnlyUnicode;
RTFReadProperties.TextStyleMode := rvrsAddIfNeeded;
RTFReadProperties.ParaStyleMode := rvrsAddIfNeeded;
RTFReadProperties.UseHypertextStyles := True;
RVFOptions := [rvfoSavePicturesBody, rvfoSaveControlsBody,
rvfoSaveBinary, rvfoSaveTextStyles, rvfoSaveParaStyles,
rvfoSaveDocProperties, rvfoLoadDocProperties];
end;
with FRVS do
begin
if TextStyles.Count > 0 then
for i := 0 to TextStyles.Count-1 do
TFontInfo(TextStyles).Unicode := True;
DefUnicodeStyle := 0;
end;
-
- Posts: 148
- Joined: Wed Dec 07, 2005 2:02 pm
- Contact:
-
- Posts: 131
- Joined: Mon Aug 29, 2005 12:03 pm
-
- Posts: 131
- Joined: Mon Aug 29, 2005 12:03 pm
I've discovered that the content is correctly being read into the offscreen TRichViewEdit (I can see it if I make that control visible), but when it's streamed out of that control and stored as RVF in a string, something goes wrong; no text is stored, and the RVF is only about a fifth the length it should be.
Any idea what might be causing this?
Cheers,
Martin
Any idea what might be causing this?
Cheers,
Martin
-
- Posts: 131
- Joined: Mon Aug 29, 2005 12:03 pm
Just to clarify, this is the code I'm using to get the RVF string:
function TMRVExporter.GetRVF: string;
var
SS: TStringStream;
strTemp: string;
begin
Result := '';//default return
SS := TStringStream.Create(strTemp);
try
//stream it into the RVE
CurrRVE.SaveRVFToStream(SS, False);
Result := SS.DataString;
finally
FreeAndNil(SS);
end;
end;
function TMRVExporter.GetRVF: string;
var
SS: TStringStream;
strTemp: string;
begin
Result := '';//default return
SS := TStringStream.Create(strTemp);
try
//stream it into the RVE
CurrRVE.SaveRVFToStream(SS, False);
Result := SS.DataString;
finally
FreeAndNil(SS);
end;
end;
-
- Posts: 148
- Joined: Wed Dec 07, 2005 2:02 pm
- Contact:
Martin,
I'm actually using a TRichViewEdit 'dropped' on a form with the visible set to false. However I'm not using the DataString property of the stream - this is an example of the type of code I'm using:
try
RichViewEdit3.SaveRVFToStream(Stream, False);
Stream.Position := 0;
PrintCardsTable.Cells[r,c].Clear;
PrintCardsTable.Cells[r,c].AppendRVFFromStream(Stream,-1,Dummy1,Dummy2);
finally
Stream.Free;
end;
RVE3 is the invisible control and has had content loaded into it from another RVE. I use either AppendRVF or LoadRVF depending on whether the target is being added to or overwritten. Hope this helps. If you need Sergey's help on this I'd recommend a fresh topic as I don't think he looks at threads that other's have "answered"
Dick
I'm actually using a TRichViewEdit 'dropped' on a form with the visible set to false. However I'm not using the DataString property of the stream - this is an example of the type of code I'm using:
try
RichViewEdit3.SaveRVFToStream(Stream, False);
Stream.Position := 0;
PrintCardsTable.Cells[r,c].Clear;
PrintCardsTable.Cells[r,c].AppendRVFFromStream(Stream,-1,Dummy1,Dummy2);
finally
Stream.Free;
end;
RVE3 is the invisible control and has had content loaded into it from another RVE. I use either AppendRVF or LoadRVF depending on whether the target is being added to or overwritten. Hope this helps. If you need Sergey's help on this I'd recommend a fresh topic as I don't think he looks at threads that other's have "answered"
Dick
-
- Posts: 131
- Joined: Mon Aug 29, 2005 12:03 pm
It looks as though there may be a difference between a TRichViewEdit which is instantiated on a form (visible or not) and one which is created entirely in code. If I make my code-built TRVE visible, and make its owner and parent the main form of the application, I can see the documents being loaded into it correctly, but when they're streamed out the stream contains an empty document; when I use an existing TRVE on the form, which was created by dropping components onto the form, then everything works fine. There must be something that happens in the process of creating the TRVE and TRVS components that's different in the two scenarios.
I think the best thing to do is to create a little sample project that demonstrates this, and run it by Sergei to see if he has any ideas. I'd really like to avoid having to use components on an actual form, because it makes my library less portable.
Cheers,
Martin
I think the best thing to do is to create a little sample project that demonstrates this, and run it by Sergei to see if he has any ideas. I'd really like to avoid having to use components on an actual form, because it makes my library less portable.
Cheers,
Martin
-
- Site Admin
- Posts: 17566
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
There is only one difference in TRichView created in code and at design time: initial values of some properties.
All these properties are listed in the component editor (right click in Delphi, "Settings" in the popup menu).
As for your problem, I think it's because of TStringStream. Binary data, such as RVF, cannot be stored in TStringStream. Use TMemoryStream instead.
All these properties are listed in the component editor (right click in Delphi, "Settings" in the popup menu).
As for your problem, I think it's because of TStringStream. Binary data, such as RVF, cannot be stored in TStringStream. Use TMemoryStream instead.
Code: Select all
function TMRVExporter.GetRVF: string;
var
MS: TMemoryStream;
begin
Result := '';//default return
MS := TMemoryStream.Create;
try
//stream it into the RVE
CurrRVE.SaveRVFToStream(MS, False);
SetLength(Result, MS.Size);
Move(MS.Memory^, PChar(Result)^, MS.Size);
finally
FreeAndNil(MS);
end;
end;
-
- Posts: 131
- Joined: Mon Aug 29, 2005 12:03 pm
Hi there,
I hadn't realized RVF was actually binary. Using your code above, is it safe to store and retrieve blocks of RVF in a TStringList? I'm associating each block of RVF (a little document) with a GUID in string form:
[GUID]=RVF
so I can retrieve each block of RVF based on its GUID, and stream it back into a TRichViewEdit for display and editing.
What's puzzling, though, is that this all works fine when I use an existing TRVE, even using TStringStream. Weird!
Cheers,
Martin
I hadn't realized RVF was actually binary. Using your code above, is it safe to store and retrieve blocks of RVF in a TStringList? I'm associating each block of RVF (a little document) with a GUID in string form:
[GUID]=RVF
so I can retrieve each block of RVF based on its GUID, and stream it back into a TRichViewEdit for display and editing.
What's puzzling, though, is that this all works fine when I use an existing TRVE, even using TStringStream. Weird!
Cheers,
Martin
-
- Site Admin
- Posts: 17566
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
You can store strings returned by this GetRVF in TStringList (one item = one RVF document). But you cannot, for example, use TStringList.SaveToFile to store this string list, because RVF contains line break characters.
RVF can be a text format, if you exclude rvfoSaveBinary from RVFOptions (but the resulting data will be larger and saved/loaded more slowly).
To move RVF string to TMemoryStream, use this code:
RVF can be a text format, if you exclude rvfoSaveBinary from RVFOptions (but the resulting data will be larger and saved/loaded more slowly).
To move RVF string to TMemoryStream, use this code:
Code: Select all
MS.Size := Length(RVFString);
Move(PChar(Result)^, MS.Memory^, MS.Size);
-
- Site Admin
- Posts: 17566
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
Probably, your RichViews placed on the form in designtime, had rvfoSaveBinary excluded from RVFOptions.
Or may be their RVFOptions do not contain options to save styles and layout, and documents do not have binary data (pictures, tables, controls, Unicode text).
In these cases, RVF is a text format.
Or may be their RVFOptions do not contain options to save styles and layout, and documents do not have binary data (pictures, tables, controls, Unicode text).
In these cases, RVF is a text format.
Last edited by Sergey Tkachenko on Tue Sep 19, 2006 6:36 am, edited 1 time in total.
-
- Posts: 131
- Joined: Mon Aug 29, 2005 12:03 pm