Récupérer une string du ClipBoard

Signaler
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
-
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
-
Violent Ken

Bonjour, j'ai une petite question : comment puis-je récupérer des strings en provenance du ClipBoard ?

Attention, ce n'est pas du texte simple, c'est du texte contenant n'importe quel caractère ASCII. Autrement dit, l'objet ClipBoard de VB ne fonctionne pas (car string terminée par vbNullChar).
Pour les APIs, j'ai bien essayer de faire le tour....sans succès.

Voici la routine que j'ai tenté pour essayer de trouver un format de ClipBoard supportant les strings avec des vbNullChar.... sans succès. Une idée ? Merci, @+



Option Explicit<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /??>






 






Private Declare Function
OpenClipboard Lib "user32" (ByVal hwnd AsLong) AsLong





Private Declare Function
CloseClipboard Lib "user32" () AsLong





Private Declare Function
GetClipboardData Lib "user32" (ByVal wFormat AsLong) AsLong





Private Declare Function
lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString AsLong) AsLong





Private Declare Sub
CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Long, ByVal ByteLen As Long)





Private Declare Function
IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Long) As Long






 






Private

Sub Form_Load()





Dim
x AsLong






   
For x = 0 To 200000






       
If IsClipboardFormatAvailable(x) Then






            MsgBox Len(GetTextD(x)), , x






       
End
If








   
Next
x







End

Sub







Private

Function GetTextD(ByVal lFormat AsLong) AsString






   
Dim hStrPtr AsLong, lLength AsLong, sBuffer AsString






    OpenClipboard Me.hwnd






    hStrPtr = GetClipboardData(lFormat)






   
If hStrPtr <> 0 Then






        lLength = lstrlen(hStrPtr)






       
If lLength > 0 Then






            sBuffer = Space$(lLength)






            CopyMemory ByVal sBuffer, ByVal hStrPtr, lLength






            GetTextD = sBuffer






       
End
If








   
End
If







   

CloseClipboard





End

Function






 

21 réponses

Messages postés
7668
Date d'inscription
samedi 5 novembre 2005
Statut
Membre
Dernière intervention
22 août 2014
24
Bonsoir,

Je viens de lire très rapidement (dois aller au restaurant) et ne suis pas sur d'avoir compris le problème

Pourquoi ne pas enlever tout simplement, avant envoi dans le clipboard, le caractère null
Envoyer ensuite dans le clipboard

A la récupération : si tu veux aussi récupérer le caractère null, tu le rajoutes...

Exemple


Private Sub Command1_Click()
  toto = "toto" & Chr(0)
  pos = InStr(toto, Chr(0))
  If pos > 0 Then toto = Mid(toto, 1, InStr(toto, Chr(0)))
  Clipboard.SetText toto
End Sub


Private Sub Command2_Click()
  toto = Clipboard.GetText  ' et si tu y tiens : .... & chr(0)
  MsgBox toto
End Sub




Je ne verrai ta réponse que dans 2 heures.
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Hum en fait, je code un éditeur hexa et je dois copier vers le ClipBoard les données visualisées. Autrement dit, il peut y avoir n'importe quoi dans la string que je copie vers le clipboard (notamment beaucoup de NullChar) et je ne peux pas prévoir son contenu.
@+
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
70
Salut
Tout dépend sous quel format ont été stockées les données.
Dis-nous depuis quelle application viennent les données afin qu'on teste de notre côté.
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Justement, les données proviennent de mon application.

Je dois faire un équivalent de ClipBoard.SetText "la string obtenue en lisant des bytes dans un fichier"

Le problème c'est que le format texte (implicite) du SetText ne prend pas en compte les caractères comme les vbNullChar.
Et avec les APIs, j'ai pas réussi à faire mieux...
@+
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
70
Re
Bon Ok, le ClipBoard au format texte ne supporte pas les caractères non imprimables.
Mais pourquoi passes-tu par le ClipBoard ?
Passe directement par une variable de type tableau de Bytes ...

