Très intéressant à propos de SHFILEOPSTRUCT et SHFileOperation

Le
Jean-marc
Hello tous,

voici une info amusante et intéressante.

Suite au posts de Sergio, j'ai regardé d'un peu près
le problème rencontré avec l'API SHFileOperation et en
particulier avec le test de la valeur de retour
fAnyOperationsAborted.

Voici la structure et la déclaration :

Private Type SHFILEOPSTRUCT
hwnd As Long
wFunc As Long
pFrom As String
pTo As String
fFlags As Integer
fAnyOperationsAborted As Boolean
hNameMappings As Long
lpszProgressTitle As String
End Type

Il est donc clair que fAnyOperationsAborted est un Booléen.

Or Sergio avait un problème car il testait l'annulation comme cela:

If FileOperation.fAnyOperationsAborted = True Then
' Operation annulée, etc.

Et ceci ne fonctionnait PAS.

Pour ma part, j'ai testé en écrivant comme ceci :

If FileOperation.fAnyOperationsAborted Then
' Operation annulée, etc.

Et ça fonctionne.

Mais il y a un problème, car ces 2 formes sont supposées être 100%
identiques.

J'ai donc investigué d'un peu près, et j'ai trouvé.

En cas d'annulation, l'API SHFileOperation écrit dans
fAnyOperationsAborted la valeur '1', et non pas '-1' qui est la
représentation habituelle de True en VB. (C'est probablement parceque
l'API est écrite en C, qu'en C il n'y a pas de Booléens et que le type
BOOL est en fait un simple int et que le programmeur a écrit 1 pour
vrai, ce qui est légitime en C).

On a donc un paradoxe amusant, qui était
que:
debug.print FileOperation.fAnyOperationsAborted
donne : True

Mais, et c'est la le truc rigolo :

debug.print (FileOperation.fAnyOperationsAborted = True)
donne : False

Pas évident de trouver l'erreur, car même sous Debugger,
on a du mal à saisir pourquoi 2 valeurs "True" ne sont pas
égales


Conclusion: quand on manipule des booléens, il vaut mieux écrire
des choses comme :

If (Condition) Then
'

plutot que

If (Condition = True) Then
'

On le savait déjà, mais voila un exemple parlant des
bénéfices de cette forme d'écriture.

On est toujours dépendant du Fait que FALSE est représentée par
Zéro, mais on est plus dépendant de la représentation de True.

Finalement, une autre façon de voir les choses est de dire que
comme les API n'ont pas vraiment de type Booléen, on remplace
dans les déclarations tous les Booleéens par des entiers, par exemple
comme ceci:

Private Type SHFILEOPSTRUCT
hwnd As Long
wFunc As Long
pFrom As String
pTo As String
fFlags As Integer
fAnyOperationsAborted As Integer ' <= ICI ENTIER
hNameMappings As Long
lpszProgressTitle As String
End Type

et on teste toujours en considérant uniquement que FALSE = 0
et toutes les autres valeurs sont true, ce qui donne :

If FileOperation.fAnyOperationsAborted <> 0 Then
' annulé

ou tout simplement

If FileOperation.fAnyOperationsAborted Then
' annulé

Comme ceci, on est tranquille.

Voila, bon dimanche à tous !


--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
FAQ VB: http://faq.vb.free.fr/
mailto: remove '_no_spam_' ; _no_spam_jean_marc_n2@yahoo.fr
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Jacques93
Le #15371831
Bonjour jean-marc,
Jean-marc a écrit :

Je profite de ce fil, excellent au demeurant, pour signaler que de
manière similaire à Patrick BASTARD, je ne vois pas ta réponse datée du
14/02/2008, ni celle d'aujourd'hui, en passant par le serveur MS.

Je vois bien ton dernier message, auquel je répond ici, et ceux des fils
Filtre BF (15/02/2008) et SHFileOperation (16/02/2008).

Sur les serveurs Orange et Free, ces messages apparaissent bien !

Etonnant non ?

--
Cordialement,

Jacques.
Jean-marc
Le #15371821
Jacques93 wrote:

Bonjour jean-marc,



Hello Jacques,

Jean-marc a écrit :

Je profite de ce fil, excellent au demeurant, pour signaler que de
manière similaire à Patrick BASTARD, je ne vois pas ta réponse datée
du 14/02/2008, ni celle d'aujourd'hui, en passant par le serveur MS.

Je vois bien ton dernier message, auquel je répond ici, et ceux des
fils Filtre BF (15/02/2008) et SHFileOperation (16/02/2008).

Sur les serveurs Orange et Free, ces messages apparaissent bien !



Oui très curieux.

