Oct 29, 2007 - Inserting RTF code into a rich edit control. For example, if RE is a TRichEdit control, to load from a stream we'd use. Following the thread thread1: Saving RichEdit to Access Database: After 2 hours of web research and tests, I finally found a working solution (using Delphi 7.0) for loading and saving richedit text (with attributes) in an access database. Rules to follow are: - the Access field must be of type 'OLE Object'.
Load and save Richedit Text in database
Load and save Richedit Text in database
Following the thread thread102-1198575: Saving RichEdit to Access Database :
After 2 hours of web research and tests, I finally found a working solution (using Delphi 7.0) for loading and saving richedit text (with attributes) in an access database.
Rules to follow are :
- the Access field must be of type 'OLE Object'
- this field must be in the first position in the query variable(because 'fields[0]', see later )
- the query must contain the primary key field (unique id the record), at any but the first position
- you must pass an ADO connection
Here are my functions, adapt them as you like
Examples :
Field is 'Notes' in table 'Actions' with primary key 'ID', RE is Richedit component, DB.GetConnection is my own ADO connection
SaveRicheditToAccess (DB.GetConnection, RE, 'SELECT Notes, ID FROM Actions WHERESELECT Notes, ID FROM Actions WHERE ID='+inttostr(id));
Function SaveRicheditToAccess (ADOC : TADOConnection ; RE : TRichEdit ; _Select : String) : Boolean;
var
ms: TMemoryStream;
ADO : TADODataset;
begin
ms := TMemoryStream.Create;
Try
Result := FALSE;
// save content to stream
RE.Lines.SaveToStream(ms);
ms.Seek(0, soFromBeginning) ;
ADO := TADODataset.Create (NIL);
ADO.Connection := ADOC;
ADO.CommandTExt := _SELECT;
ADO.Active := True;
ADO.Edit;
// Put stream content in blob field and post it to database
TBlobField(ADO.Fields[0]).LoadFromStream(ms);
ADO.Post;
Result := TRUE;
Finally
FreeAndNil (ms);
FreeAndNil (ADO);
End;
End;
Function LoadRicheditFromAccess (ADOC : TADOConnection ; RE : TRichEdit ; _Select : String) : Boolean; // Select doit renvoyer LE champ à modifier
var
ms: TMemoryStream;
ADO : TADODataset;
begin
ms := TMemoryStream.Create;
Try
Result := FALSE;
ADO := TADODataset.Create (NIL);
ADO.Connection := ADOC;
ADO.CommandTExt := _SELECT;
ADO.Active := True;
// Load rich edit content into stream
TBlobField(ADO.Fields[0]).SaveToStream(ms);
ms.Seek(0, soFromBeginning) ;
// Load rich edit content from stream to component
RE.Lines.LoadFromStream(MS);
Result := TRUE;
Finally
FreeAndNil (ADO);
FreeAndNil (Ms);
End;
End;
After 2 hours of web research and tests, I finally found a working solution (using Delphi 7.0) for loading and saving richedit text (with attributes) in an access database.
Rules to follow are :
- the Access field must be of type 'OLE Object'
- this field must be in the first position in the query variable(because 'fields[0]', see later )
- the query must contain the primary key field (unique id the record), at any but the first position
- you must pass an ADO connection
Here are my functions, adapt them as you like
Examples :
Field is 'Notes' in table 'Actions' with primary key 'ID', RE is Richedit component, DB.GetConnection is my own ADO connection
SaveRicheditToAccess (DB.GetConnection, RE, 'SELECT Notes, ID FROM Actions WHERESELECT Notes, ID FROM Actions WHERE ID='+inttostr(id));
Function SaveRicheditToAccess (ADOC : TADOConnection ; RE : TRichEdit ; _Select : String) : Boolean;
var
ms: TMemoryStream;
ADO : TADODataset;
begin
ms := TMemoryStream.Create;
Try
Result := FALSE;
// save content to stream
RE.Lines.SaveToStream(ms);
ms.Seek(0, soFromBeginning) ;
ADO := TADODataset.Create (NIL);
ADO.Connection := ADOC;
ADO.CommandTExt := _SELECT;
ADO.Active := True;
ADO.Edit;
// Put stream content in blob field and post it to database
TBlobField(ADO.Fields[0]).LoadFromStream(ms);
ADO.Post;
Result := TRUE;
Finally
FreeAndNil (ms);
FreeAndNil (ADO);
End;
End;
Function LoadRicheditFromAccess (ADOC : TADOConnection ; RE : TRichEdit ; _Select : String) : Boolean; // Select doit renvoyer LE champ à modifier
var
ms: TMemoryStream;
ADO : TADODataset;
begin
ms := TMemoryStream.Create;
Try
Result := FALSE;
ADO := TADODataset.Create (NIL);
ADO.Connection := ADOC;
ADO.CommandTExt := _SELECT;
ADO.Active := True;
// Load rich edit content into stream
TBlobField(ADO.Fields[0]).SaveToStream(ms);
ms.Seek(0, soFromBeginning) ;
// Load rich edit content from stream to component
RE.Lines.LoadFromStream(MS);
Result := TRUE;
Finally
FreeAndNil (ADO);
FreeAndNil (Ms);
End;
End;
I am attempting to use Tables in a TRichEdit control in Delphi XE2 Starter Edition. (In other words, I don’t have the source code for XE2 – but I do have it for TurboDelphi). I understand that the default RichEdit control does not use a version of MS RichEdit that supports tables, so I have subclassed it to use MS RichEdit v4.1 as described here 1 and here 6, and also modeled off the code in the JEDI TjvRichEdit. (for the sake of brevity, I have not included the code segment that determines RichEdit version numbers for DLL's other than v4.1, that I borrowed from JEDI. A simplified version is shown here.)
An MSDN blog 2 states that Windows messages to support RTF tables were an undocumented feature of MS RichEdit version 4.1, and that the EM_INSERTTABLE message has been available since Windows XP SP2. For more information on which versions were available when, see here 3.
A comment following this blog 2, posted by David Kinder on 26 Sep 2008, states he was able to get the EM_INSERTTABLE message to work with RichEdit v4.1, using the same code which I have shown below (except he wasn’t using Delphi).
For details on the EM_INSERTTABLE message and the structures that support it, see the MSDN docs 4 (which state they were introduced with Windows 8, but which clearly pre-dated that by at least two major OS versions). Also note that the definition(s) of the structures have changed somewhat since Murray wrote his blog 2 in 2008. I have searched to the ends of the internet and cannot find a MS richedit.h version that goes with RichEdit 4.1 and includes the “undocumented” structures TABLEROWPARMS and TABLECELLPARMS as they existed at that time, so I am limited to the MSDN docs as the exist for Win8 4 and Murray’s blog 2 as they allegedly existed in Win XP and Win7.
Here is my custom RichEdit:
Usage:
Upon execution, rc contains -2147024809 (
E_INVALIDARG
). I don’t have a good understanding of why this fails, or what the problem is with the message arguments. As a disclaimer, I am new to working with RichEdit in Delphi, but I tried to learn as much as possible before posting for help.In my extensive searching, I found this website 5 which may help narrow the problem. This site hosts a utility called RTFLabel. Download the zip file and have a look at richedit2.pas, where they explain that “The definition of CHARFORMAT2A and CHARFORMAT2W in richedit.h (2005 SDK) has an error in the C part”, and that they needed to insert a new dummy field to “fix” the byte alignment of the structure in order to make it work correctly with Delphi. I have a feeling there may be similar alignment issues with one or both of the TABLEROWPARMS and TABLECELLPARMS structures which is causing this error.
I would like some help to figure out why the
-Jeff Aylor
SendMessage
is returning a E_INVALIDARG, and what I can do to fix it. Any assistance would be greatly appreciated!-Jeff Aylor
Referenced websites:
1 [http://fgaillard.com/2010/09/using-richedit-4-1-with-d2010/]1
2 [http://blogs.msdn.com/b/murrays/archive/2008/09/15/richedit-s-nested-table-facility.aspx]2
3 [http://blogs.msdn.com/b/murrays/archive/2006/10/14/richedit-versions.aspx]3
4 [http://msdn.microsoft.com/en-us/library/windows/desktop/hh768373%28v=vs.85%29.aspx]4
5 [http://flocke.vssd.de/prog/code/pascal/rtflabel/]5
6 [Delphi 7 TRichTextEdit Text in a box not displaying correctly6
1 [http://fgaillard.com/2010/09/using-richedit-4-1-with-d2010/]1
2 [http://blogs.msdn.com/b/murrays/archive/2008/09/15/richedit-s-nested-table-facility.aspx]2
3 [http://blogs.msdn.com/b/murrays/archive/2006/10/14/richedit-versions.aspx]3
4 [http://msdn.microsoft.com/en-us/library/windows/desktop/hh768373%28v=vs.85%29.aspx]4
5 [http://flocke.vssd.de/prog/code/pascal/rtflabel/]5
6 [Delphi 7 TRichTextEdit Text in a box not displaying correctly6
Community♦
JeffJeff
2 Answers
tl;dr:
Don't use it for anything other than it is advertised/documented for (i.e lower than W8), even then I would keep an open eye. It's a mess.
Notice that there are other differences between the blog post you take your records from and the documentation, other than the additional three fields of
TABLEROWPARMS
. This is in TABLECELLPARMS
. Here's a side by side comparison, on the left is the record from the blog post, on the right is the record from the documentation. Here you see two additional fields inserted in the middle of the record intuitively. Or, one of them is wrong, perhaps both... But we know from the blog post that there are people who have been able to make it work with the one on the left. Maybe there's a specific version against a specific dll.
Anyway, considering there's a very good probability that the cause of the
E_INVALIDARG
is the size of the structs, since even with a minimal test it fails to work, this led me to test using brute force to determine correct record sizes.Putting a breakpoint to the end of the procedure,
rows.cbRow
comes up '28' and rows.cbCell
comes up '40'. They are pretty smaller than both references. I also tested for a possible match larger than the first hit, there are none. My test is against 'msftedit.dll' version 5.41.21.2510, residing in 'syswow64' of a W7 box, using XE2.So where should we cut the structs, from the end? As we see from the above references, probably not. I don't see any sound way to advance from here, but I'm posting my best try in case you have a similar environment and want to carry on (which I do not recommend - note I had to change the order of fields to come this far). Which is definitely incorrect as it's not able to insert a table having columns more than one for instance.
Sertac AkyuzSertac Akyuz
Erwin SienknechtErwin Sienknecht
![Insert Insert](/uploads/1/2/5/5/125543778/294358813.png)