I am using TWebBrowser as editor GUI for users. I want to be able to insert web controls into the document. A simple example would be a check box. (I can elaborate why if needed). I have all this working when I first assemble the HTML document (with its STYLE and SCRIPTS sections) and then pass it en-block to the TWebBrowser. But now I want to be able to insert my elements into an existing document.
I have this code, below, but it is causing and OLE error (see in comments in code):
procedure THTMLTemplateDocument.EnsureStylesInWebDOM;
var StyleBlock : IHTMLElement;
StyleText: string;
begin
StyleBlock := FWebBrowser.GetDocStyle;
if not assigned(StyleBlock) then
raise Exception.Create('Unable to access <STYLE> block in web document');
StyleText := FCumulativeStyleCodes.Text;
StyleBlock.InnerText := StyleText; <--- generates "OLE ERROR 800A0258"
end;
The called functions from the above code are as follows:
function THtmlObj.GetDocStyle: IHTMLElement;
//Return pointer to <STYLE> block, creating this if it was not already present.
var
Document: IHTMLDocument2; // IHTMLDocument2 interface of Doc
Elements: IHTMLElementCollection; // all tags in document body
AElement: IHTMLElement; // a tag in document body
Style, Head: IHTMLElement;
I: Integer; // loops thru Elements in document body
begin
Result := nil;
if not Supports(Doc, IHTMLDocument2, Document) then
raise Exception.Create('Invalid HTML document');
Elements := Document.all;
for I := 0 to Pred(Elements.length) do begin
AElement := Elements.item(I, EmptyParam) as IHTMLElement;
if UpperCase(AElement.tagName) <> 'STYLE' then continue;
result := AElement;
break;
end;
if not assigned(Result) then begin
Head := GetDocHead;
if assigned(Head) then begin
Style := Document.CreateElement('STYLE');
(Head as IHTMLDOMNode).AppendChild(Style as IHTMLDOMNode);
Result := Style;
end;
end;
end;
and
function THtmlObj.GetDocHead: IHTMLElement;
//Return pointer to <HEAD> block, creating this if it was not already present.
var
Document: IHTMLDocument2; // IHTMLDocument2 interface of Doc
Elements: IHTMLElementCollection; // all tags in document body
AElement: IHTMLElement; // a tag in document body
Body: IHTMLElement2; // document body element
Head: IHTMLElement;
I: Integer; // loops thru Elements in document body
begin
Result := nil;
if not Supports(Doc, IHTMLDocument2, Document) then
raise Exception.Create('Invalid HTML document');
if not Supports(Document.body, IHTMLElement2, Body) then
raise Exception.Create('Can''t find <body> element');
Elements := Document.all;
for I := 0 to Pred(Elements.length) do begin
AElement := Elements.item(I, EmptyParam) as IHTMLElement;
if UpperCase(AElement.tagName) <> 'HEAD' then continue;
Result := AElement;
break;
end;
if not assigned(Result) then begin
Head := Document.CreateElement('HEAD');
(Body as IHTMLDOMNode).insertBefore(Head as IHTMLDOMNode, Body as IHTMLDOMNode);
//now look for it again
Elements := Document.all;
for I := 0 to Pred(Elements.length) do begin
AElement := Elements.item(I, EmptyParam) as IHTMLElement;
if UpperCase(AElement.tagName) <> 'HEAD' then continue;
Result := AElement;
break;
end;
end;
end;
When I run this, StyleText =
'.selected {'#$D#$A' font-weight : bold;'#$D#$A' //background-color : yellow;'#$D#$A'}'#$D#$A'.unselected {'#$D#$A' font-weight : normal;'#$D#$A' //background-color : white;'#$D#$A'}'#$D#$A#$D#$A
But I tried making StyleText to be something simple like 'hello', and it still crashed.
A Google search for "OLE ERROR 800A0258" reveals several other people who have had similar problems, such as here and here -- this later user seems to indicate he fixed the problem by using .OuterHTML, but I tried this with similar error generated. This thread seems to indicate the .InnerText is read only. But in the interface declaration (see below), it seems to have a method for setting (i.e. not read-only).
// *********************************************************************//
// Interface: IHTMLElement
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {3050F1FF-98B5-11CF-BB82-00AA00BDCE0B}
// *********************************************************************//
IHTMLElement = interface(IDispatch)
['{3050F1FF-98B5-11CF-BB82-00AA00BDCE0B}']
...
procedure Set_innerHTML(const p: WideString); safecall;
function Get_innerHTML: WideString; safecall;
procedure Set_innerText(const p: WideString); safecall;
function Get_innerText: WideString; safecall;
procedure Set_outerHTML(const p: WideString); safecall;
function Get_outerHTML: WideString; safecall;
procedure Set_outerText(const p: WideString); safecall;
function Get_outerText: WideString; safecall;
...
property innerHTML: WideString read Get_innerHTML write Set_innerHTML;
property innerText: WideString read Get_innerText write Set_innerText;
property outerHTML: WideString read Get_outerHTML write Set_outerHTML;
property outerText: WideString read Get_outerText write Set_outerText;
...
end;
Can anyone help be figure out how to set up STYLES in the <STYLE> section of an existing HTML document in a TWebBrowser?