Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi TWebbrowser Gridshow und Snap-to-grid CtoPas (https://www.delphipraxis.net/67760-twebbrowser-gridshow-und-snap-grid-ctopas.html)

Mavarik 19. Apr 2006 14:15


TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Hallo Zusammen...

Ein Problem habe ich noch vielleicht kann ja einer von Euch besser C.

Ich würde gerne im TWebbrowser ein Grid anzeigen...

Delphi-Quellcode:
error := ((HTMLDocument2Ifc as IHTMLDocument2).body as IHTMLElement2).addBehavior('',vFactory);
Hierbei müsste "nur" noch VFactory richtig gesetzt werden. Als Interface Procedure auf eine IHTMLPainter Routinen...

In C sieht die so aus:

Delphi-Quellcode:
STDMETHODIMP CHTMLEditControlSite::XHTMLPainter::Draw(RECT rcBounds, RECT /*rcUpdate*/, LONG /*lDrawFlags*/, HDC hdc, LPVOID /*pvDrawObject*/)
{
   if (m_bGrid != FALSE)
   {
      HPEN redPen   = (HPEN) CreatePen(PS_DOT, 0, RGB(0xff, 0x99, 0x99));
      HPEN oldPen = (HPEN) SelectObject(hdc, redPen);

      long lFirstLine = rcBounds.left + m_iGrid;

      for (int i = lFirstLine; i <= rcBounds.right; i += m_iGrid)
      {
         MoveToEx(hdc, i, rcBounds.top, NULL);
         LineTo(hdc, i, rcBounds.bottom);
      }

      lFirstLine = rcBounds.top + m_iGrid;

      for (i = lFirstLine ; i <= rcBounds.bottom; i += m_iGrid)
      {
         MoveToEx(hdc, rcBounds.left, i, NULL);
         LineTo(hdc, rcBounds.right, i);
      }

      SelectObject(hdc, oldPen);
      DeleteObject(redPen);
   }

   return S_OK;
}
Auf ähnliche Weise muss die SnaptoGrid eingebunden werden...

Hat einer von Euch das als Delphi Source?

Ich habe auch noch 2* Source und Demo in C gefunden:

Einmal hier
und hier (msdn)

Danke im Voraus

Frank :coder:

Mavarik 20. Apr 2006 07:14

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Hallo Zusammen...

Vielleicht hat ja einer von Euch eine Idee, wie ich eine QueryService procedure in mein Form-Object implementiere.

Das würde mir schon helfen.

Frank :coder:

marabu 20. Apr 2006 08:43

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Hallo Frank,

meinst du das hier?

Delphi-Quellcode:
uses
  {...} ActiveX;

type
  TForm1 = class(TForm, IServiceProvider)
  public
    function QueryService(const rsid, iid: TGuid; out Obj): HResult; stdcall;
  end;
Grüße vom marabu

Mavarik 20. Apr 2006 09:20

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Zitat:

Zitat von marabu
Hallo Frank,

meinst du das hier?

Delphi-Quellcode:
uses
  {...} ActiveX;

type
  TForm1 = class(TForm, IServiceProvider)
  public
    function QueryService(const rsid, iid: TGuid; out Obj): HResult; stdcall;
  end;
Grüße vom marabu

Ja genau, aber diese QueryService wird bei mir NIE aufgerufen, genau das ist mein Problem!

Meine Test Unit:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, OleCtrls, SHDocVw,ActiveX,MSHTML;

type
  TForm1 = class(TForm,IServiceProvider)
    WebBrowser1: TWebBrowser;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure WebBrowser1DocumentComplete(Sender: TObject;
      const pDisp: IDispatch; var URL: OleVariant);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    function QueryService(const rsid, iid: TGuid; out Obj): HResult; stdcall;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Webbrowser1.Navigate('http://www.delphipraxis.net');
end;

function TForm1.QueryService(const rsid, iid: TGuid; out Obj): HResult; stdcall;
begin
  Caption := 'Query'; // Wird nie Aufgerufen
end;

procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
begin
  (Webbrowser1.Document as IHTMLDocument2).designMode := 'on';
end;

end.
Frank :wiejetzt:

marabu 20. Apr 2006 09:35

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Vielleicht weil deine Form nicht der Host für die TWebBrowser-Komponente ist.

Nachtrag: wenn ich richtig gelesen habe, dann muss deine Form auch die Schnittstelle IOleClientSite implementieren, deren Methode QueryInterface verwendet wird um den ServiceProvider zu ermitteln.

marabu

Mavarik 20. Apr 2006 09:48

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Zitat:

Zitat von marabu
Vielleicht weil deine Form nicht der Host für die TWebBrowser-Komponente ist.

Nachtrag: wenn ich richtig gelesen habe, dann muss deine Form auch die Schnittstelle IOleClientSite implementieren, deren Methode QueryInterface verwendet wird um den ServiceProvider zu ermitteln.

marabu

:wiejetzt: Kannst Du das mal In Delphi antworten... Das habe ich jetzt nicht verstanden!

Frank

Mavarik 20. Apr 2006 19:34

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Zitat:

Zitat von marabu
Vielleicht weil deine Form nicht der Host für die TWebBrowser-Komponente ist.

Nachtrag: wenn ich richtig gelesen habe, dann muss deine Form auch die Schnittstelle IOleClientSite implementieren, deren Methode QueryInterface verwendet wird um den ServiceProvider zu ermitteln.

marabu

OK Habe mittlerweile verstanden was Du damit meinst....

Wenn ich jedoch IOleClientSite und IHTMLPainter und IHTMLBehavior und IHTMLBehaviorFactory in mein TForm include...

:wall: :wiejetzt:

Wie kann ich unterschiedliche QueryInterface declarieren?

Frank :coder: :roteyes: :spin2:

marabu 20. Apr 2006 19:41

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Wieso denn "unterschiedliche" QueryInterface? Die Interfaces teilen sich doch eine Implementierung dieser Methode - oder verstehe ich dich falsch?

marabu

Mavarik 20. Apr 2006 20:05

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Zitat:

Zitat von marabu
Wieso denn "unterschiedliche" QueryInterface? Die Interfaces teilen sich doch eine Implementierung dieser Methode - oder verstehe ich dich falsch?

marabu

Schon, jedoch ist in diesem C-Beispiel folgendes:

Delphi-Quellcode:
STDMETHODIMP CHTMLEditControlSite::XHTMLEditHost::QueryInterface(REFIID iid, LPVOID far* ppvObj)    
{
   METHOD_PROLOGUE(CHTMLEditControlSite, HTMLEditHost);

   return pThis->ExternalQueryInterface(&iid, ppvObj);
}
und

Delphi-Quellcode:
STDMETHODIMP CHTMLEditControlSite::XHTMLElementBehaviorFactory::QueryInterface(REFIID iid, LPVOID far* ppvObj)    
{
   METHOD_PROLOGUE(CHTMLEditControlSite, HTMLElementBehaviorFactory);

   *ppvObj = NULL;

   if (IsEqualIID(iid, IID_IElementBehaviorFactory))
   {
      *ppvObj = (IUnknown *) this;
      return S_OK;
   }
   else if (IsEqualIID(iid, IID_IElementBehavior))
   {
      *ppvObj = (IUnknown *) &pThis->m_xHTMLElementBehavior;
      return S_OK;
   }

   return E_NOTIMPL;
}
und

Delphi-Quellcode:
STDMETHODIMP CHTMLEditControlSite::XHTMLPainter::QueryInterface(REFIID iid, LPVOID far* ppvObj)    
{
   METHOD_PROLOGUE(CHTMLEditControlSite, HTMLPainter);

   return pThis->ExternalQueryInterface(&iid, ppvObj);
}
Also drei Mal QueryInterface mit unterschiedlichen Auswirkungen...

Ich habe es jetzt so gelöst, da das ursprüngliche Obj kein Interface ist und ich keinen TypCast hingekiregt habe...

Delphi-Quellcode:
function TForm1.MyQuery(out Obj: IInterface): HRESULT;
begin
  Obj := Self as IHTMLPainter;
  Result := S_OK;
end;

function TForm1.MyQuery2(out Obj: IInterface): HRESULT;
begin
  Obj := Self;
  Result := S_OK;
end;

function TForm1.MyQuery3(out Obj: IInterface): HRESULT;
begin
  Obj := Self as IElementBehaviorFactory;
  Result := S_OK;
end;

function TForm1.MyQuery4(out Obj: IInterface): HRESULT;
begin
  Obj := Self as IElementBehavior;
  Result := S_OK;
end;

function TForm1.QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
begin
  Inherited QueryInterface(IID,Obj);

  if IsEqualGUID(IID,IID_IElementBehaviorFactory) then
    begin
      result := MyQuery3(IUnknown(Obj));
      exit;
    end;

  if IsEqualGUID(IID,IID_IElementBehavior) then
    begin
      result := MyQuery4(IUnknown(Obj));
      exit;
    end;

  if IsEqualGUID(IID, IID_IHTMLPainter) then
    begin
      result := MyQuery(IUnknown(Obj));
      exit;
    end;
  if IsEqualGUID(IID, IID_IUnKnown) then
    begin
      result := MyQuery2(IUnknown(Obj));
      exit;
    end;
  result := E_NOTIMPL;
end;

Ich habe ein Testprogramm mit EmbeddedWB! Diese Unit "schafft" es den QueryInterface zu erhalten.

Bei mit kommt im Queryinterface immer nur ein TGUID = '{00000000-0000-0000-C000-000000000046}'
einmal und sonst NIX!

Frank :wall: :wall:

marabu 20. Apr 2006 20:51

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Zitat:

Zitat von Mavarik
Also drei Mal QueryInterface mit unterschiedlichen Auswirkungen...

Naja, nicht ganz.

Wolltest du es vielleicht so?

Delphi-Quellcode:
// ungetestet

function TForm1.QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
begin
  Result := S_OK;
  if IsEqualGUID(IID, IID_IElementBehaviorFactory) then
    IInterface(Obj) := self as IElementBehaviorFactory else
  if IsEqualGUID(IID, IID_IElementBehavior) then
    IInterface(Obj) := self as IElementBehavior else
  if IsEqualGUID(IID, IID_IHTMLPainter) then
    IInterface(Obj) := self as IHTMLPainter else
  Result := inherited QueryInterface(IID, Obj);
end;
marabu

Mavarik 20. Apr 2006 21:14

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Zitat:

Zitat von marabu
Delphi-Quellcode:
function TForm1.QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
begin
  Result := S_OK;
  if IsEqualGUID(IID, IID_IElementBehaviorFactory) then
    IInterface(Obj) := self as IElementBehaviorFactory else
  if IsEqualGUID(IID, IID_IElementBehavior) then
    IInterface(Obj) := self as IElementBehavior else
  if IsEqualGUID(IID, IID_IHTMLPainter) then
    IInterface(Obj) := self as IHTMLPainter else
  Result := inherited QueryInterface(IID, Obj);
end;
marabu

Ojee ja genau... Wusste nicht, das man auch auf der zuweisenden Seite Typcasten kann. :wall:

Folgende events kommen in dieser Procedure in dieser Reihenfolge an:

Delphi-Quellcode:
  IID_IElementBehaviorFactory:{3050F429-98B5-11CF-BB82-00AA00BDCE0B}
  IID_IElementBehavior:{3050F425-98B5-11CF-BB82-00AA00BDCE0B}
  IID_IProxyManager:TGUID ='{00000008-0000-0000-C000-000000000046}'
??? {3050F4FA-98B5-11CF-BB82-00AA00BDCE0B}
  IID_IPersistPropertyBag2:TGUID ='{22F55881-280B-11D0-A8A9-00A0C90C2004}'
  IID_IPersistPropertyBag:TGUID ='{37D84F60-42CB-11CE-8135-00AA004BB851}'
  IID_CPC:TGUID = '{B196B284-BAB4-101A-B69C-00AA00341D07}'
  IID_IHTMLPainter:{3050F6A6-98B5-11CF-BB82-00AA00BDCE0B}
??? {3050F6DE-98B5-11CF-BB82-00AA00BDCE0B}
  IID_IHTMLPainterOverlay: TGUID = '{3050F7E3-98B5-11CF-BB82-00AA00BDCE0B}';
  IID_IHTMLPainterEventInfo: TGUID = '{3050F6DF-98B5-11CF-BB82-00AA00BDCE0B}';
  IID_IElementBehaviorCategory: TGUID = '{3050F4ED-98B5-11CF-BB82-00AA00BDCE0B}';
  IID_IOleCommandTarget = "{B722BCCB-4E68-101B-A2BC-00AA00404770}"
  IID_IElementBehaviorLayout: TGUID = '{3050F6BA-98B5-11CF-BB82-00AA00BDCE0B}';
Leider wird die IHTMLPainter.Draw nie aufgerufen...

Hast Du noch eine Idee?

Ach ja die Behavior setze ich so: (Ich hasse Interfaces)

Delphi-Quellcode:
procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
var
  vFactory : OleVariant;
  Body : IHTMLElement;
  Body2 : IHTMLElement2;
  Doc : IHTMLDocument2;
begin
  (Webbrowser1.Document as IHTMLDocument2).designMode := 'on';
  (Webbrowser1.Document as IHTMLDocument2).execCommand('2D-Position', false,true);
  (Webbrowser1.Document as IHTMLDocument2).execCommand('MULTIPLESELECTION',false,true);
  (Webbrowser1.Document as IHTMLDocument2).execCommand('Liveresize',false,true);

  Doc := (Webbrowser1.Document as IHTMLDocument2);
  Body := Doc.createElement('body');
  if Body = NIL then
    exit;

  Body.QueryInterface(IID_IHTMLElement2,Body2);

  if Body2 = NIL then
    begin
      Body._Release;
      exit;
    end;

  VFactory := IElementBehaviorFactory(Self);
  Body2.addBehavior('',vFactory);
  Body._Release;
  Body2._Release;
end;
mfg Frank :coder:

Mavarik 20. Apr 2006 21:31

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
PS.: Die Aufrufreihenfolge ist

FindBehavior
Init
GetPainterInfo
Notify
Detach

Jedoch liefert ein PaintSite.InvalidateRect(NIL);
einen Fehler $8000FFFF

{ Catastrophic failure }
E_UNEXPECTED = HRESULT($8000FFFF);


Frank :gruebel:

Mavarik 27. Apr 2006 08:17

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
hähem.... Push :oops:

Hat das von Euch noch niemand verwenden?

Frank :angel:

marabu 27. Apr 2006 08:28

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Ich habe diese Schnittstellen in noch keinem Projekt gebraucht, aber wenn du Code-Fragmente zum debuggen hast, dann stelle sie ruhig ein.

marabu

Mavarik 27. Apr 2006 08:37

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Zitat:

Zitat von marabu
Ich habe diese Schnittstellen in noch keinem Projekt gebraucht, aber wenn du Code-Fragmente zum debuggen hast, dann stelle sie ruhig ein.

marabu

:roll: aäääähh ok... Muss mal sehen wie ich die Zeilen aus dem Project raushole...

Werde ich machen...Danke für das Angebot.

Frrank

Mavarik 27. Apr 2006 15:18

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Zitat:

Zitat von marabu
Ich habe diese Schnittstellen in noch keinem Projekt gebraucht, aber wenn du Code-Fragmente zum debuggen hast, dann stelle sie ruhig ein.

marabu

OK eMail ist mit dem Testprogramm an Dich raus!

Mfg Frank

marabu 8. Mai 2006 10:21

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Frank,

ich habe ein Rahmenprojekt implementiert, welches ohne die von dir verwendete EditHost-Komponente auskommt. Ist nicht viel Code, tut nicht viel, aber soll möglichst deutlich die Vorgehensweise beim Implementieren der Schnittstelle IHTMLEditHost zeigen. Ich habe den von dir verwendeten EmbeddedWebBrowser zugrunde gelegt. Die Unit MSHTML_TLB verwende ich nicht direkt, sondern schlachte sie nach Bedarf aus. Wenn Interesse besteht, dann baue ich das Projekt noch weiter aus. Kann aber dauern, da ich momentan bei einem Kunden eingespannt bin und zusammenhängende Zeit zu finden nicht einfach ist.

Grüße vom marabu

Mavarik 8. Mai 2006 12:35

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Hallo!

Sorry, aber das war es leider nicht...

Es ging darum, das der QueryService NUR aufgerufen wird, wenn diese EmbeddedWebBrowser komponente verwendet wird.
Diese Komponente nutzt übrigens auch die MSHTML_TLB und Du hast die Indirekt auch verwendet, den
MSHTML ist das gleiche - nur von Borland und veraltet.

Es ging mir darum die Paintsite implementierung zu erhalten um das Grid zu zeichnen...

Ich hatte Dir doch ein Demo-Programm geschickt...

Trotzdem Danke für Deine Mühe...

LG Frank

PS.: Vielleicht kannst Du ja nochmal schauen, warum QueryService in einem "normalen" Form nicht funktioniert, bzw. ein PaintSite.Invalidate eine
Catrastrophic failure liefert...

marabu 8. Mai 2006 15:04

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Hallo Frank.

Zitat:

Zitat von Mavarik
Sorry, aber das war es leider nicht...

Das war eine Fingerübung von mir - ich brauche schließlich sauberen Code um darauf aufzubauen. Insbesondere wollte ich deine Komponente eliminieren, damit ich diese nicht unnötigerweise auf meiner Maschine installieren muss.

Zitat:

Zitat von Mavarik
Es ging darum, das der QueryService NUR aufgerufen wird, wenn diese EmbeddedWebBrowser komponente verwendet wird.

Das ist nicht verwunderlich. Wenn du EWB nicht verwenden willst, dann musst du eine eigene Komponente von TWebBrowser ableiten, welche die Schnittstelle IServiceProvider implementiert. Oder du verzichtest auf die Komponente TWebBrowser und hostest direkt MSHTML - zu aufwendig finde ich.

Zitat:

Zitat von Mavarik
Diese Komponente nutzt übrigens auch die MSHTML_TLB und Du hast die Indirekt auch verwendet, den MSHTML ist das gleiche - nur von Borland und veraltet.

Ich weiß genau was ich tue - meistens. Unter MSHTML_TLB verstehe ich eine beliebige mit TLIBIMP erzeugte Unit, im Gegensatz zur Original-Unit MSHTML von Borland. Ich verwende eine (nicht deine) bei mir installierte EWB-Komponente und diese verwendet die original MSHTML Unit.

Zitat:

Zitat von Mavarik
Es ging mir darum die Paintsite implementierung zu erhalten um das Grid zu zeichnen...

Eines nach dem anderen. Ich hatte ja schon erwähnt, dass ich diese Schnittstellen noch nicht verwendet habe, also habe ich auch keinen fertigen Code für dich - den muss ich erst noch schreiben.

Zitat:

Zitat von Mavarik
Vielleicht kannst Du ja nochmal schauen, warum QueryService in einem "normalen" Form nicht funktioniert, bzw. ein PaintSite.Invalidate eine Catrastrophic failure liefert...

Nochmal mit anderen Worten: deine normale Form ist kein Host für das WebBrowser Control. Eine Host-Object-Beziehung erzeugst du z.B. wenn du mit TOleContainer arbeitest.

Freundliche Grüße

marabu

Mavarik 8. Mai 2006 15:42

Re: TWebbrowser Gridshow und Snap-to-grid CtoPas
 
Zitat:

Zitat von marabu
Hallo Frank.

Zitat:

Zitat von Mavarik
Sorry, aber das war es leider nicht...

Das war eine Fingerübung von mir - ich brauche schließlich sauberen Code um darauf aufzubauen. Insbesondere wollte ich deine Komponente eliminieren, damit ich diese nicht unnötigerweise auf meiner Maschine installieren muss.

OK
Zitat:

Zitat von marabu
Zitat:

Zitat von Mavarik
Es ging darum, das der QueryService NUR aufgerufen wird, wenn diese EmbeddedWebBrowser komponente verwendet wird.

Das ist nicht verwunderlich. Wenn du EWB nicht verwenden willst, dann musst du eine eigene Komponente von TWebBrowser ableiten, welche die Schnittstelle IServiceProvider implementiert. Oder du verzichtest auf die Komponente TWebBrowser und hostest direkt MSHTML - zu aufwendig finde ich.

Ach... Das ist der ganze Trick? Muss ich sofort mal ausprobieren...

Zitat:

Zitat von marabu
Eines nach dem anderen. Ich hatte ja schon erwähnt, dass ich diese Schnittstellen noch nicht verwendet habe, also habe ich auch keinen fertigen Code für dich - den muss ich erst noch schreiben.

OK kein Problem...

Zitat:

Zitat von marabu
Zitat:

Zitat von Mavarik
Vielleicht kannst Du ja nochmal schauen, warum QueryService in einem "normalen" Form nicht funktioniert, bzw. ein PaintSite.Invalidate eine Catrastrophic failure liefert...

Nochmal mit anderen Worten: deine normale Form ist kein Host für das WebBrowser Control. Eine Host-Object-Beziehung erzeugst du z.B. wenn du mit TOleContainer arbeitest.

Ahh... Wo ist der Unterschied? Bzw. wie funktioniert es, dass ein XY TForm ein HOST wird?

LG Frank :coder:


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:41 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz