Acquista i nostri libri consigliati su Amazon.it
+ Rispondi al messaggio
Visualizzazione dei risultati da 1 a 2 su 2

Aprire pagina specifica Internet Explorer istanza aperta, in una nuova istanza IE

  1. #1
    Angelo_Tbp non è in linea Novello
    Buona sera, in qusti tempi difficili, rimanendo a casa per molte ore mi sono potuto riavvicinare al tipo di programmazione che a me piace... saluto tutti e vengo al 3d

    ...comprendo che l'oggetto sicuramente apparirà criptico e mi scuso in anticipo nel caso non avessi centrato pienamente il sub forum più adatto per gestire il problema in quanto gli argomenti trattati spaziano tra HTML, javascript e in gran parte VBA.

    Sto cercando di automatizzare la lettura di alcune pagine web in modo da poter scrivere i dati letti all'interno di tabelle web "<table>", in altrettante tabelle di access.
    L'automazione avviene mediante l'uso di un oggetto Internet Explorer in una routine VBA che mi legge il codice HTML delle pagine WEB per poi processarlo.

    La struttura DOM delle pagine che leggo ha degli <iframe> annidati (per chi non lo sapesse l'<iframe> mostra al suo interno un'altra pagina web) nei quali riesco a districarmi senza fatica nel leggere e processare il codice HTML.
    ...e tutto si è svolto sempre in maniera egregia finché non mi sono trovato davanti una situazione particolare che mi sta mettendo in difficolta.

    Cercherò di descriverla:
    Nel browser Internet Explorer ho una pagina Web aperta che al suo interno ha un pulsante che mi apre una nuova finestra di tipo modale, che al suo interno ha un <iframe> che ne visualizza un'altra ancora (… che bellezza…).
    Riesco a leggere sia il codice HTML della pagina principale che quello della modale ma non riesco ad accedere a quello della pagina visualizzata nell' <iframe> ed è proprio quello che mi servirebbe... la situazione è diversa da quella di routine nella quale mi districo bene in quanto normalmente non ho mai a che fare con delle finestre di tipo modale che, a quanto pare, sono rognose.

    Se qualche anima pia è desiderosa di aiutarmi fornisco di seguito gli elementi per simulare lo scenario (ma fate una pausa prima :-) )

    Codice HTML della pagina "index html" da salvare sul proprio desktop;
    <head>
        <script type="text/javascript">
            function UpdateFields (newFore, newSur) {
                var forename = document.getElementById ("forename");
                var surname = document.getElementById ("surname");
                forename.value = newFore;
                surname.value = newSur;
            }
    
            function ShowModal () {
                var forename = document.getElementById ("forename");
                var surname = document.getElementById ("surname");
    
                var sharedObject = {};
                sharedObject.forename = forename.value;
                sharedObject.surname = surname.value;
                
                if (window.showModalDialog) {
                    var retValue = showModalDialog ("modal.htm", sharedObject, "dialogHeight=600px; dialogWidth=200px;edge=sunken;help=no;resizable=yes;status=no;scroll:no");
                    
    		if (retValue) {
                        UpdateFields (retValue.forename, retValue.surname);
                    }
                }
                else {
                        // for similar functionality in Opera, but it's not modal!
                    var modal = window.open ("modal.htm", null, "dialogHeight=600px;dialogWidth=px;edge=sunken;help=no;resizable=yes;status=no;scroll:no", null);
                    modal.dialogArguments = sharedObject;
                }
            }
        </script>
    </head>
    
    <body>
        Forename: <input type="text" id="forename" value="Alan"/><br/>
        Surname: <input type="text" id="surname" value="Smith"/>
        <br/><br/>
        <button onclick="ShowModal ()">Edit the fields with a modal dialog!</button>
    </body>
    
    Codice HTML della pagina "modal.htm" da salvare sul proprio desktop;
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>Modal dialog sample</title>
        <script type="text/javascript">
            function Init () {
                var sharedObject = window.dialogArguments;
    
                var forename = document.getElementById ("forename");
                var surname = document.getElementById ("surname");
                forename.value = sharedObject.forename;
                surname.value = sharedObject.surname;
            }
    
            function OnOK () {
                var forename = document.getElementById ("forename");
                var surname = document.getElementById ("surname");
    
                if (window.showModalDialog) {
                    var sharedObject = {};
                    sharedObject.forename = forename.value;
                    sharedObject.surname = surname.value;
    
                    window.returnValue = sharedObject;
                }
                else {
                        // if not modal, we cannot use the returnValue property, we need to update the opener window
                    window.opener.UpdateFields (forename.value, surname.value);
                }
                window.close ();
            }
    
            function OnCancel () {
                window.close ();
            }
        </script>
    
    <body onload="Init ();">
        Forename: <input type="text" id="forename"/><br/>
        Surname: <input type="text" id="surname"/>
        <br/><br/>
        <button onclick="OnOK ()">OK</button> <button onclick="OnCancel ()">Cancel</button>
        <iframe id="nomeID" name="nomeID" src="index2.html" scrolling="no" align="left" MARGINHEIGHT="0" MARGINWIDTH="0" frameborder="0" width="100%" height="100%"></iframe>
        
    </body>
    </html>
    
    Codice HTML della pagina "index2.html" da salvare sul proprio desktop (in realtà questa può essere una qualsiasi pagina.. è ininfluente);
    <html>
    <script language="javascript">
    function openwindow()
    {
    retval=window.showModalDialog("pagina.htm")
    document.getElementById('text1').value=retval
    }
    </script>
    <body>
    <form name=frm>
    <input name=text1 type=text>
    <input type=button onclick="javascript:openwindow()" value="Open window..">
    </form>
    </body>
    </html>
    
    Codice VBA da scrivere nel modulo di una form access nella quale posizionerete un pulante chiamato 'Comando_0'
    Option Explicit
    
    ' Requires: VBA project reference to "Microsoft HTML Object Library"
    'https://stackoverflow.com/questions/54318737/automating-the-html-document-in-an-ie-web-dialog-window
    
    Private Const SMTO_ABORTIFHUNG = &H2
    Private Const GW_CHILD = 5
    Private Const GW_HWNDNEXT = 2
    
    Private Type UUID
       Data1 As Long
       Data2 As Integer
       Data3 As Integer
       Data4(0 To 7) As Byte
    End Type
    
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    
    Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
        (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
    
    Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" _
        (ByVal hWnd As Long) As Long
    
    Private Declare Function GetWindow Lib "user32" _
        (ByVal hWnd As Long, ByVal wCmd As Long) As Long
    
    Private Declare Function IsWindowVisible Lib "user32" _
        (ByVal hWnd As Long) As Boolean
    
    Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
        (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
    
    Private Declare Function RegisterWindowMessage Lib "user32" _
         Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long
    
    Private Declare Function SendMessageTimeout Lib "user32" _
       Alias "SendMessageTimeoutA" ( _
       ByVal hWnd As Long, _
       ByVal msg As Long, _
       ByVal wParam As Long, _
       lParam As Any, _
       ByVal fuFlags As Long, _
       ByVal uTimeout As Long, _
       lpdwResult As Long) As Long
    
    Private Declare Function ObjectFromLresult Lib "oleacc" ( _
       ByVal lResult As Long, _
       riid As UUID, _
       ByVal wParam As Long, _
       ppvObject As Any) As Long
    
    Sub DialogDemo()
        Const DLG_TITLE = "Modal dialog sample" '<< the dialog title
        Dim Doc As IHTMLDocument
    
        Set Doc = GetIEDialogDocument(DLG_TITLE)
    
        If Not Doc Is Nothing Then
            Debug.Print Doc.body.innerHTML
        Else
            MsgBox "Dialog Window '" & DLG_TITLE & "' was not found!", vbOKOnly + vbExclamation
        End If
    End Sub
    
    'Given an IE dialog window title, find the window and return a reference
    '   to the embedded HTML document object
    Function GetIEDialogDocument(dialogTitle As String) As IHTMLDocument
        Dim lhWndP As Long, lhWndC As Long, Doc As IHTMLDocument
        'find the IE dialog window given its title
        If GetHandleFromPartialCaption(lhWndP, dialogTitle) Then
            Debug.Print "Found dialog window - " & dialogTitle & "(" & TheClassName(lhWndP) & ")"
            lhWndC = GetWindow(lhWndP, GW_CHILD)  'Find Child
            If lhWndC > 0 Then
                If TheClassName(lhWndC) = "Internet Explorer_Server" Then
                    Debug.Print "HWND PARENT: ", lhWndP
                    Debug.Print "HWND CHILD: ", lhWndC
                    Set Doc = IEDOMFromhWnd(lhWndC)
                End If
            End If
        Else
            Debug.Print "Window '" & dialogTitle & "' not found!"
        End If
        Set GetIEDialogDocument = Doc
    End Function
    
    ' IEDOMFromhWnd
    ' Returns the IHTMLDocument interface from a WebBrowser window
    ' hWnd - Window handle of the control
    Function IEDOMFromhWnd(ByVal hWnd As Long) As IHTMLDocument
        Dim IID_IHTMLDocument As UUID
        Dim hWndChild As Long
        Dim lRes As Long
        Dim lMsg As Long
        Dim hr As Long
    
        If hWnd <> 0 Then
    
            lMsg = RegisterWindowMessage("WM_HTML_GETOBJECT") ' Register the message
            SendMessageTimeout hWnd, lMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, lRes ' Get the object pointer
    
            If lRes Then
                With IID_IHTMLDocument ' Initialize the interface ID
                    .Data1 = &H626FC520
                    .Data2 = &HA41E
                    .Data3 = &H11CF
                    .Data4(0) = &HA7
                    .Data4(1) = &H31
                    .Data4(2) = &H0
                    .Data4(3) = &HA0
                    .Data4(4) = &HC9
                    .Data4(5) = &H8
                    .Data4(6) = &H26
                    .Data4(7) = &H37
                End With
                ' Get the object from lRes (note - returns the object via the last parameter)
                hr = ObjectFromLresult(lRes, IID_IHTMLDocument, 0, IEDOMFromhWnd)
            End If
       End If 'hWnd<>0
    End Function
    
    'utilty function for getting the classname given a window handle
    Function TheClassName(lhWnd As Long)
        Dim strText As String, lngRet As Long
        strText = String$(100, Chr$(0))
        lngRet = GetClassName(lhWnd, strText, 100)
        TheClassName = Left$(strText, lngRet)
    End Function
    
    Private Function GetHandleFromPartialCaption(ByRef lWnd As Long, _
                                                 ByVal sCaption As String) As Boolean
        Dim lhWndP As Long, sStr As String
    
        GetHandleFromPartialCaption = False
        lhWndP = FindWindow(vbNullString, vbNullString) 'PARENT WINDOW
        Do While lhWndP <> 0
            sStr = String(GetWindowTextLength(lhWndP) + 1, Chr$(0))
            GetWindowText lhWndP, sStr, Len(sStr)
            sStr = Left$(sStr, Len(sStr) - 1)
            If Len(sStr) > 2 Then
                If UCase(sStr) Like "*ARG*" Then Debug.Print sStr
            End If
            If InStr(1, sStr, sCaption) > 0 Then
                GetHandleFromPartialCaption = True
                lWnd = lhWndP
                Exit Do
            End If
            lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
        Loop
    End Function
    
    Private Sub Comando0_Click()
        DialogDemo
    End Sub
    
    all'inizio del modulo della form ho scritto i riferimenti web dove ho preso il codice e i riferimenti necessari

    Procedimento di simulazione:
    1. Creare i file "index.html", "modal.htm" e "index2.html" (va bene anche il notepad purché quando salvate con nome scriviate "nome.html" compresi i doppi apici.
    2. tasto destro su index.html e scegliere apri con -> internet explorer (E' importante aprire con IE perchè è con questo browser che ho problemi e non posso usarne altri);
    3. se richiesto dalla pagina, abilitare il contenuto activex;
    4. cliccare sul pulsante "edit the filed...." e si aprira la finestra modale incriminata che a video (maledetta lei!!!) mostra correttamente anche il contenuto dell'iframe.
    5. non chiudere internet explorer e, dopo aver aperto access, premere il pulsante Command_0 della form di access.

    output del debug che ottengo quando premo il pulsante Command_0
    Window 'Modal dialog sample' not found!
    Found dialog window - Modal dialog sample(Internet Explorer_TridentDlgFrame)
    HWND PARENT:   3934384 
    HWND CHILD:    2689912 
    
        Forename: <input id="forename" type="text"><br>
        Surname: <input id="surname" type="text">
        <br><br>
        <button onclick="OnOK ()">OK</button> <button onclick="OnCancel ()">Cancel</button>
        <iframe name="frameWinModale_contenitore" width="100%" height="100%" align="center" id="frameWinModale_contenitore" src="index2.html" frameborder="0" marginwidth="0" marginheight="0" scrolling="yes" bgcolor="#F0F8FF">
            </iframe>
    
    come potete notare la parte finale dell'output è quella dell'<iframe> in cui si evince il riferimento alla pagina index.html2 ma non ne mostra il contenuto quindi ho pensato che se riuscissi a passare la finestra modale per intero in una nuova istanza di internet explorer forse riuscirei a districarmi nuovamente bene in quanto in teoria non dovrebbe più essere di tipo modale.
    Nel debug sono mostrati i HWND della finestra IE parent e HWND di quella modale quindi se esistesse un modo di sfruttare il 'numero magico' per far passare la finestra modale in una nuova istanza IE forse risolvereì...
    ho provato con 'SetWindowPos' e "showWindow' ma non ho cavato un ragno dal buco... qualcuni riesce a illuminarmi ?... un piccolo suggerimento?
    Ultima modifica di Angelo_Tbp; 09-04-2020 00:23  Motivo: Cambio Titolo 3D a seguito risoluzione dello stesso.

  2. #2
    Angelo_Tbp non è in linea Novello
    Devo scrivere più spesso in questo forum :-) porta bene!!!

    Come spesso accade nello scrivere ci si costringe a riflettere e talvolta accade di autoilluminarsi.

    Per leggere il contenuto della pagina HTML nell'iframe incriminato basta cambiare la riga della funzione 'GetIEDialogDocument':
    Set Doc = IEDOMFromhWnd(lhWndC)
    
    con
    Set Doc = IEDOMFromhWnd(lhWndC).getElementById("nomeID").contentWindow.Document
    
    Ho risolto spero possa essere utile a qualcun altro.

+ Rispondi al messaggio

Potrebbero interessarti anche ...

  1. Risposte: 0
    Ultimo Post: 12-01-2017, 16:30
  2. Aprire file pdf a pagina specifica
    Da gianni90 nel forum Microsoft Word
    Risposte: 17
    Ultimo Post: 13-12-2010, 17:34
  3. [Access] istanza excel aperta
    Da dodo47 nel forum Microsoft Excel
    Risposte: 5
    Ultimo Post: 02-02-2010, 08:26
  4. Errore in istanza excel su pagina asp
    Da misonsan nel forum ASP 3, ASP .Net
    Risposte: 0
    Ultimo Post: 08-03-2009, 21:08
  5. [MsSQL] nuova istanza
    Da niclo nel forum Microsoft SQL Server
    Risposte: 2
    Ultimo Post: 08-06-2008, 12:07