OVH Cloud OVH Cloud

GetOpenFileName (encore !)

18 réponses
Avatar
scraper
bonsoir à tous !

j'utilise dans un projet GetOpenFileName avec comme flags
OFN_EXPLORER Or OFN_ALLOWMULTISELECT notamment

ceci afin d'avoir une fenêtre type "explorateur" et la multisélection de
fichiers ...

le problème est que lorsque je sélectionne plusieurs fichiers, le résultat
est de la forme

"strRepertoire" "strFichier1" "srtFichier2" etc ....

et je n'arrive pas à retrouver, à partir de ces infos, le chemin complet du
répertoire ?

j'ai bien spécifié le répertoire initial, mais en cas de changement, comment
retrouver le répertoire sélectionné ?

merci à tous par avance



--

Attention ! Adresse mail invalide ...
Pour me contacter, cliquez sur le lien ci-dessous:
http://scraper.chez.tiscali.fr/contact.htm

scraper

8 réponses

1 2
Avatar
Alain CROS
Bonjour.

Pas besoin de subclasser pour obtenir ce renseignement.

Private Const FNERR_BUFFERTOOSMALL As Long = &H3003
If GetOpenFileNameA(OFN) Then
--Traitement si OK
Else
If CommDlgExtendedError = FNERR_BUFFERTOOSMALL then Msgbox "Buffer too small"
End If

Alain CROS

mais j'ai lu sur le net que si la taille du buffer était trop petite, on
pouvait récupérer la valeur de CommDlgExtendedError()
qui doit alors être à FNERR_BUFFERTOOSMALL ...

j'ai donc essayé ?? en mettant une taille plus petite
mais ça fonctionne pas chez moi ?? j'ai toujours une valeur de retour =0
pour CommDlgExtendedError

j'ai ausis lu qu'il fallait subclasser la fenêtre parent (c'est ça ? :-)
pour intercepter le message ....
j'ai mis en place un hook ... qui doit fonctionner, puisque j'arrive par ce
hook à changer le titre de la fenêtre GetOpenFileName
mais je ne sais pas comment intercepter le message d'erreur pour buffer trop
petit ??

c'est pas que ce soit vraiment vital; mais j'ai merais bien comprendre ?
:-)

merci d'avance


--

Attention ! Adresse mail invalide ...
Pour me contacter, cliquez sur le lien ci-dessous:
http://scraper.chez.tiscali.fr/contact.htm

scraper




Avatar
scraper
Bonjour Alain CROS
(dans news:)
tu nous disais :

Bonjour.

Pas besoin de subclasser pour obtenir ce renseignement.



