CppWebBrowser Probleme



  • Hallo,

    hab einige Probleme mit der CppWebBrowser-Komponente.

    Ich hab mir im Internet Quellcode für automatisches Login auf Webseiten zusammengesucht.

    Das ganze funktioniert so, das ich per CppWebBrowser1->Navigate die entsprechende Seite öffne und per Funktionen Formularfelder automatisch ausfüllen lassen und danach das Formular abschicke.

    Um die Formulareingaben ausfüllen zu können muss die Seite aber komplett geladen sein, weil es sonst nicht funktioniert. Aber wie bekomm ich nun genau diesen Status raus.

    ein

    CppWebBrowser1->Navigate((WideString)"xyz.de");
    while (CppWebBrowser1->Busy)
    {
      Application->ProcessMessages();
    }
    Fill_Element(CppWebBrowser1,"loginName","Mr.x");
    Fill_Element(CppWebBrowser1,"password","xxxxx");
    AutoSubmitForm(CppWebBrowser,"frmLogin");
    

    funktioniert leider nicht, da die Seite trotz allem nicht komplett geladen zu sein scheint. Auch CppWebBrowser1->ReadyState erfüllt nicht den Zweck, da er einfach nicht von 3 auf 4 springt :-((((

    Einzig hilfreich ist das Event : CppWebBrowser1->DocumentComplete.

    Leider habe ich aber ein PageControl und möchte gleichzeitig mehrere Webseiten abfragen. (d.H. die CppWebBrowsers sind dynamisch angelegt worden)

    Wie erstelle ich für mehrere dynamische CppWebBrowser Komponenten ein Ereignis und wie weise ich es zu ???

    Und noch eine Frage. Das Ausfüllen und Submitten der Forms macht er immer nur wenn die CppWebBrowser Komponente den Focus hat. D.H. Er macht mir erst die Eingaben wenn ich die entsprechende Page im PageControl öffne. Wie kann ich alle Seiten fertig laden und erst beim vollständigen laden aller Seiten das Ergebnis anzeigen ???

    Hier meine Funktionen zum automatischen Befüllen der WebForms.

    Automatisches Absenden einer Form

    void TForm1::AutoSubmitForm(TCppWebBrowser *CppWebBrowser, AnsiString HtmlFormName)
    {
    	IHTMLDocument2 *HTMLDoc = NULL;
    
        if(SUCCEEDED(CppWebBrowser->Document->QueryInterface(IID_IHTMLDocument2,
    
        (LPVOID*)&HTMLDoc)))
    
        {
    
            //CppWebBrowser->Navigate((TVariant)URL);
    
            IHTMLElementCollection *pAll = NULL;
    
            if(SUCCEEDED(HTMLDoc->get_all(&pAll)))
    
            {
    
              IHTMLElementCollection *HTMLForms = NULL;
    
              if(SUCCEEDED(HTMLDoc->get_forms(&HTMLForms)) && HTMLForms)
    
              {
    
                // Name des HTML-Formulars <form name="SearchForm"...>
    
                TVariant vName;
    
                TVariant vIndex = 0;
    
                IDispatch *pDisp = NULL;
    
                vName = HtmlFormName;
    
                vIndex = 0;
    
                if(SUCCEEDED(HTMLForms->item(vName, vIndex, &pDisp)) && pDisp)
    
                {
    
                  IHTMLFormElement *HTMLForm = NULL;
    
                  if(SUCCEEDED(pDisp->QueryInterface(IID_IHTMLFormElement,
    
                  (LPVOID*)&HTMLForm)) && HTMLForm)
    
                  {
    
                    HTMLForm->submit();
    
                    HTMLForm->Release();
    
                  }
    
                   pDisp->Release();
    
                }
    
                HTMLForms->Release();
    
            }
        }
     }
    }
    

    Automatisches Befüllen von FormFeldern

    bool TForm1::FillElement (TCppWebBrowser *CppWebBrowser, TVariant NameStr, char
    *Text)
    {
    	//CppWebBrowser->Navigate(WideString(URL).c_bstr());
    	IHTMLDocument2 *HTMLDoc;
    	 if(SUCCEEDED(CppWebBrowser->Document->QueryInterface(IID_IHTMLDocument2,
    	(LPVOID*)&HTMLDoc)))
    	{
    		//CppWebBrowser->Navigate((TVariant)URL);
    		IHTMLElementCollection *pAll = NULL;
    		if(SUCCEEDED(HTMLDoc->get_all(&pAll)))
    		{
    			IDispatch *pDisp = NULL;
    
    			TVariant name = NameStr;   
    			TVariant index=0;
    			if(SUCCEEDED(pAll->item(name, index, &pDisp)))
    			{
    				if(pDisp)
    				{
    					IHTMLInputElement *pInput = NULL;     // mshtml.h
    					pDisp->QueryInterface(IID_IHTMLInputElement, (LPVOID*)&pInput);
    					pDisp->Release();
    					if(pInput)
    					{
    						WideString mybuffer;
    						pInput->put_value (WideString(Text)); //hier der String, der zu schreiben ist.
    						return TRUE;
    					}
    					pInput->Release();
    				}
    			}
    		}
    		pAll->Release();
    	}
    	HTMLDoc->Release();
    	return TRUE;
    }
    


  • Wie erstelle ich für mehrere dynamische CppWebBrowser Komponenten ein Ereignis und wie weise ich es zu ???

    Wie ein anderes Property auch, z.B.

    cppWebBrowser->DocumentComplete = MyDocumentComplete;
    

    Und MyDocumentComplete erstellst du dann als normale Methode in deiner Klasse (mit den vorgegebenen Parametern des Events, s. Hilfe).
    Alternativ einfach temporär ein CppWebBrowserControl auf dein Formular ziehen und dann den Event im ObjektInspektor setzen (lassen).



  • @Th69:

    Danke für die schnelle Antwort.

    Das habe ich versucht, leider ohne Erfolg 😞

    Ich habe mir eine CppWebBrowser Komponente ins Form gezogen und das Event generiert. Dann hab ich in der Header Datei den Namen des Events umbenannt und auch in der Cpp.

    Beispiel

    void __fastcall TForm1::EvtDocumentComplete(TObject *Sender,
          LPDISPATCH pDisp, Variant *URL)
    {
      // ... hier der Code der ausgeführt werden soll
      FillElement(...);
      AutoSubmitForm(...); 
    }
    

    Danach hab ich die Komponente auf der Form wieder gelöscht.

    Wenn ich jetzt der dynamischen CppBrowser Komponente b1

    b1->onDocumentComplete = EvtDocumentComplete;
    

    das Event zuweise, bekomm ich Errors beim Compilieren, das irgendwelche Parameter nicht kompatibel sind.



  • Zeig mal die genaue Fehlermeldung.

    So wie du es jetzt beschrieben hast, sollte es eigentlich klappen.



  • Ok ich muss es noch mal nachstellen, da ich es wieder gelöscht habe.

    Sobald ich es habe melde ich dir die Fehlermeldung.

    Danke schon mal im voraus 🙂



  • So,

    hab es gerade nochmal mit einem Mini Beispiel getestet :

    Header Datei :

    #ifndef Unit1H
    #define Unit1H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include "shdocvw_ocx.h"
    #include <OleCtrls.hpp>
    //---------------------------------------------------------------------------
    class TForm1 : public TForm
    {
    __published:	// IDE-verwaltete Komponenten
            void __fastcall EvtTest(TObject *Sender, LPDISPATCH pDisp, Variant *URL);
    private:	// Benutzer Deklarationen
    public:		// Benutzer Deklarationen
    	__fastcall TForm1(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif
    

    CPP

    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma link "shdocvw_ocx"
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
    	: TForm(Owner)
    {
      TCppWebBrowser *w1 = new TCppWebBrowser(Form1);
      w1->Width = 600;
      w1->Height = 500;
      w1->Top = 10;
      w1->Left = 50;
      w1->Visible = true;
      w1->Navigate((WideString)"www.google.de");
      w1->OnDocumentComplete = EvtTest;
      Form1->InsertControl (w1);
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::EvtTest(TObject *Sender, LPDISPATCH pDisp, Variant *URL)
    {
      Beep();
    }
    //---------------------------------------------------------------------------
    

    Fehlermeldung :

    [BCC32 Fehler] Unit1.cpp(23): E2034 Konvertierung von 'void (_fastcall * (_closure )(TObject *,IDispatch *,Variant *))(TObject *,IDispatch *,Variant *)' nach 'TCppWebBrowserDocumentComplete' nicht möglich



  • Das scheint bei dir ein ähnliches Problem wie unter http://www.delphigroups.info/3/3/5270.html zu sein, d.h. probiere mal statt "LPDISPATCH pDisp, Variant *URL":

    void __fastcall TForm1::EvtTest(TObject *Sender, const _di_IDispatch pDisp, OleVariant &URL)
    

    Wenn nicht, dann mal einfach in die zug. Header-Datei "SHDocVw.hpp" von deinem Builder schauen (welche Version verwendest du denn?).

    Hat denn das Kompilieren geklappt, als du die Komponente direkt benutzt hast (d.h. dessen DocumentComplete-Event erzeugt hast)???



  • Hallo,

    den Artikel hab ich auch gefunden, als ich nach der Fehlermeldung gegoogelt habe.

    Leider hat das Ändern in

    const _di_IDispatch pDisp
    

    nichts gebracht. Ich benutze das RAD-Studio 2007.

    Aber ich schaue mir die Header Datei mal an.

    Danke für deine Hilfe 🙂



  • Poste dann bitte deine Lösung (falls es geklappt hat).



  • Versuchs mit dieser Funktion.
    In meinen Augen ist das so wesentlich sauberer (und schneller).

    void WebPostData(TCppWebBrowser *CppWebBrowser, String sURL, String sPostData)
    {
      BSTR bstrHeaders = NULL;
      TVariant vFlags = {0}, vTargetFrameName={0}, vPostData={0}, vHeaders={0};
      LPSAFEARRAY psa;
      LPCTSTR cszPostData = sPostData.c_str();
      UINT cElems = lstrlen(cszPostData);
      LPSTR pPostData;
      LPVARIANT pvPostData;
    
      bstrHeaders = SysAllocString(L"Content-Type: application/x-www-form-urlencodedrn");
      if (!bstrHeaders){
        Application->MessageBox("Could not allocate bstrHeaders", "Warning", MB_OK | MB_ICONWARNING);
        return;
      }
    
      V_VT(&vHeaders) = VT_BSTR;
      V_BSTR(&vHeaders) = bstrHeaders;
    
      pvPostData = vPostData;
    
      if(pvPostData){
        VariantInit(pvPostData);
    
        psa = SafeArrayCreateVector(VT_UI1, 0, cElems);
        if(!psa){
          return;
        }
    
        SafeArrayAccessData(psa, (LPVOID*)&pPostData);
        memcpy(pPostData, cszPostData, cElems);
        SafeArrayUnaccessData(psa);
    
        V_VT(pvPostData) = VT_ARRAY | VT_UI1;
        V_ARRAY(pvPostData) = psa;
      }
    
       CppWebBrowser->Navigate((TVariant)sURL, &vFlags, &vTargetFrameName, &vPostData, &vHeaders);
    }
    


  • @Yuri:
    Diese Funktion kenn ich auch, war mein erster Versuch. Nur leider funktioniert es nicht ganz.

    Bei einer Abfrage füllt er die Felder aus, submittet mein WebForm aber leider nicht. Wieso und weshalb weiß ich nicht 😞



  • Möglicherweise falsche Parameter eingegeben.
    Wie benutzt du denn die Funktion?



  • Wie ich sie Benutze :

    also ich hab ein Web-Formular

    <form action="result.asp" method="POST" name="form">
     <table border="0">
     <TR>
     <TD nowrap><B>Vorname:&nbsp;</B><input type="text" size="10" name="Vorname_f"   onFocus="init_vorname()" VALUE="">&nbsp;&nbsp;&nbsp;&nbsp;
    <B>Nachname:&nbsp;</B><input type="text" size="10" name="Nachname_f"  onFocus="init_nachname()" VALUE="">
    </TD>
    </TR>
    </table>
    <BR>
    <table border="0">
    <TR>
    <TD nowrap><input type="submit" name="Absenden" value="Absenden"></TD>
    </TR>
    </table>
    </form>
    

    Dieses ruf ich dann mit

    WebPostData(CppWebBrowser1,"http://myserver/mysite.php","Vorname_f=Max&Nachname_f=Mustermann");
    

    auf.

    Das in action aufgerufene Skript

    <form action="result.asp" method="POST" name="form">
    

    lässt sich leider auch nicht direkt nutzen.

    z.b. mit http://myserver/result.asp?Vorname_f=Max&Nachname_f=Mustermann

    die seite wird zwar aufgerufen aber die parameter nicht übergeben



  • PsiAgent schrieb:

    z.b. mit http://myserver/result.asp?Vorname_f=Max&Nachname_f=Mustermann

    Das ist auch ein GET - Request.

    Versuchs so:
    WebPostData(CppWebBrowser1,"http://myserver/result.asp","Vorname_f=Max&Nachname_f=Mustermann");



  • Hey Klasse !!!!

    Das hat funktioniert :-))))

    Danke !!!


Anmelden zum Antworten