15

Is there a way how to draw specific HTML element content on a canvas without using any web browser control ?

With this code I'm rendering the element to the form's canvas (just as an example).
It works though, but this code is not a good practice - see below, why...

uses
  SHDocVw, MSHTML;

procedure TForm1.Button1Click(Sender: TObject);
var
  WebBrowser: TWebBrowser;
  HTMLElement: IHTMLElement;
  HTMLRenderer: IHTMLElementRender;
begin
  WebBrowser := TWebBrowser.Create(nil);
  try
    WebBrowser.ParentWindow := Application.Handle;
    WebBrowser.Navigate('https://stackoverflow.com/questions/2975586/good-delphi-blogs');

    while WebBrowser.ReadyState < READYSTATE_COMPLETE do
      Application.ProcessMessages;

    HTMLElement := (WebBrowser.Document as IHTMLDocument3).getElementById('question');
    HTMLRenderer := (HTMLElement as IHTMLElementRender);
    HTMLRenderer.DrawToDC(Canvas.Handle);

  finally
    HTMLElement := nil;
    HTMLRenderer := nil;
    WebBrowser.Free;
  end;
end;

It's bad because

  • it uses the hidden TWebBrowser control, but I would like to load the HTML document directly through the IHTMLDocument interface and render certain element on my own canvas
  • if I create and load the IHTMLDocument manually e.g. this way then the renderer method IHTMLElementRender.DrawToDC doesn't paint anything (maybe because there's no canvas for rendering of the document)
  • even worse is that IHTMLElementRender.DrawToDC is deprecated at this time, so I'm looking for an alternative method for rendering elements on my own canvas

Is there a clean way to solve this using MSHTML ?

Community
  • 1
  • 1
TLama
  • 75,147
  • 17
  • 214
  • 392
  • 5
    did you tried embedding chromium: http://code.google.com/p/delphichromiumembedded, there is an offscreen rendering component. – Henri Gourvest Nov 29 '11 at 14:36
  • Agreed, try delphichromiumembedded. It even includes an offscreen rendering demo. – Ondrej Kelle Nov 29 '11 at 14:38
  • Thanks for the response, but I want to avoid to use 3rd party controls at all (even if they might be better). I'd like to use pure MS interface solution. It's a pity that `IHTMLElement` doesn't support `IViewObject`. – TLama Nov 29 '11 at 14:53
  • 1
    What does "badly hidden" mean? Why not use TWebBrowser directly? And why not chromium if it supports drawing on canvas? – Marcus Adams Nov 29 '11 at 15:54
  • @Marcus, I mean that it has `ParentWindow` set to the `Application.Handle`, what seems to me not so good. To the second question, because I want to avoid to use `TWebBrowser` at all; I'd like to work directly with `IHTMLDocument`. Why not chromium ? Just because I'm looking for a MS HTML solution :) I know it's better than the old IWebBrowser2 wrapper ;) – TLama Nov 29 '11 at 16:26
  • @TLama, I wonder what do you want to do? do you want to print the document? provide a preview? I have managed to Load the `IHTMLDocument` manually but it paints the WB borders also... :/ I also tried to use `"htmlfile"` ole object, but it doesn't paint anything on the output canvas... if DrawToDC is deprecated in IE9 then you probably should use a 3rd party solution like `THtmlViewer`. – kobik Nov 30 '11 at 13:52
  • @kobik, I want to make a screenshot of the certain element on a page. And as lightweight as possible. And distribute our application with chromium seems to me like an overkill because it's the minor functionality in our software. How did you managed to load and paint the `IHTMLDocument` manually without web browser control ? That's probably what I'm looking for, at this time I think it's impossible because the document misses the renderer - the web browser control. I'm able to load the document, find the element but I can't render it without web browser control. – TLama Nov 30 '11 at 14:09
  • @TLama, by "Manually" I meant using the `SetHtml` as string method, rather than Navigate. This can not be done without using the TWebBrowser IMHO. the response HTML is depended on the css, it can be dynamically created with JS, etc... so , the TWebBrowser control (`Internet Explorer_Server` HWND) is rendering the page. I think your solution is good enough (if it's a minor functionality in you app). – kobik Nov 30 '11 at 15:43
  • @kobik, post your last comment as the answer and I'll accept it. I agree with you, that the `TWebBrowser` is necessary for content rendering. Anyway, thanks to all – TLama Dec 17 '11 at 16:25

3 Answers3

3

DrawToDC and IViewObject both require the TWebBrowser control to actually render the document into a target DC.

kobik
  • 21,001
  • 4
  • 61
  • 121
  • 1
    As I promised, including +1 :) anyway interesting music production, I've heard some of your tracks and I like that. It sounds me very strongly like Depeche Mode. – TLama Dec 17 '11 at 22:19
1

Maybe you can try THtmlViewer? http://code.google.com/p/thtmlviewer/

André
  • 8,920
  • 1
  • 24
  • 24
  • 1
    sniped for a second! These do work but will probably choke on most modern ajax-y pages. – Leonardo Herrera Nov 29 '11 at 14:54
  • Thanks, but I'm really looking for a [IHTMLElementRender.DrawToDC](http://msdn.microsoft.com/en-us/library/aa752273%28v=vs.85%29.aspx) alternative from MS (if there's some). – TLama Nov 29 '11 at 15:00
1

See THTMLabel from tms-software

Ravaut123
  • 2,764
  • 31
  • 46
  • I appreciate your answer, but unfortunately `THTMLabel` is without source and paid and I bet it has its own parsing and rendering system. I'm really focusing on MS interfaces. – TLama Nov 29 '11 at 15:56