C'est une réponse un peu politique :
Dis moi ce qui ne va pas, je te dirais comment t'en passer !
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Bah tout simplement, j'inclus les principales fonctionnalités dans mon application (un éditeur hexadécimal). Autrement dit, j'ai besoin de coder des routines pour que l'utilisateur puisse faire tranquillement
-couper
-copier
-coller
sur les caractères qu'il visualise (parce que pas de problème s'il s'agit de copier les valeurs hexa).

Donc j'utilise le ClipBoard dans sa véritable fonction, c'est à dire un presse papier !

Mais je viens de me rendre compte que Notepad++, pourtant bien foutu, ne gère lui non plus pas les strings comportant des caractères non communs pour les copier/coller.... alors peut être est-ce tout simplement impossible de faire ce que je voudrais dans Windows ??

@+
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
70
Ah Ok, je vois
Donc, ce que l'utilisateur met dans le presse papier ressemble (à l'écran) à des petits carrés ...
En fait, je pense que c'est lors du stockage que Windows épure la chaine et que les caractères non imprimables disparaissent. C'est pour cela que tu n'arrives pas à les lire : ils n'existent pas dans le buffer.
Pour confirmer cela, essaye de faire un "Collage spécial" sous Word, par exemple et teste si tu arrives à les retrouver quand même.
Pas d'autre idée ...
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Oui voilà, tu as saisi ce que je voulais faire.

Tests avec Word :
-le copiage à partir de mon application vers Word ne marche pas (car dès le ClipBoard.SetText la string est tronquée), donc collage spécial idem
-Word ne permet pas de visualiser les NullChar quand on ouvre un fichier binaire avec lui.... ce chacal remplace les &H0 par des &H20 pour esquiver le problème du copier/coller.

Donc au final, il est bel et bien impossible de pouvoir déposer dans le presse papier des strings comportant des &H0 ??? C'est fou quand même !

@+
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
70
Impossible, peut-être pas, mais compliqué.
La seule solution que je verrais serait de Hooker le Clipboard et d'exécuter une Sub à ce moment afin de récupérer le contenu actuellement sélectionné.
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
70
Ah, bah remarque, si tu arrives à détecter un click-droit, tu pourras peut-être rechercher le texte sélectionné à ce moment là ...
Messages postés
1263
Date d'inscription
mardi 11 novembre 2003
Statut
Membre
Dernière intervention
24 juillet 2013
6
Salut Violent_Ken
D'après mon bouquin sur Visual Basic 5 le presse-papier de Windows ( Clipboard) ne peut contenier que du texte ou des données de format graphique (bitmap,etc...). Il n'y a aucune infomation pour le contenu de données binaires brutes ( je parles de ton éditeur héxadécimal)
Je pense qur visual Basic 6.0 a les mêmes réactions que son prédécesseur à ce sujet
Le mieux serait d'utiliser une variable chaine (Pressepapier as string  par exemple).Cela fonctionne très bien car c'est ainsi que je procède dans "Acces Direct Disque" pour les fonctions Copier,Couper,Coller et Supprimer pour l'édition des secteurs.
Je vais chercher pour voir s'il n'y aurait point une autre méthode.
Bon courage et A+

GRENIER Alain[8D]
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Salut Galain.


En admettant que j'arrive à hooker le clipboard, je pourrais copier mes &H0 dans le clipboard et pourquoi pas les récupérer dans mon logiciel, mais la récupération du texte dans un autre éditeur ne fonctionnera pas ?
L'intérêt de copier/couper/coller est aussi de pouvoir transporter les données dans un autre logiciel (Word, Notepad++...etc)

Galain, la méthode de la string apporte le même résultat (mais elle a l'avantage d'être simple) ==> possibilité de faire du copier/coller à l'intérieur même de mon logiciel, mais impossibilité d'exporter ces données dans un autre logiciel par l'intermédiaire du clipboard (sans altérer la string en remplaçant les &H0)