bon ... même si après je désire redimensionner le buffer trop petit ?
(pardon de pas l'avoir précisé ...)

Private Const FNERR_BUFFERTOOSMALL As Long = &H3003
If GetOpenFileNameA(OFN) Then
--Traitement si OK
Else
If CommDlgExtendedError = FNERR_BUFFERTOOSMALL then Msgbox "Buffer
too small" End If



ben de toutes façons ça fonctionne pas ...

je dois encore merder qque part ! :-(

pour éviter la même konn*** qui quelques posts plus haut, je te poste le
bout de code sur lequel j'essaie d'intercepter l'erreur "BUFFERTOOSMALL "

si tu y vois une erreur ??

merci encore :-)



'dans une Form
---------------------------
Option Explicit

Private Declare Function GetOpenFileName _
Lib "comdlg32.dll" Alias "GetOpenFileNameA" _
(pOpenfilename As OPENFILENAME) As Long
Private Declare Function CommDlgExtendedError _
Lib "comdlg32.dll" () As Long

Private Const MAX_PATH = 260
Private Const FNERR_BUFFERTOOSMALL As Long = &H3003

Public Enum OFN_Constants
OFN_ALLOWMULTISELECT = &H200
OFN_CREATEPROMPT = &H2000
OFN_DONTADDTORECENT = &H2000000
OFN_ENABLEHOOK = &H20
OFN_ENABLEINCLUDENOTIFY = &H400000
OFN_ENABLESIZING = &H800000
OFN_ENABLETEMPLATE = &H40
OFN_ENABLETEMPLATEHANDLE = &H80
OFN_EX_NOPLACESBAR = &H1
OFN_EXPLORER = &H0
OFN_EXTENSIONDIFFERENT = &H400
OFN_FILEMUSTEXIST = &H1000
OFN_FORCESHOWHIDDEN = &H10000000
OFN_HIDEREADONLY = &H4
OFN_LONGNAMES = &H200000
OFN_NOCHANGEDIR = &H8
OFN_NODEREFERENCELINKS = &H100000
OFN_NOLONGNAMES = &H40000
OFN_NONETWORKBUTTON = &H20000
OFN_NOREADONLYRETURN = &H8000
OFN_NOTESTFILECREATE = &H10000
OFN_NOVALIDATE = &H100
OFN_OVERWRITEPROMPT = &H2
OFN_PATHMUSTEXIST = &H800
OFN_READONLY = &H1
OFN_SHAREAWARE = &H4000
OFN_SHAREFALLTHROUGH = 2
OFN_SHARENOWARN = 1
OFN_SHAREWARN = 0
OFN_SHOWHELP = &H10
OFN_USEMONIKERS = &H1000000
End Enum

Private Type OPENFILENAME
lStructSize As Long
hwndOwner As Long
hInstance As Long
lpstrFilter As String
lpstrCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
lpstrFile As String
nMaxFile As Long
lpstrFileTitle As String
nMaxFileTitle As Long
lpstrInitialDir As String
lpstrTitle As String
Flags As Long
nFileOffset As Integer
nFileExtension As Integer
lpstrDefExt As String
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End Type

Public Function OpenFileDialog(Optional DialogTitle _
As String, Optional sFilter As String, Optional Flags _
As OFN_Constants, Optional InitialDir As String, _
Optional hwndOwner As Long, Optional hInstance _
As Long) As String

Dim OFName As OPENFILENAME

With OFName
.lStructSize = Len(OFName)
.hwndOwner = hwndOwner
.hInstance = hInstance
.lpstrFilter = sFilter
.nMaxFile = 50 ' 32767
.lpstrFile = String$(.nMaxFile, vbNullChar)
.lpstrFileTitle = Space$(254)
.nMaxFileTitle = 255
.lpstrInitialDir = InitialDir
.lpstrTitle = DialogTitle
.Flags = Flags
End With

If GetOpenFileName(OFName) Then
OpenFileDialog = Trim$(OFName.lpstrFile)
OpenFileDialog = Left$(OpenFileDialog, _
InStr(OpenFileDialog, vbNullChar & vbNullChar) - 1)
Else
If CommDlgExtendedError = FNERR_BUFFERTOOSMALL _
Then MsgBox "Buffer too small"
OpenFileDialog = -1
End If

End Function

Private Sub Form_Load()

Dim strReturn As String

strReturn = OpenFileDialog("Sélectionnez des Fichiers", _
"All Files(*.*)" & Chr(0) & "*.*" & Chr(0), &H80000 _
+ &H20000 + &H200 + &H20 + &H100 + &H10000000 _
+ &H4 + &H200000, "c:temp")
strReturn = Replace(strReturn, vbNullChar, ";")

If strReturn <> "-1" Then MsgBox strReturn
Unload Me

End Sub

--------



--

Attention ! Adresse mail invalide ...
Pour me contacter, cliquez sur le lien ci-dessous:
http://scraper.chez.tiscali.fr/contact.htm

scraper
Avatar
Alain CROS
Bonjour.

Ton code ne fonctionne pas chez moi.
Le coupable est le + &H100 dans le paramètre flags qui correspond a :
OFN_NOVALIDATE = &H100
Ma Doc me dit ça
OFN_NOVALIDATE
Specifies that the common dialog boxes allow invalid characters in the returned filename. Typically, the calling application uses a
hook procedure that checks the filename by using the FILEOKSTRING message. If the text box in the edit control is empty or contains
nothing but spaces, the lists of files and directories are updated. If the text box in the edit control contains anything else,
nFileOffset and nFileExtension are set to values generated by parsing the text. No default extension is added to the text, nor is
text copied to the buffer specified by lpstrFileTitle.
If the value specified by nFileOffset is less than zero, the filename is invalid. Otherwise, the filename is valid, and
nFileExtension and nFileOffset can be used as if the OFN_NOVALIDATE flag had not been specified.

Sur ce coup là, je crois bien que je ne peux pas t'aider plus car je ne comprends pas très bien la signification de ce texte et donc
l'utilisation de ce flag.

Alain CROS
Avatar
scraper
Bonjour Alain CROS
(dans news:%23%)
tu nous disais :

Bonjour.

Ton code ne fonctionne pas chez moi.
Le coupable est le + &H100 dans le paramètre flags qui correspond a :
OFN_NOVALIDATE = &H100
Ma Doc me dit ça
OFN_NOVALIDATE



effectivement, en l'enlevant, ça va un poil mieux ?

mais c'est pas franchement résolu .... si je sélectionne plein de fichiers,
la fenêtre reste ouverte ??!
aucun message d'erreur, ni rien ...
ce qui correspond à ce qui est expliqué là dedans :

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/CommonDialogBoxLibrary/CommonDialogBoxReference/CommonDialogBoxMessages/FILEOKSTRING.asp

(lien à partir de la mention FILEOKSTRING de la doc MSDN ...

et là, je retombe donc sur mon hook ;-)

merde, on tourne en rond ! :-)