Sur Google Groups, tout apprarait, à la bonne date et heure de surcroit:
http://groups.google.fr/group/microsoft.public.fr.vb/browse_thread/thread/bdb2cca392664919/94fc1f0fcedfa6eb#94fc1f0fcedfa6eb

J'utilise aussi 2 machines (une perso et une au boulot) sur lesquelles
je lis les news depuis (news.skynet.be) et avec ce provider,
tout fonctionne bien .. Très curieux, en effet !

Bon dimanche !

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
FAQ VB: http://faq.vb.free.fr/
mailto: remove '_no_spam_' ;
Jacques93
Le #15371811
Jean-marc a écrit :
Jacques93 wrote:

Bonjour jean-marc,



Hello Jacques,

Jean-marc a écrit :

Je profite de ce fil, excellent au demeurant, pour signaler que de
manière similaire à Patrick BASTARD, je ne vois pas ta réponse datée
du 14/02/2008, ni celle d'aujourd'hui, en passant par le serveur MS.

Je vois bien ton dernier message, auquel je répond ici, et ceux des
fils Filtre BF (15/02/2008) et SHFileOperation (16/02/2008).

Sur les serveurs Orange et Free, ces messages apparaissent bien !



Oui très curieux.

Sur Google Groups, tout apprarait, à la bonne date et heure de surcroit:
http://groups.google.fr/group/microsoft.public.fr.vb/browse_thread/thread/bdb2cca392664919/94fc1f0fcedfa6eb#94fc1f0fcedfa6eb

J'utilise aussi 2 machines (une perso et une au boulot) sur lesquelles
je lis les news depuis (news.skynet.be) et avec ce provider,
tout fonctionne bien .. Très curieux, en effet !



Voici ce que j'obtiens avec news.microsoft.com, news.orange.fr et
news.free.fr :

http://cjoint.com/?crlSnp4ij2

ici avec ThunderBird, mais c'est pareil avec OE.

Seule particularité que j'ai vue, le message de Patrick est crossposté
sur microsoft.public.fr.vb et microsoft.public.fr.excel, sans FU2, mais
bon ...

Bon dimanche !



A toi aussi.

--
Cordialement,

Jacques.
tking
Le #15371801
Jean-marc a émis l'idée suivante :
Hello tous,



(snip)

Voila, bon dimanche à tous !




Très intéressant et éclairant à lire, merci beaucoup et bon dimanche.
Patrice Henrio
Le #15371791
tking a écrit :
Jean-marc a émis l'idée suivante :
Hello tous,



(snip)

Voila, bon dimanche à tous !




Très intéressant et éclairant à lire, merci beaucoup et bon dimanche.




Ce post démontre très clairement que si un type booléen existe il faut
l'utiliser tel qu'il est.
Pour ma part If <variable booleéenne> = true me fait hurler.
Jean-marc
Le #15371781
Patrice Henrio wrote:

Ce post démontre très clairement que si un type booléen existe il faut
l'utiliser tel qu'il est.
Pour ma part If <variable booleéenne> = true me fait hurler.



Tout à fait, à tel point que dans le langage courant, on dit:

SI il fait beau demain, j'irais me promener
et pas:
SI il fait beau demain EST VRAI, j'irais me promener

Les formes :
If ... = True et If ... = False
sont des hérésies sémantiques. Elles sont autorisées par
pur souci d'orthogonalité syntaxique, mais c'est tout.

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
FAQ VB: http://faq.vb.free.fr/
mailto: remove '_no_spam_' ;
parci
Le #15371691
On Sun, 17 Feb 2008 10:54:32 +0100, "Jean-marc"

//...//


Finalement, une autre façon de voir les choses est de dire que
comme les API n'ont pas vraiment de type Booléen, on remplace
dans les déclarations tous les Booleéens par des entiers, par exemple
comme ceci:

Private Type SHFILEOPSTRUCT
hwnd As Long
wFunc As Long
pFrom As String
pTo As String
fFlags As Integer
fAnyOperationsAborted As Integer ' <==== ICI ENTIER
hNameMappings As Long
lpszProgressTitle As String
End Type

et on teste toujours en considérant uniquement que FALSE = 0
et toutes les autres valeurs sont true, ce qui donne :

If FileOperation.fAnyOperationsAborted <> 0 Then
' annulé

ou tout simplement

If FileOperation.fAnyOperationsAborted Then
' annulé

Comme ceci, on est tranquille.



Presque Jean-Marc, parce que si on veut aussi afficher un texte
personnalisé pendant l'opération avec lpszProgressTitle (plus le flag
FOF_SIMPLEPROGRESS), ça ne marchera pas pour une question d'alignement
des données.

Voir par exemple :
http://www.softcircuits.com/dl/vbsrc/shfileop.zip
Jacques93
Le #15371681
Bonjour parci,
parci a écrit :
On Sun, 17 Feb 2008 10:54:32 +0100, "Jean-marc"

