Browser embedded





  • Danke FachmannFürBrowser für den Tipp!
    Genau so was habe ich gesucht.

    Ich habe ein Beispiel im Netz gefunden, welches eigentlich soweit auch funktioniert.

    #include <windows.h>
     #include <exdisp.h>
    
     HWND container;
    
     /***************************************************************************/
     LRESULT CALLBACK WndProc( HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam )
     {    
         switch(messg)
         {
             case WM_SIZE:
                 MoveWindow(container,0,0,LOWORD(lParam), HIWORD(lParam),1);
                 break;
    
             case WM_CLOSE:
                 DestroyWindow(hWnd);
                 break;
    
             case WM_DESTROY:
                 PostQuitMessage( 0 );
                 break;
    
             default:
                 return( DefWindowProc( hWnd, messg, wParam, lParam ) );
         }
         return 0;
     }
     /***************************************************************************/
    
     /********************* Funktion WinMain ************************************************/
     int WINAPI WinMain( HINSTANCE hInst,HINSTANCE hPreInst,LPSTR lpszCmdLine, int nCmdShow )
     {
         WNDCLASS wc;
         char NomClasse[] = "container";
         wc.lpszClassName = NomClasse;
         wc.hInstance      = hInst;
         wc.lpfnWndProc     = WndProc;
         wc.hCursor = LoadCursor( 0, IDC_ARROW );
         wc.hIcon     = LoadIcon( 0, IDI_APPLICATION );
         wc.lpszMenuName     = 0;
         wc.hbrBackground = 0;
         wc.style     = 0;
         wc.cbClsExtra     = 0;
         wc.cbWndExtra        = 0;
    
         if (!RegisterClass(&wc)) return 0;
    
         HWND hWnd = CreateWindow( NomClasse,"container Activex",WS_OVERLAPPEDWINDOW,0,0,800,575, 0, 0, hInst,0);
         ShowWindow(hWnd, nCmdShow );
         UpdateWindow( hWnd );
    
         HINSTANCE hDLL = LoadLibrary("atl.dll");
         typedef HRESULT (WINAPI *PAttachControl)(IUnknown*, HWND,IUnknown**);
         PAttachControl AtlAxAttachControl = (PAttachControl) GetProcAddress(hDLL, "AtlAxAttachControl");
         RECT rect;
         GetClientRect(hWnd,&rect);
         container=CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","",WS_CHILD | WS_VISIBLE,0,0,rect.right,rect.bottom,hWnd,0,0,0);
         CoInitialize(0);
         IWebBrowser2 *pIwb;
         CoCreateInstance(CLSID_WebBrowser,0,CLSCTX_ALL,IID_IWebBrowser2,(void**)&pIwb);
         AtlAxAttachControl(pIwb,container,0);
         pIwb->GoHome();
    
         pIwb->Navigate2("www.google.ch",0,0,0,0);
    
         MSG Msg;
         while( GetMessage(&Msg, 0, 0, 0))
         {
             TranslateMessage( &Msg );
             DispatchMessage( &Msg );
         }
    
         pIwb->Release();
         CoUninitialize();        
         FreeLibrary(hDLL);
         return( Msg.wParam);
     }
    

    Wenn ich den Code:

    pIwb->Navigate2("www.google.ch",0,0,0,0);
    

    deaktiviere, so sehe ich eine leere HTML Seite. [wegen pIwb->GoHome();]

    Mit dem Code kommt mir eine Fehlermeldung:

    error C2664: 'Navigate2' : cannot convert parameter 1 from 'char [14]' to 'struct tagVARIANT *' 
    Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
    

    Der Syntax müsste eigentlich Ok sein.
    Diese ganze ActiveX, ATL Geschichte ist für mich noch ein Buch mit sieben Siegel . 😃

    Grüsse,
    Sotares



  • Die Funktion erwartet (einen Pointer auf) eine VARIANT-Struktur. Und die braucht den Text als Unicode.

    Ansi in Unicode: MultiByteToWideChar
    VARIANT::vt sollte VT_BSTR sein.
    VARIANT::bstrVal dann ein Pointer auf deine Unicode-Zeichenkette

    Grüße



  • Hallo Badestrand,

    Ich bin nicht sicher, ob ich Konvertierung richtig gemacht habe.
    Auf jedenfall gibt iResult den Wert 0 zurück, müsste dies nicht 1 sein?

    char url[]="www.google.ch";
    WCHAR *strBuffer = new WCHAR[128];
    int iResult = MultiByteToWideChar(CP_ACP, 0, url, 0, strBuffer, sizeof(strBuffer));
    
    	 if(iResult == 0)
    	 {
    	 MessageBox(NULL, "Fehler","",MB_OK);
    	 }
    

    Die Sache mit dem tagVARIANT habe ich nicht ganz begriffen.
    1.) Wie überprüfe ich den Wert in ::tagVARIANT::vt ?
    2.) Wie setze ich danach einen Pointer von ::tagVARIANT::bstrVal auf url?

    Oder habe ich alles komplett falsch verstanden?

    Grüsse,
    Sotares



  • Dein MultiByteToWideChar ist fast richtig: Du musst nur den Parameter cbMultiByte (hinter "url") auf -1 statt auf 0 setzen 😉

    Und das mit VARIANT ist auch ganz einfach:

    VARIANT Variant;
    Variant.vt = VT_BSTR;
    Variant.bstrVal = strBuffer;
    
    // Den Unicode-String kannst du mit
    MessageBoxW( NULL, Variant.bstr /*bzw strBuffer*/, NULL, 0 );
    // ausgeben lassen.
    

    Keine Angst: Hast alles richtig verstanden 🤡 👍

    Der Typ VARIANT ist ein union-Typ. Gibts etliche Tutorials für, is auch ganz easy 🙂



  • Danke, jetzt läufts!

    char cURL[]="www.google.ch";
    WCHAR strBuffer[100];
    MultiByteToWideChar(CP_ACP, 0, cURL, -1, strBuffer, sizeof(strBuffer));
    
    //VARIANT Variant;
    //Variant.vt = VT_BSTR;
    //Variant.bstrVal = strBuffer; 
    
    pIwb->Navigate(strBuffer,0,0,0,0);
    

    Mir ist was aufgefallen:
    1.) Navigate2 war offensichtlich die falsche Funktion. Mit Navigate geht es hingegen.
    2.) VARIANT braucht es gar nicht. Eine Typenumwandlung reicht anscheinend vollkommen aus.

    Wenn ich das richtig verstanden habe kann man mit VARIANT verschiedene Arten von Werten speichern, ohne explizit eine Typenbezeichnung wie int, char usw. zu benutzen?

    Welche Bücher zum Thema ActiveX, DLL in Verbindung mit WinAPI und C sind empfehlenswert?
    Ich arbeite momentan mit dem Buch "Windows-Programmierung" von Petzold, welches ich sehr gut finde.

    Grüsse,
    Sotares



  • Sotares schrieb:

    Wenn ich das richtig verstanden habe kann man mit VARIANT verschiedene Arten von Werten speichern, ohne explizit eine Typenbezeichnung wie int, char usw. zu benutzen?

    Ja, so ist es gedacht.
    Im Grunde speichert VARIANT aber 2 Variablen, einmal vt und eine "undefinierte". Du weißt ja sicherlich, dass Variablen im Arbeitsspeicher liegen und eine bestimmte Menge an Platz verbrauchen (z.B. 1, 2, 4 oder 8 Bytes sind typisch).
    Die Variablen spricht man im Programm mit einem Namen an, der Compiler legt jede Variable an einer Stelle im Speicher ab, die er sich merkt. Wenn du die Variable ansprichst, weiß der Compiler durch ihren Namen, welche Stelle im Arbeitsspeicher er verändern/auslesen soll.
    Unions funktionieren so, dass eine Stelle im Arbeitsspeicher durch mehrere verschiedene Namen angesprochen werden kann.
    Man ziehe sich folgenden Code rein:

    union TypUnion
    {
        int i;
        int j;
    };
    TypUnion Bla;
    Bla.i = 10;
    // Bla.j ist jetzt auch 10, da mit Bla.j derselbe Speicher
    // angesprochen wird wie mit Bla.i.
    

    Die Union oben ist nur 4 Byte groß, hat also nur die Größe von einem int (und ist relativ sinnlos).
    Wenn die Union verschieden große Typen beinhaltet, wie VARIANT, hat die Union bzw. der Speicherbereich die Größe des größten Typs der Union.
    Bei VARIANT gibt es den Member "vt", damit man weiß, welchen Typs die Daten in der Union nun sind. Anhand der Daten im Speicher weißt du ja nicht, ob es sich um einen String oder int oder sonstwas handelt...

    Hoffe habs anschaulich erklärt,
    Grüße



  • Danke für die ausfürliche Erklärung!
    Wo in der Praxis macht es Sinn, den Wert einer Variable in einem Union zu ändern, um danach die restlichen Variablen in diesem Union ebenfalls mit diesem Wert zur Vefügung zu haben?

    Oder ist dies einfach nur aus der Sicht der optimierten Nutzung des Speichers zu sehen?

    short int A (2 Byte)
    short int B (2 Byte)
    short int C (2 Byte)
    long int D (4 Byte)
    Das Union ist 4 Byte gross.

    Grüsse,
    Sotares



  • Sotares schrieb:

    Wo in der Praxis macht es Sinn, den Wert einer Variable in einem Union zu ändern, um danach die restlichen Variablen in diesem Union ebenfalls mit diesem Wert zur Vefügung zu haben?

    Verschiedene Variablen vom gleichen Typ in einer Union hat absolut keinen Sinn.
    Es ist aber von Nutzen, wie es VARIANT ja macht. Wenn dort die BSTR-Variante gesetzt wurde, kannst du diese explizit ansprechen.
    Eine andere Möglichkeit für die VARIANT-Struktur wäre eine solche:

    struct VARIANT
    {
        int WhichType;
        double Variable;
    };
    
    VARIANT SollStringSpeichern;
    SollStringSpeichern.WhichType  = VT_STR;
    reinterpret_cast<char**>(&SollStringSpeichern.Variable)[0] = "lalala";
    

    Man sieht ja wie umständlich das wäre! Aus Compilersicht hat es null Nutzen, nur für uns Programmierer ist es erleichternd, wenn eine Speicherstelle je nach Situation als anderer Variablentyp genutzt werden kann.



  • Danke, das war sehr informativ.

    Grüsse,
    Sotares


Anmelden zum Antworten