Utilitaires
Scripts
Divers
Jeux
Rechercher
Quillevere.net
Réflexions informatiques

Interagir avec les fichiers du presse-papiers

18/08/2020
VB.Net

Ce code VB.Net permet d'accéder aux données du presse-papiers de Windows, sur la partie fichiers, pour stocker des fichiers à couper ou à copier et pour récupérer (coller) les fichiers stockés dans le presse-papiers, en gérant la copie ou le déplacement.

La fonction isFichiersPresents indique si des fichiers ont été copiés dans le presse-papiers, afin d'activer ou non un éventuel menu "Coller".

' Couper/copier l'objet fichier dans le presse-papier Windows
 Public Sub couperCopierFichiersVersPressePapiers(ByVal bCouper As Boolean, ByVal listeFichiers() As String)
    Clipboard.Clear()
    Dim doFichiers As New DataObject(DataFormats.FileDrop, listeFichiers)
    doFichiers.SetData("Preferred Dropeffect", New MemoryStream(BitConverter.GetBytes(CInt(IIf(bCouper, DragDropEffects.Move, DragDropEffects.Copy)))))
    Clipboard.SetDataObject(doFichiers, False)
 End Sub

 ' Indique si un fichier a été coupé/copié dans le presse-papiers
Public Function isFichiersPresents() As Boolean
    Dim data As IDataObject = Clipboard.GetDataObject
    isFichierEnMemoire = data.GetDataPresent(DataFormats.FileDrop)
 End Function

' Couper/copier l'objet fichier dans le presse-papier Windows
Public Sub collerFichiersDepuisPressePapiers(ByVal sRepDesti As String)
    Dim data As IDataObject = Clipboard.GetDataObject
    If Not isFichiersPresents() Then Exit Sub

    ' Récupère l'effet copier ou couper
    Dim stream As MemoryStream = CType(data.GetData("Preferred DropEffect", True), MemoryStream)
    Dim iVal As Integer = stream.ReadByte()
    If iVal <> 2 AndAlso iVal <> 5 Then Exit Sub
    Dim bCouper As Boolean = iVal = 2

    ' Parcours les fichiers en mémoire
    For Each sNomFichier As String In data.GetData(DataFormats.FileDrop)
        Dim sNouveauNom As String = Path.Combine(sRepDesti, Path.GetFileName(sNomFichier))
        If bCouper Then
            File.Move(sNomFichier, sNouveauNom)
        Else
            File.Copy(sNomFichier, sNouveauNom)
        End If
    Next
End Sub

Cas des fichiers en bureau à distance

Si le fichier source ou en destination ne provient pas de la même machine, le presse-papiers fonctionne différemment :

  • Le presse-papiers du fichier de la machine source contient un lien vers le fichier
  • Le presse-papiers de la machine destination contient une structure indiquant un flux de fichier (Stream)

Voici une fonction permettant d'identifier que le fichier à coller provient d'un bureau à distance : le presse-papiers contient l'objet FileGroupDescriptorW :

' Indique si un fichier en RDP a été copié ou coupé dans le presse-papiers (depuis un bureau à distance)
Public Function isFichierRDPEnMemoire() As Boolean
    isFichierRDPEnMemoire = Clipboard.GetDataObject.GetDataPresent("FileGroupDescriptorW")
End Function

Il est possible de récupérer la structure des fichiers en mémoire, en utilisant une structure FILEDESCRIPTOR. Cependant, il n'est pas toujours nécessaire de la connaître : le code-ci dessous va permettre de coller le contenu du presse-papiers en faisant intervenir la fonction Coller de Windows. Il ouvre tout d'abord un explorateur sur le chemin cible, appelle la commande Control+V, puis referme l'explorateur une fois la commande terminée.

Malheureusement, il est nécessaire de garder cet explorateur visible : l'envoi de certaines touches (Control, ALT...) ne fonctionne que vers l'application active ouverte avec Sendkeys.

Private Declare Auto Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hwnd As IntPtr, ByRef lpdwProcessId As Integer)As Integer

Private Declare Function GetForegroundWindow Lib "user32.dll" () As IntPtr

' Ouvre un explorateur, colle les fichiers et referme l'explorateur
Public Sub collerAvecExplorateur(ByVal sRepDesti As String)
    Dim myProg As New Process
    With myProg.StartInfo
        .FileName = "explorer.exe"
        .WindowStyle = ProcessWindowStyle.Normal
        .Arguments = "/separate," & sRepDesti
        .CreateNoWindow = False
        .UseShellExecute = True
    End With
    Dim hwndAppliActuelle As System.IntPtr = GetForegroundWindow()

    If myProg.Start() Then
        ' Explorer ouvre un autre processus que le sien, on ne peut donc pas s'appuyer sur l'ID récupéré.
        ' On va retrouver l'ID à partir du changement de fenêtre active
        While GetForegroundWindow() = hwndAppliActuelle
            Application.DoEvents()
        End While
        Dim hwndFenetreExplorer As System.IntPtr = GetForegroundWindow()

        ' Récupère l'id du process, pour vérifier s'il est bien fermé
        Dim iProcessId As Integer
        GetWindowThreadProcessId(hwndFenetreExplorer, iProcessId)
        Thread.Sleep(200) ' Attend la visibilité de la fenêtre
        ' Aucune attente malgré le sendwait
        ' L'utilisation de %{F4} ne ferme pas toujours la fenêtre (si le fichier est volumineux par exemple)
        System.Windows.Forms.SendKeys.SendWait("^v") ' CONTROL + V
        Thread.Sleep(300)

        ' Ferme la fenêtre Explorer ouverte
        Try
            Dim listProcess() As Process = System.Diagnostics.Process.GetProcesses()
            For Each proc As Process In listProcess
                If (proc.Id = iProcessId) Then
                    ' Demande de fermeture du process Explorer
                    proc.WaitForInputIdle()
                    proc.CloseMainWindow()
                    Exit For
                End If
            Next proc
        Catch ex As Exception
            Console.WriteLine(ex.Message)
        End Try
    End If
End Sub
Dernière modification le 24/08/2020 - Quillevere.net

Rechercher sur le site

rss RSS info Informations