Et je viens de faire une découverte : WinHex, LA référence des éditeurs hexa, ne permet de faire un copier/coller correct qu'à l'intérieur de lui-même. Dès qu'il s'agit de coller dans un autre logiciel (comme Notepad++,qui a l'avantage de faire apparaitre tous les caractères), la string est tronquée au premier nullchar rencontré...

Donc bon, je crois que je vais sagement abandonner (si Winhex ne le permet pas, je vois pas comment je pourrais le permettre), et me contenter de faire le copier/coller avec les nullchars à l'intérieur de mon logiciel ^^

Merci pour votre aide, @+
Messages postés
7668
Date d'inscription
samedi 5 novembre 2005
Statut
Membre
Dernière intervention
22 août 2014
24
Me voilà revenu...

Le vrai problème que je vois, en ce qui me concerne, n'est pas le clipboard lui-même mais, même si l'on restitue le tout (donc avec les caractères NULL, l'exploitation de ce tout !
Car msgbox "toto" & chr(0) & "titi" ====>>> "toto" est basta !
S maintenant, tu pouvais vraiment te contenter de "mettre" puis de "récupérer", sans tenir compte de ce qui précède, c'est à toi de voir !
La solution bête serait alors simplement de :
1) remplacer les caractères NULL par "ce que tu veux"
2) envoyer dans le clipboard
3) récupérer ce qu'il y a dans le clipbboard (sans les NULL, donc)
4) remplacer enfin "ce que tu veux" par NULL

Tu obtiendras ainsi dans la variable de ton choix exactement ce qu'il y avait au départ... mais je vois mal ce que tu pourras ensuite en faire (et là, ce n'est plus un problème de clipboard, mais tout autre chose)

Pour ce qui est de la chaîne "ce que tu veux", tu pourrais la remplacer (car "ce que tu veux" pourrait toujours malencontreusement se trouver dans la chaîne à copier), par, par exemple, "vlt" & nb, ou nb est incrémenté de 1 unité tant que instr(ta_chaine, "vlt" & nb > 0)
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Oui, je sais que les NullChar tronquent la string lors de l'affichage dans un msgbox... mais pour constater le problème, j'utilise la méthode du
s="string avec des nullchars"
clipboard.settext s
s=clipboard.gettext
et là... bah s a été modifiée. Donc c'est bien le clipboard qui pose problème.

4) remplacer enfin "ce que tu veux" par NULL
C'est impossible pour la simple raison que je ne veux pas forcément exploiter le contenu du presse papier dans mon application uniquement, mais aussi dans d'autres logiciels. Alors oui, je peux effectivement avoir une string avec des chr$(0) à l'intérieur même de mon logiciel (mais là autant utiliser la méthode de Galain), mais plus possible de coller mes chr$(0) dans un autre logiciel.