//...//


Finalement, une autre façon de voir les choses est de dire que
comme les API n'ont pas vraiment de type Booléen, on remplace
dans les déclarations tous les Booleéens par des entiers, par exemple
comme ceci:

Private Type SHFILEOPSTRUCT
hwnd As Long
wFunc As Long
pFrom As String
pTo As String
fFlags As Integer
fAnyOperationsAborted As Integer ' <==== ICI ENTIER
hNameMappings As Long
lpszProgressTitle As String
End Type

et on teste toujours en considérant uniquement que FALSE = 0
et toutes les autres valeurs sont true, ce qui donne :

If FileOperation.fAnyOperationsAborted <> 0 Then
' annulé

ou tout simplement

If FileOperation.fAnyOperationsAborted Then
' annulé

Comme ceci, on est tranquille.



Presque Jean-Marc, parce que si on veut aussi afficher un texte
personnalisé pendant l'opération avec lpszProgressTitle (plus le flag
FOF_SIMPLEPROGRESS), ça ne marchera pas pour une question d'alignement
des données.

Voir par exemple :
http://www.softcircuits.com/dl/vbsrc/shfileop.zip




Pour une fois que jean-marc ne veux pas jeter des octets par la fenêtre ;-)

En VB le type Integer prend 2 octets (16 bits), et le type Long 4 octets
(32 bits). Par contre en C/C++, dans les dernières versions, en tout cas
depuis la 6.0, les types int et long sont tous les deux sur 32 bits, et
BOOL est défini comme étant un int, donc 32 bits. Dans la structure il
faut mettre, je pense :

fAnyOperationsAborted As Long ' <==== ICI LONG

sinon effectivement on a un décalage des données qui suivent.

A noter que en C/C++, on peut forcer le ré-alignement des données sur un
multiple de deux, ou au contraire forcer la contiguïté des données, avec
la directive de compilation :

#pragma pack (4)

par exemple, qui force le ré-alignment sur le prochain multiple de 4.
Mais cette possibilité n'existe pas en VB.

--
Cordialement,

Jacques.
Jean-marc
Le #15371671
parci wrote:
On Sun, 17 Feb 2008 10:54:32 +0100, "Jean-marc"




Presque Jean-Marc, parce que si on veut aussi afficher un texte
personnalisé pendant l'opération avec lpszProgressTitle (plus le flag
FOF_SIMPLEPROGRESS), ça ne marchera pas pour une question d'alignement
des données.



Très juste!

Et de fait (comme le signale Jacques d'ailleurs), le type Long va
convenir.

Le petit module de classe dans ton zip fait comme ça d'ailleurs.
(très bien le module de classe, très sympa).

Merci en tout cas de cette intéressante remarque !

Bon Aprèm :-)

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
FAQ VB: http://faq.vb.free.fr/
mailto: remove '_no_spam_' ;
parci
Le #15371621
On Sun, 17 Feb 2008 16:55:41 +0100, "Jean-marc"

parci wrote:
On Sun, 17 Feb 2008 10:54:32 +0100, "Jean-marc"




Presque Jean-Marc, parce que si on veut aussi afficher un texte
personnalisé pendant l'opération avec lpszProgressTitle (plus le flag
FOF_SIMPLEPROGRESS), ça ne marchera pas pour une question d'alignement
des données.



Très juste!

Et de fait (comme le signale Jacques d'ailleurs), le type Long va
convenir.



En fait, du moment qu'on réaligne les données sur 30 octets, Long ou
Integer convient.

Dans l'exemple, il suffit d'écrire :
ReDim ByteArray(0 To 29) As Byte

Le problème vient - si j'ai bien compris - qu'en VB le ré-alignement
des données est forcé sur le prochain multiple de 4. Ce qui fait que
SHFILEOPSTRUCT déclaré comme suit, occupe en fait 32 octets.

Private Type SHFILEOPSTRUCT
hwnd As Long
wFunc As Long
pFrom As String
pTo As String
fFlags As Integer
fAnyOperationsAborted As Long
hNameMappings As Long
lpszProgressTitle As String
End Type

Or ce n'est visiblement pas le cas avec cette dll.
Le plus simple aurait été de déclarer le flag en DWORD plutôt qu'en
WORD (ça m'a l'air d'être le seul cas dans shellapi).

Le petit module de classe dans ton zip fait comme ça d'ailleurs.
(très bien le module de classe, très sympa).



Ce n'est mon zip, mais le code est très pratique, en effet. Et c'est
un bon exemple pour convertir une structure en tableau d'octets.

Bonne soirée à vous deux (et aux autres).
Publicité
Poster une réponse
Anonyme