si j'ai bien compris (?) cette page, si je n'installe pas de hook et que
j'intercepte pas le message ....

If the hook procedure returns a nonzero value, the Open or Save As dialog




box rejects the specified file name and remains open.

c'est ce qui se passe, semble t il ???!


euh .... si tu as une ch'tite idée, parce que là, je commence *vraiment* à
pateauger ! :-)

merci en tout cas


--

Attention ! Adresse mail invalide ...
Pour me contacter, cliquez sur le lien ci-dessous:
http://scraper.chez.tiscali.fr/contact.htm

scraper
Avatar
Alain CROS
Bonjour scraper

J'ai un peu regardé ton code et je pense que ce que tu veux faire est impossible.

La structure ofname que tu initialise au départ correspond au paramètre de création de la boite de dialogue.
Cette structure doit être copiée quelque part en mémoire dans une zone que la boite de dialogue se réserve.
Une fois que cette boite de dialogue est affichée, un certain nombres de ses paramètres ne "peuvent" pas être modifiés, notamment
ceux contenus dans la structure ofname d'initialisation, par contre, certain peuvent l'être comme le titre de la fenêtre mais en
utilisant une fonction extérieure SetWindowText.
Si tu essaye de modifier le paramètre du titre de la fenêtre dans la structure ofname, il ne se passe rien.

La structure ofname dont tu disposes peut être modifiée mais ceci n'aura aucune influence puisque la boite de dialogue travaille sur
une copie(elle connaît donc la taille des buffers, les filtres, etc...). Cette structure ofname dont tu dispose ne sera remplie par
la boite de dialogue que lorsque celle ci se décharge de la mémoire par l'appuis du bouton OK pour que le programme puisse connaître
les choix effectués.

La référence que tu as donnés sur FILEOKSTRING m'a semblé plutôt confuse.

Le paramètre OFN_NOVALIDATE = &H100 te permet d'intercepter dans le hook l'appuis sur le bouton ok.
Pour cela , il faut intercepter CDN_FILEOK défini par Private Const CDN_FILEOK As Long = (CDN_FIRST - &H5)
par exemple en reprenant ton code :

Case CDN_FILEOK
FolderBuff = SendMessage(hWndParent, CDM_GETFOLDERPATH, 0, ByVal 0&)
FileBuff = SendMessage(hWndParent, CDM_GETSPEC, 0, ByVal 0&)
If (FolderBuff + FileBuff) > OFName.nMaxFile Then
' Si tu décides de ne pas valider donc ne pas fermer la boite de dialogue
' Const DWL_MSGRESULT As Long = 0
OFNHookProc = True
SetWindowLong hwnd, DWL_MSGRESULT, 1&
Exit Function
' Si tu décides de valider ofname.lpstrFile contient la taille du buffer nécessaire
OFNHookProc = False
MsgBox Asc(OFName.lpstrFile)
End If
End Select

Alain CROS


bon, voila, j'ai un peu avancé !