En bref, je ne peux pas contrôler l'opération "coller" dans un logiciel comme Word, WinHex, Notepad++...
@+
Messages postés
1263
Date d'inscription
mardi 11 novembre 2003
Statut
Membre
Dernière intervention
24 juillet 2013
6
Salut violent_Ken me revoila
Les copier,coller,etc... dont tu parles pour ton éditeur héxa  se font bien à partir d'une zone de texte qui réprésentent le contenu  en octets de fichiers,secteurs disque ou autre
J'en conclus que l'utilisateur agit sur un contrôle texte pour ces opérations : ce contrôle texte ne contient que des caractères imprimables (les chiffres héxas 1,2,3,4,5,6,7,8,9,A,B,C,E,F puis l'espace puis le VBCRLF)
Les chr$(0) que tu nous présentes sont les octets nuls et ils sont représentés en vérité par 2 fois le caractère chr$(48) qui représente le chiffre 0
il faut travailler sue les octets en réprésentation héxadécimale et non sur la valeur même de ces mêmes octets : le caractère 0 ( le chiffre 0) serait représenté par les caractères ASCII  3 et 0

Je ne vois pas pourquoi tu ne peux pas utilisr le Clipboard si tu manipules les données sous format texte qui représentent les octets du fichier ou du secteur disque

A+

GRENIER Alain[8D]
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Alors pour ce qui est de la zone de texte, il s'agit en fait d'un Usercontrol assez complexe qui n'est pas constitué par une textbox. Les valeurs copiées sont donc obtenues par lecture directe dans les fichiers/disques/processus.

Par ailleurs, j'ai mis 3 différentes copies
- la copie des valeurs hexa : ce sont les valeurs "00 48 E5 4A" qui seront copiées
- la copie des strings formatées : ce sont des strings qui seront copiées, mais les caractères illisibles sont remplacés par un '.'
- la copie des strings réelles : alors je récupère directement la string depuis le fichier/processus/disque correspondant à la zone sélectionnée et je met cette string (qui peut être constituée par des nullchar) dans le presse papier, en vue d'une copie ultérieure dans mon propre logiciel, ou bien dans un logiciel autre. C'est ce 3eme type de copie qui ne fonctionne pas (puisque le vbnullchar tronque la chaine placée dans le clipboard).
@+
Messages postés
1263
Date d'inscription
mardi 11 novembre 2003
Statut
Membre
Dernière intervention
24 juillet 2013
6
D'accord là je comprends mieux
si j'ai quelque chose de nouveau et d'intéressant je te le ferais savoir
A+ et bon courage

GRENIER Alain[8D]
Messages postés
1812
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
26 octobre 2010
1
Violent Ken

Ok, merci ;)

Mais bon, c'est pas grave si je n'y arrive pas, de toutes façons aucun autre logiciel n'y parvient ^^
@+
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
65
Une fois obtenu le pointeur vers les données, beaucoup d'applis utilisent lstrlen (ou equivalent)...
va s'arreter forcément au premier '\0' rencontré.

doit être possible de passer par un format personalisé...

Renfield
Admin CodeS-SourceS- MVP Visual Basic
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
65
Petites précisions...


ce qui est important, ce ne sont pas les données, mais leur interpretation.
le format texte est très clair :


il s'agit d'une zone mémoire délimitée par un caractère de code 0, je ne t'apprend rien.


il est NORMAL (en format Text) de chercher le premier \0
en effet, on pourrait utiliser GlobalSize pour connaitre la taille de la zone reservée en mémoire
pour stocker nos données... Mais rien n'empeche d'allouer 20 octets et de n'en utiliser que 4...


tes \0 ne sont pas reelement perdues, donc, c'est juste une question d'interpretation, et de
format de clipboard a utiliser.




Le presse papier, est un ensemble de zones mémoires (une par format).
certains formats sont des formats par defaut, dont certains sont accessible via l'objet ClipBoard (Texte, bitmap, RTF...)
Tu peux ajouter de nouveaux formats, soit propres a ton application, soit compréhensibles par les softs de la suite Office,
par exemple.


cas concrêt : lorsque tu copie une plage de cellule depuis Excel, ce dernier créé une bonne vingtaine d'export dans le clipboard,
dans tout un tas de format...
l'application cible choisira ensuite le format quu correspond le mieux.
C'est ainsi qu'on aura un tableau sous word, une image sous Paint, et le texte dans Notepad...




ensuite, tout dépend de ce que tu souhaites faire de tes données :


- copier vers Word, Notepad, etc   pas besoin d'y récupérer tes \0, a priori, qu'en ferai Word ?
  => Copie du texte (ASCII ou HEXA, a toi de voir)
- copier vers une autre instance de ton composant HexEdit
  => Format perso, qui exploite le buffer, sans interpreter les \0 : tu peux récupérer tes
  données sans souci




J'ai un outil, chez moi qui pourrait t'aider, peut etre... il m'a rendu service quelques fois en tous cas.
Je le posterai ce soir.

Renfield
Admin CodeS-SourceS- MVP Visual Basic