Chiudere da Access specifica finestra Windows aperta

di il
17 risposte

Chiudere da Access specifica finestra Windows aperta

Salve a tutti.

Ho la necessità di chiudere automaticamente da una form una determinata finestra di windows, aperta precedentemente con un comando utilizzando un campo testo dove ho la path, in maniera che se l'utente la dimentica aperta, alla fine non si ritrovi con una moltitudine di finestre windows aperte.

Ho cercato in rete ed ho trovato questo codice per Excel sul forum Microsoft il quale però chiude tutte le finestre Windows aperte, e questo non mi piace. L'indirizzo della discussione è questo:

https://answers.microsoft.com/it-it/msoffice/forum/all/chiudere-finestre-di-windows-tramite-vba/71ac8d74-d43e-4145-bc61-a46ec29fa972

Questo è il codice proposto per due soluzioni diverse che pare funzionino entrambe:


Per risolvere la tua domanda, in testa ad un modulo standard, prima di qualsiasi altra routine, incolla il seguente codice:

'=========>>
Option Explicit
Private Declare Function SendMessage Lib "user32" _
                                     Alias "SendMessageA" _
                                     (ByVal hwnd As Long, _
                                      ByVal wMsg As Long, _
                                      ByVal wParam As Long, _
                                      ByRef lParam As Any) As Long

'--------->>
Private Declare Function FindWindow Lib "user32" _
                                    Alias "FindWindowA" _
                                    (ByVal lpClassName As String, _
                                     ByVal lpWindowName As String) As Long

Private Const SC_CLOSE = &HF060&
Private Const WM_SYSCOMMAND = &H112
Private Const EXPLORER_CLASSNAME As String = "CabinetWClass"

'--------->>
Public Sub Tester()
Dim iExplhwnd As Long
      iExplhwnd = FindWindow(EXPLORER_CLASSNAME, vbNullString)

    Do Until Not CBool(iExplhwnd)
        SendMessage iExplhwnd, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&
        iExplhwnd = FindWindow(EXPLORER_CLASSNAME, vbNullString)
    Loop

End Sub
'<<=========

Nelle mie prove ho voluto anche sostituire l'uso di WinExec  con ShellExecute e, pertanto, il codice diventerebbe:

'=========>>
Option Explicit
Declare Function ShellExecute Lib "shell32.dll" Alias _
                              "ShellExecuteA" ( _
                              ByVal hwnd As Long, _
                              ByVal lpOperation As String, _
                              ByVal lpFile As String, _
                              ByVal lpParameters As String, _
                              ByVal lpDirectory As String, _
                              ByVal nShowCmd As Long) _
                              As Long

'--------->>
Private Declare Function SendMessage Lib "user32" _
                                     Alias "SendMessageA" _
                                     (ByVal hwnd As Long, _
                                      ByVal wMsg As Long, _
                                      ByVal wParam As Long, _
                                      ByRef lParam As Any) As Long

'--------->>
Private Declare Function FindWindow Lib "user32" _
                                    Alias "FindWindowA" _
                                    (ByVal lpClassName As String, _
                                     ByVal lpWindowName As String) As Long

Private Const SC_CLOSE = &HF060&
Private Const WM_SYSCOMMAND = &H112
Private Const EXPLORER_CLASSNAME As String = "CabinetWClass"

'--------->>
Public Sub Tester()
Dim iExplhwnd As Long
      iExplhwnd = FindWindow(EXPLORER_CLASSNAME, vbNullString)

    Do Until Not CBool(iExplhwnd)
        SendMessage iExplhwnd, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&
        iExplhwnd = FindWindow(EXPLORER_CLASSNAME, vbNullString)
    Loop

End Sub

'--------->>
Private Sub ApriArchivio()
'Apre Cartella PC
    ShellExecute 0, "Open", "C:\Users\ndj\Documents\", 0, 0, 1
End Sub
'<<=========
È possibile utilizzarlo in qualche maniera su Access modificandolo per chiudere una specifica finestra di Windows, e se sì come?

Questa è roba parecchio complicata, quindi non mi chiedete di applicarmi più di così .

Grazie per un eventuale aiuto .

Alex66