donc, je résume :
je cherche à récupérer le message généré par un buffer trop petit, lors
d'une multisélection dans la fenêtre GetOpenFileName

j'ai installé un hook .... maintenant, j'arrive bien à récupérer ce message
mais plusieurs problèmes subsistent :

- au delà d'un certain nombre de fichiers sélectionnés, ça fonctionne plus,
et si je clique sur ouvrir, rien ne se passe .... je clique 1 fois dans la
fenêtre "Nom de fichiers " puis sur ouvrir, et là je reçois des signes
cabalistiques

- je ne sais pas comment interceper le message envoyé par la fenêtre
lorsqu'on clique sur ouvrir ?

- je ne sais pas envoyer à la fenêtre la nouvelle valeur du buffer que j'ai
déterminée ??

si vous avez des infos ...

merci



le source est en PJ car j'ai eu peur qu'il soit trop volumineux pour le
message (longueur du texte)




--

Attention ! Adresse mail invalide ...
Pour me contacter, cliquez sur le lien ci-dessous:
http://scraper.chez.tiscali.fr/contact.htm

scraper





Avatar
scraper
Bonjour Alain CROS
(dans news:)
tu nous disais :

Bonjour scraper

J'ai un peu regardé ton code et je pense que ce que tu veux faire est
impossible.



bonjour !

ah .....

La structure ofname que tu initialise au départ correspond au
paramètre de création de la boite de dialogue.



oui

Cette structure doit être copiée quelque part en mémoire dans une
zone que la boite de dialogue se réserve.



bon

Une fois que cette boite de dialogue est affichée, un certain nombres
de ses paramètres ne "peuvent" pas être modifiés, notamment ceux
contenus dans la structure ofname d'initialisation, par contre,
certain peuvent l'être comme le titre de la fenêtre mais en utilisant
une fonction extérieure SetWindowText.



pas seulement !
avec un hook, tu peux aussi modifier les boutons, et plein d'autres trucs !
et même (si j'ai bien compris, mais je n'ai fait que survoler ...) remplacer
la boite de dialogue par une de ton cru avec OFN_ENABLETEMPLATE (de tête)

Si tu essaye de modifier le paramètre du titre de la fenêtre dans la
structure ofname, il ne se passe rien.



tout comme la longueur du buffer :-(

La structure ofname dont tu disposes peut être modifiée mais ceci
n'aura aucune influence puisque la boite de dialogue travaille sur
une copie(elle connaît donc la taille des buffers, les filtres,
etc...). Cette structure ofname dont tu dispose ne sera remplie par
la boite de dialogue que lorsque celle ci se décharge de la mémoire
par l'appuis du bouton OK pour que le programme puisse connaître les
choix effectués.



c'est là que je capte pas !
je croyais que le hook , une fois effectuées les modifications, recopiait
cette portion de zone mémoire ?

La référence que tu as donnés sur FILEOKSTRING m'a semblé plutôt
confuse.

Le paramètre OFN_NOVALIDATE = &H100 te permet d'intercepter dans le
hook l'appuis sur le bouton ok.
Pour cela , il faut intercepter CDN_FILEOK défini par Private Const
CDN_FILEOK As Long = (CDN_FIRST - &H5)
par exemple en reprenant ton code :

Case CDN_FILEOK
FolderBuff = SendMessage(hWndParent,
CDM_GETFOLDERPATH, 0, ByVal 0&) FileBuff > SendMessage(hWndParent, CDM_GETSPEC, 0, ByVal
0&) If (FolderBuff + FileBuff) > OFName.nMaxFile Then ' Si tu décides
de ne pas valider donc ne pas fermer la boite de dialogue ' Const
DWL_MSGRESULT As Long = 0 OFNHookProc > True SetWindowLong hwnd, DWL_MSGRESULT, 1&
Exit Function
' Si tu décides de valider ofname.lpstrFile contient la taille du
buffer nécessaire OFNHookProc = False
MsgBox Asc(OFName.lpstrFile)
End If
End Select




eh oui, et c'est bien pour cela que je me dis que si ça a été prévu de
pouvoir intercepter le dépassement de taille du buffer, c'est bien pour
pouvoir le redimensionner dynamiquement ???!
au surplus, je suis tombé sur une page (mais en C++ :-( qui l'expliquait
...


en tout cas, merci de ton aide ....

si j'ai du neuf, je reposterai .... mais sinon, ben je crois malheureusement
avoir fait un peu le tour ...



--

Attention ! Adresse mail invalide ...
Pour me contacter, cliquez sur le lien ci-dessous:
http://scraper.chez.tiscali.fr/contact.htm

scraper
Avatar
Alain CROS
Bonjour scraper.

si j'ai du neuf, je reposterai .... mais sinon, ben je crois malheureusement
avoir fait un peu le tour ...



Voila un petit tour supplémentaire.

Alain CROS


Module de la Form qui comporte 1 Command_Button :

'**********
Private Declare Function GlobalSize& Lib "kernel32" (ByVal hMem&)

Private Declare Function GlobalFree& Lib "kernel32" (ByVal hMem&)

Private Sub Command1_Click()
Const OFN_ENABLEHOOK& = &H20, OFN_EXPLORER& = &H80000, OFN_NONETWORKBUTTON& = &H20000, _
OFN_ALLOWMULTISELECT& = &H200, OFN_NOVALIDATE& = &H100, OFN_FILEMUSTEXIST& = &H1000, _
OFN_FORCESHOWHIDDEN& = &H10000000, OFN_HIDEREADONLY& = &H4, OFN_LONGNAMES& = &H200000, _
OFN_PATHMUSTEXIST& = &H800, OFN_NOCHANGEDIR& = &H8
Dim strSource$, strResult$, MaMem&, MemRetour$, PMemRetour&, Tailleretour&
strSource = CurDir
strResult = OpenFileDialog("Sélectionnez les fichiers", "All Files (*.*)", _
OFN_ENABLEHOOK Or OFN_EXPLORER Or OFN_NONETWORKBUTTON Or OFN_ALLOWMULTISELECT Or _
OFN_NOVALIDATE Or OFN_FILEMUSTEXIST Or OFN_FORCESHOWHIDDEN Or OFN_HIDEREADONLY Or _
OFN_LONGNAMES Or OFN_PATHMUSTEXIST Or OFN_NOCHANGEDIR, strSource, VarPtr(MaMem))
If strResult <> "" Then
PMemRetour = GlobalLock(MaMem)
Tailleretour = GlobalSize(MaMem)
MemRetour = Space$(Tailleretour)
CopyMemory ByVal MemRetour, ByVal PMemRetour, Tailleretour
GlobalFree PMemRetour
MsgBox Left$(MemRetour, InStr(MemRetour, vbNullChar) - 1&)
Else
MsgBox "Opération Annulée"
End If
End Sub
'**********

Dans un module :

'**********
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(lpvDest As Any, lpvSource As Any, ByVal cbCopy&)

Public Declare Function GlobalLock& Lib "kernel32" (ByVal hMem&)

Private Declare Function GlobalAlloc& Lib "kernel32" (ByVal wFlags&, ByVal dwBytes&)

Private Declare Function GetParent& Lib "user32" (ByVal hwnd&)

Private Declare Function GetOpenFileName& Lib "comdlg32" Alias "GetOpenFileNameA" _
(pOpenfilename As OPENFILENAME)

Private Declare Function SendMessage& Lib "user32" Alias "SendMessageA" _
(ByVal hwnd&, ByVal wMsg&, ByVal wParam&, ByVal lParam As Any)

Private Type NMHDR
hwndFrom As Long
idfrom As Long
code As Long
End Type

Private Type OFNOTIFY
hdr As NMHDR
lpOFN As Long
pszFile As Long
End Type

Public Type OPENFILENAME
lStructSize As Long
hwndOwner As Long
hInstance As Long
lpstrFilter As String
lpstrCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
lpstrFile As String
nMaxFile As Long
lpstrFileTitle As String
nMaxFileTitle As Long
lpstrInitialDir As String
lpstrTitle As String
Flags As Long
nFileOffset As Integer
nFileExtension As Integer
lpstrDefExt As String
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End Type

Public Function OpenFileDialog$(Optional DialogTitle$, Optional sFilter$, Optional Flags&, _
Optional InitialDir$, Optional ByVal Refmem&, Optional hwndOwner&, Optional hInstance&)
Dim OFName As OPENFILENAME
With OFName
.lStructSize = Len(OFName)
.hwndOwner = hwndOwner
.hInstance = hInstance
.lpstrFilter = sFilter
.nMaxFile = 5&
.lpstrFile = String$(.nMaxFile, vbNullChar)
.lpstrFileTitle = Space$(255&)
.nMaxFileTitle = 255&
.lpstrInitialDir = InitialDir
.lpstrTitle = DialogTitle
.Flags = Flags
.lCustData = Refmem
.lpfnHook = FARPROC(AddressOf OFNHookProc)
GetOpenFileName OFName
OpenFileDialog = Left$(.lpstrFile, InStr(.lpstrFile, vbNullChar) - 1&)
End With
End Function

Public Function FARPROC&(ByVal pfn&)
FARPROC = pfn
End Function

Public Function OFNHookProc&(ByVal hwnd&, ByVal uMsg&, ByVal wParam&, ByVal lParam&)
Const GMEM_MOVEABLE& = &H2, WM_NOTIFY& = &H4E, CDN_FIRST& = -601&, _
CDN_FILEOK& = (CDN_FIRST - &H5), WM_USER& = &H400, CDM_FIRST& = (WM_USER + 100&), _
CDM_GETFOLDERPATH& = (CDM_FIRST + &H2), CDM_GETSPEC& = (CDM_FIRST + &H0)
Dim hWndParent&, tNMH As NMHDR, tofNotify As OFNOTIFY, OFN As OPENFILENAME
Dim LePath$, TPath&, LesFiles$, TFiles&, TBuff&, LeRetour$, VarMem&, PVarMem&
hWndParent = GetParent(hwnd)
If uMsg = WM_NOTIFY Then
CopyMemory ByVal VarPtr(tofNotify), ByVal lParam, Len(tofNotify)
If tofNotify.hdr.code = CDN_FILEOK Then
Do
LePath = Space$(TPath)
TPath = SendMessage(hWndParent, CDM_GETFOLDERPATH, TPath, LePath)
Loop While Len(LePath) = 0&
Do
LesFiles = Space$(TFiles)
TFiles = SendMessage(hWndParent, CDM_GETSPEC, TFiles, LesFiles)
Loop While Len(LesFiles) = 0&
LeRetour = Left$(LePath, TPath - 1&) & " > " & LesFiles
TBuff = Len(LeRetour)
CopyMemory ByVal VarPtr(OFN), ByVal tofNotify.lpOFN, Len(OFN)
VarMem = GlobalAlloc(GMEM_MOVEABLE, TBuff)
PVarMem = GlobalLock(VarMem)
CopyMemory ByVal PVarMem, ByVal LeRetour, TBuff
CopyMemory ByVal OFN.lCustData, VarMem, 4&
End If
End If
End Function
Avatar
scraper
Bonjour Alain CROS
(dans news:%)
tu nous disais :

Bonjour scraper.

si j'ai du neuf, je reposterai .... mais sinon, ben je crois
malheureusement avoir fait un peu le tour ...



Voila un petit tour supplémentaire.



hello !

merci de t'intéresser à ce problème ... :-)

j'ai survolé rapidement pour l'instant, et j'avoue avoir un peu décroché ...
:-(

j'ai testé, tout de même, et .... effectivement, le seuil de 5 est bien
dépassé ....
mais ça bloque toujours ?!

selon, j'ai l'impression, la longueur de la chaine qui contient les fichiers
sélectionnés ??

je clique sur ouvrir, il ne se passe rien ?
je clique une fois dans la fenêtre "Nom de fichier", puis à nouveau sur
ouvrir, et je reçois une erreur d'exécution 5 au niveau de la fonction Hook
...

ici, très pécisément :

LesFiles = Space$(TFiles)


dans la semaine, je vais essayer de me pencher là dessus .... mais j'ai du
mal ? :-)

merci en tout cas


--

Attention ! Adresse mail invalide ...
Pour me contacter, cliquez sur le lien ci-dessous:
http://scraper.chez.tiscali.fr/contact.htm

scraper
1 2