17 Risposte

  • Re: Chiudere da Access specifica finestra Windows aperta

    Non ho capito la domanda...
    Quel codice gira regolarmente su Access 32bit.

    Personalmente penso che prima di usare codice di cui non hai pratica, magari puoi indicarci come hai aperto l'applicativo di cui sopra... e poi si analizza con cognizione di causa.
  • Re: Chiudere da Access specifica finestra Windows aperta

    Ok, quindi VBA Access = VBA Excel. E quindi siamo già a metà dell'opera.

    Allora, ho una form da dove, con un pulsante, utilizzando la path inserita in un txtControl di nome "PATH_ELEMENTO" che ho nella form stessa, se esiste, apro una finestra windows, altrimenti chiedo se si vuole creare e, se sì, la crea e la apre.

    Questo è il codice, che ho preso da altro forum microsoft e modificato per le mie esigenze:
    
    
    Private Sub Pulsante_Cartella_Foto_Elemento_Click()
    
    On Error GoTo errorHandler
    
     Dim strPath As String
     Dim dbp     As Access.CurrentProject
     Dim bool    As Boolean
     
     With Application
        Set dbp = .CurrentProject
     End With
    
     strPath = Me.PATH_ELEMENTO
    
     bool = ((GetAttr(strPath) And vbDirectory) = vbDirectory)
     Shell "explorer.exe " & strPath, vbNormalFocus
    
    
    ext_errorHandler:
        Set dbp = Nothing
        Exit Sub
       
    errorHandler:
        With Err
         Select Case .Number
                Case 53
                        Dim Scelta As Long
                        Scelta = MsgBox("La cartella contenente le foto di questo elemento " & vbCrLf & "della Categoria " & Me.DESCR_CATEGORIA & " non 
                              esiste!!!" & vbCrLf & vbCrLf & "Vuoi crearla?", vbYesNo + vbInformation, "ATTENZIONE!!!")
                        
                        Select Case Scelta
                            
                        Case vbYes
                            MkDir (Left(Me.PATH_ELEMENTO, Len(Me.PATH_ELEMENTO) - 1))
                            Shell "explorer.exe " & Me.PATH_ELEMENTO, vbNormalFocus
                            Exit Sub
                        Case Else
                            Exit Sub
                        End Select
                
                    MsgBox "ERR#" & .Number _
                        & vbNewLine & .Description _
                        , vbOKOnly Or vbCritical
          End Select
        End With
        Resume ext_errorHandler
       
    End Sub
    
    
    Ora, se l'utente non mi chiude la finestra windows, cliccando sulla finestra Access, questa va dietro e, se mi riclicca il pulsante, me la riapre di nuovo, e così via ad libidium. Inoltre se mi esce da quel record e mi riapre la form su un altro record e mi clicca il pulsante, ecc. ecc. ecc.

    Vorrei evitare tutto questo facendo in modo che all'evento su Chiusura, per esempio, mi chiuda anche la finestra windows di cui al "PATH_ELEMENTO". Questo come soluzione ottimale. O magari c'è un modo per rimettere la finestra Windows in primo piano, per ricordare all'utente di chuderla. Se non è possibile metterò un messaggio dove glielo ricordo con le cattive .

    Grazie.

    Alex66
  • Re: Chiudere da Access specifica finestra Windows aperta

    Mah qualche cosa non mi torna... ma non approfondisco... ci sarebbe da capire perché fai aprire una cartella esterna...

    Un codice forse più immediato è questo:

    https://stackoverflow.com/questions/49649663/close-folder-opened-through-explorer-exe

    Adattarlo passando il Path così se ne hai aperti 10 li chiudi tutti...
  • Re: Chiudere da Access specifica finestra Windows aperta

    @Alex ha scritto:


    Mah qualche cosa non mi torna... ma non approfondisco... ci sarebbe da capire perché fai aprire una cartella esterna...

    Un codice forse più immediato è questo:

    https://stackoverflow.com/questions/49649663/close-folder-opened-through-explorer-exe

    Adattarlo passando il Path così se ne hai aperti 10 li chiudi tutti...
    Non mi funziona. Ossia non dà errore ma non chiude le finestre Windows aperte.

    Ho proceduto così:

    Sul pulante Esci della maschera c'è questo codice:
    
    
        Call CloseWindow
        DoCmd.Close acForm, "NomeMaschera", acSaveNo
    
    
    Su un moldulo ho inserito questo codice (ho cambiato il nome controllo in PATH_FORM per renderlo fruibile anche da altre maschere):

    
    
    Option Compare Database
    
    #If VBA7 Then
        Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" _
            (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Long) As LongPtr
    #Else
        Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
            (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long
    #End If
    
    Const WM_SYSCOMMAND = &H112
    Const SC_CLOSE = &HF060
    
    Option Explicit
    
    Public Sub CloseWindow()
        Dim sh As Object
        Set sh = CreateObject("shell.application")
    
        Dim w As Variant
        For Each w In sh.Windows
            'print all locations in the intermediate window
            Debug.Print w.LocationURL
    
            ' select correct shell window by LocationURL
            If w.LocationURL = PATH_FORM Then
                SendMessage w.hWnd, WM_SYSCOMMAND, SC_CLOSE, 0
            End If
        Next w
    End Sub
    
    
    Credo che il problema sia nella riga dell'If.
    Se metto .PATH_FORM mi dà "Errore di compilazione: Riferimento non valido o non qualificato". Cliccando sul bottone [?] mi dice che il punto può essere usato solo con With.
    Se metto """ & PATH_FORM & """, non succede nulla.
    Se metto solo PATH_FORM, non succede nulla.
    Ho inserito anche direttamente la path delle finestre aperte "testoPathCopiatoDaIndirizzoFinestraWindowsEIncollato".

    Credo di non usare la sintassi giusta. O forse c'è dell'altro.

    Grazie per eventuale aiuto.

    Alex66
  • Re: Chiudere da Access specifica finestra Windows aperta

    Scusa ma cosa contiene PATH_FORM?

    Tu visualizzi tutte le cartelle aperte con la

    Debug.Print w.LocationURL

    prendi la url che ti interessa e mettila al posto di PATH_FORM. Dovrà iniziare per "file:///"
  • Re: Chiudere da Access specifica finestra Windows aperta

    oregon ha scritto:


    Scusa ma cosa contiene PATH_FORM?

    Tu visualizzi tutte le cartelle aperte con la

    Debug.Print w.LocationURL

    prendi la url che ti interessa e mettila al posto di PATH_FORM. Dovrà iniziare per "file:///"
    PATH_FORM è il controllo della maschera che contiene l'indirizzo della finestra Windows, ossia, almeno per ora che sto ancora sviluppando: "C:\...".

    Allora ho provato a fare così:
    
            If w.LocationURL = "file:\\" & PATH_FORM Then
    
    
    ma mi dà Errore di compliazione: Variabile non definita e mi evidenzia in azzurro PATH_FORM.

    Ho provato anche a fare così:
    
    
            If w.LocationURL = "file:\\C:\..." Then
    
    
    non dà errore ma non chiude la\e finestra\e windows.

    È sbagliata la sintassi o mi manca un pezzo e non so quale?

    Alex66
  • Re: Chiudere da Access specifica finestra Windows aperta

    Non devi "provare" a fare tante cose senza senso o sbagliate. Devi riflettere e fare la cosa giusta.

    Se PATH_FORM non è definita devi capire cosa fare.

    Alla funzione CloseWindow passa la stringa

    Public Sub CloseWindow(url As String)

    chiamandola dal tuo codice con

    CloseWindow(....)

    mettendo al posto dei puntini il valore del testo contenuto nel controllo e poi usa

    "file:///" & url

    E TI RIPETO ... quando hai aperta la finestra ed esegui

    Debug.Print w.LocationURL

    cosa visualizzi nella finestra di Debug?
  • Re: Chiudere da Access specifica finestra Windows aperta

    oregon ha scritto:


    Non devi "provare" a fare tante cose senza senso o sbagliate. Devi riflettere e fare la cosa giusta.

    Se PATH_FORM non è definita devi capire cosa fare.

    Alla funzione CloseWindow passa la stringa

    Public Sub CloseWindow(url As String)

    chiamandola dal tuo codice con

    CloseWindow(....)

    mettendo al posto dei puntini il valore del testo contenuto nel controllo e poi usa

    "file:///" & url

    E TI RIPETO ... quando hai aperta la finestra ed esegui

    Debug.Print w.LocationURL

    cosa visualizzi nella finestra di Debug?
    Se posiziono il cursore su url di <CloseWindow(url As String)> o su url di <If w.LocationURL = "file:\\" & url Then> mi dà la path di PATH_FORM (il mio controllo nella maschera).
    Se invece lo posiziono su w.LocationURL di <Debug.Print w.LocationURL> o su quello di <If w.LocationURL = "file:\\" & url Then> non mi dà niente.

    Alex66
  • Re: Chiudere da Access specifica finestra Windows aperta

    Esegui il codice e controlla la finestra di Debug! Non usare il cursore quando il programma è fermo o terminato.
  • Re: Chiudere da Access specifica finestra Windows aperta

    oregon ha scritto:


    Esegui il codice e controlla la finestra di Debug! Non usare il cursore quando il programma è fermo o terminato.
    È quello che ho fatto.

    Ho inserito un errore alla riga
    If w.LocationURL = "file:\\" & url Then
    cambiando url in urlx per generare un errore dopo la riga
    Debug.Print w.LocationURL
    in modo che mi si apra debug che giustamente mi dà Errore di compilazione: Variabile non definita.
    Ricorreggo urlx in url e mi dà quello che ho scritto.

    Per miei limiti, non conosco altri modi. Altrimenti, per favore, dimmelo tu quello che devo fare.

    Ciao.

    Alex66
  • Re: Chiudere da Access specifica finestra Windows aperta

    Inserisci un errore? Devi usare il debugger ... usa i breakpoint, ecco cosa devi fare...

    Posta il file zippato, vediamo cosa si capisce direttamente ...
  • Re: Chiudere da Access specifica finestra Windows aperta

    oregon ha scritto:


    Inserisci un errore? Devi usare il debugger ... usa i breakpoint, ecco cosa devi fare...

    Posta il file zippato, vediamo cosa si capisce direttamente ...
    Scusa, prima di preparare il file zippato, dove dovrei fare opera di pulizia per la privacy non indifferente e che poi mi dovresti dire, sempre per favore, come si inserisce nel messaggio, vorrei capire una cosa.

    Ho inserito il breakpoint sulla riga:
    Next w
    che se ci vado sopra mi dà w="Esplora risorse". Il risultato è lo stesso.

    Mi sembra di capire, da profano, che se non mi chiude la finestra, il problema sia che non viene passato alcun valore a w.LocationURL, così che non viene soddisfatta la If e quindi passa alla prossima finestra fino alla fine e non chiude un cavolo di niente, anche se ne ho aperte cinque sulla stessa url.

    Fammi sapere. Grazie.

    Alex66
  • Re: Chiudere da Access specifica finestra Windows aperta

    Il breakpoint mettilo dopo la next w, quando si ferma controlla nella finestra di debug... trovi nella lista il nome della finestra da chiudere?(ovviamente se questa è aperta)
  • Re: Chiudere da Access specifica finestra Windows aperta

    oregon ha scritto:


    Il breakpoint mettilo dopo la next w, quando si ferma controlla nella finestra di debug... trovi nella lista il nome della finestra da chiudere?(ovviamente se questa è aperta)
    Ho attivato la Finestra immediata e inserito il breakpoint alla End Sub.
    Dopo aver eseguito il codice, nella Finestra immediata è comparsa la stringa "file:///NomeFinestraWindowsdellaPATH_FORM", per n volte tante quante è stata aperta.

    Però ho notato che converte gli spazi in "%20" e gli "\" in "/".

    Allora ho inserito una variante "loc" dove faccio il Replace degli spazi e degli "\", modificando così il codice:
    
    
    Public Sub CloseWindow(url As String)
        
        
        Dim loc As Variant
        
        loc = "file:///" & Replace(Replace(url, " ", "%20"), "\", "/")
        'Debug.Print loc
        
        Dim sh As Object
        Set sh = CreateObject("shell.application")
            
        Dim w As Variant
        For Each w In sh.Windows
            'print all locations in the intermediate window
            Debug.Print w.LocationURL
            
            ' select correct shell window by LocationURL
            If w.LocationURL = loc Then
                'Forms![ELEMENTI_SCENICI-Inserimento]!PATH_FORM
                SendMessage w.hWnd, WM_SYSCOMMAND, SC_CLOSE, 0
            End If
        Next w
        
    End Sub
    
    
    ma ancora non funziona.

    Allora ho attivato la riga
    Debug.Print loc
    e la stringa che mi restituisce è identica a quelle di Debug.Print w.LocationURL!!!

    Ho provato anche con una sola finestra aperta. Nada de nada.

    Quale è il problema?


    Alex66
Devi accedere o registrarti per scrivere nel forum
17 risposte