Zipper / Dézipper avec les fonctions de Window

Partagez votre expérience de PureBasic avec les autres utilisateurs.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Zipper / Dézipper avec les fonctions de Window

Message par nico »

Voici un code qui permet de Zipper et de Dézipper en utilisant les fonctions de Window

Remarque:
-Il faut que les fichiers à zipper soit dans un dossier mais le dossier lui même ne sera pas zipper
donc si vous voulez zipper des fichiers avec le dossier, il faut mettre ce dossier dans un autre dossier

-Le dossier qui a été choisi pour zipper le contenu, ne peut pas être utiliser pour placer le nouveau fichier zip

Par exemple si je choisis de compresser le dossier purebasic dans le chemin ci dessous:
C:\sauvegarde\programme\purebasic
Le dossier source sera C:\sauvegarde\programme\
et le dossier de destination sera, si on souhaite utiliser le même chemin: C:\sauvegarde\
je ne pourrais donc pas utiliser le chemin: C:\sauvegarde\programme\ même si celui-ci (le dossier programme) ne sera pas compresser.


Lorsqu'on dézippe un fichier, la fonction est bloquante mais pas quand on zip, c'est pour cela qu'un second thread est lancé pour vérifier quand est ce que le processus a terminé; de plus il y a une tempo que vous pourrez modifier qui détermine combien de temps on laisse à window pour compresser les fichiers, car il n'y a aucun moyen de savoir si l'opération à été un succès ou pas au niveau de l'objet com.

Le code de la procédure:

Code : Tout sélectionner

#FOF_SILENT = $4
; #FOF_RENAMEONCOLLISION = $8
#FOF_NOCONFIRMATION = $10
; #FOF_ALLOWUNDO = $40
; #FOF_FILESONLY = $80
; #FOF_SIMPLEPROGRESS = $100
; #FOF_NOCONFIRMMKDIR = $200
#FOF_NOERRORUI = $400
; #FOF_NOCOPYSECURITYATTRIBS = $800
; #FOF_NORECURSION = $1000
; #FOF_NO_CONNECTED_ELEMENTS = $2000

Structure param
  Id.i
  Dest.s
EndStructure

Structure param2
  Src.s
  Dest.s
  hWindow.i
EndStructure

Procedure Newzip(file.s)
  Protected id.i
  
  id.i= CreateFile(#PB_Any,file)
  If id<>0
    WriteByte(id, 80)
    WriteByte(id, 75)   
    WriteByte(id, 5) 
    WriteByte(id, 6)
    For a=1 To 20
      WriteByte(id, 0)
    Next
    Debug "ok"
    CloseFile(id)
  Else
    ProcedureReturn 0
  EndIf 
  
  ProcedureReturn 1
EndProcedure

Procedure Set_Variant(*Variant.Variant, Type.w, *Valeur.integer)
  
  Select type
    Case #VT_I4
      *Variant\vt=Type
      *Variant\lval=*Valeur\i
      
    Case #VT_BSTR
      *Bstr=SysAllocString_(*Valeur)
      *Variant\vt=Type
      *Variant\pbstrVal=*Bstr
      
    Case #VT_DISPATCH
      *Variant\vt=Type
      *Variant\pdispVal=*Valeur\i
  EndSelect
  
EndProcedure

Procedure Clean_BSTR(*Variant.Variant)
  If *Variant\pbstrVal <> 0
    SysFreeString_(*Variant\pbstrVal)
    *Variant\pbstrVal = 0
  EndIf 
EndProcedure

Procedure Wait(*lParam.param)
  Protected File.s, size.l, Id.i
  
  File = *lParam\Dest
  
  size = FileSize(File)
  Repeat
    Delay(150)
    a=a+1
    Debug "a="+Str(a)
  Until FileSize(File) <> size
  
  
  Repeat
    Delay(50)
    a=a+1
    Debug "b="+Str(a)
    Id = OpenFile(0, File)
    *lParam\Id=Id
  Until Id <> 0
  
  CloseFile(0)
  
EndProcedure


Procedure Zip_Unzip(*lParam.param2)
  Protected Ret.l = 0, Zip.l = 0, hThread.i, param.param, cFlags.l
  Protected Dest.s, Src.s
  
  CoInitialize_(0) 
  
  Dest = *lParam\Dest
  Debug Dest
  Src = *lParam\Src
  Debug Src
  
  If CoCreateInstance_(?CLSID_Shell, 0, 1, ?IID_IShellDispatch, @IShell.IShellDispatch) <> #S_OK
    Goto Clean
  EndIf
  
  ; Si le dossier destinataire un un zip, il faut créer un zip vierge
  If LCase(GetExtensionPart(Dest))="zip"
    If Newzip(Dest)=0
      Goto Clean
    Else
      Zip = 1
    EndIf
  EndIf
  
  Set_Variant(@vt.variant, #VT_BSTR, @Src)
  If IShell\Namespace(vt, @FolderScr.Folder ) <> 0
    Goto Clean
  EndIf
  Clean_BSTR(@vt)
  Debug FolderScr
  
  Set_Variant(@vt.variant, #VT_BSTR, @Dest)
  If IShell\Namespace(vt, @FolderDest.Folder ) <> 0
    Goto Clean
  EndIf
  Clean_BSTR(@vt)
  Debug FolderDest
  
  
  If FolderScr\Items(@fdItems.FolderItems) <> 0
    Goto Clean
  EndIf 
  Debug fdItems
  
  cFlags.l = #FOF_SILENT + #FOF_NOCONFIRMATION + #FOF_NOERRORUI
  Set_Variant(@vt.variant, #VT_DISPATCH , @fdItems)
  Set_Variant(@vt2.variant, #VT_I4, @cFlags)
  If FolderDest\CopyHere(@vt, @vt2) <> 0
    Goto Clean
  EndIf
  
  Ret=1
  
  ; Si le dossier de destination est un zip alors on crée un thread
  ; car la fonction de zippage est asynchrone
  If Zip 
    ;hThread = CreateThread(@Wait(), @Dest)
    param\Dest=Dest
    hThread = CreateThread_(#Null, 0, @Wait(), @param, #THREAD_TERMINATE | #THREAD_QUERY_INFORMATION, @idThread)
    Select WaitForSingleObject_(hThread, 30000)
      Case #WAIT_OBJECT_0
        Ret = 1
        Debug "Fin attendue"
        
      Default
        Retval = TerminateThread_(hThread, 0)
        CloseHandle_(hThread)
        If param\Id <> 0
          CloseFile(Id)
          Ret = 1
        Else
          Ret = 0
          DeleteFile(Dest)
        EndIf
        Debug "Erreur, Temps alloué au thread dépassé!"
        
    EndSelect
  EndIf 
  
  Clean:
  If FolderScr <> 0
    FolderScr\release()
  EndIf 
  
  If FolderDest <> 0
    FolderDest\release()
  EndIf 
  
  If fdItems <> 0
    fdItems\release()
  EndIf 
  
  If IShell <> 0
    IShell\release()
  EndIf 
  
  CoUninitialize_() 
  
  PostMessage_(*lParam\hWindow, #WM_USER + 1000, 0 , Ret)
  
  DataSection 
    CLSID_Shell: 
    Data.l $13709620 
    Data.w $C279,$11CE 
    Data.b $A4,$9E,$44,$45,$53,$54,$00,$00 
    
    IID_IShellDispatch: 
    Data.l $D8F015C0 
    Data.w $C278,$11CE 
    Data.b $A4,$9E,$44,$45,$53,$54,$00,$00 
    
    IID_IDispatch:
    Data.l $00020400 
    Data.w $0000,$0000 
    Data.b $C0,$00,$00,$00,$00,$00,$00,$46
    
    IID_NULL:   
    Data.l $00000000 
    Data.w $0000,$0000 
    Data.b $00,$00,$00,$00,$00,$00,$00,$00
  EndDataSection
  
EndProcedure

Procedure Thread_Zip_Unzip(Dest.s, Src.s, hWindow.i)
  Static Folder.param2
  
  Folder\Dest = Dest
  Folder\Src = Src
  Folder\hWindow = hWindow
  
  CreateThread(@Zip_Unzip(), @Folder)
EndProcedure
Un code de démo d'utilisation:

Code : Tout sélectionner

;{- Enumerations / DataSections
;{ Windows
Enumeration
  #Window_0
EndEnumeration
;}
;{ Gadgets
Enumeration
  #Button_Valider
  #String
  #Text
  #Button_Dossier
  #Button_Fichier
EndEnumeration
;}
;}
Procedure OpenWindow_Window_0()
  If OpenWindow(#Window_0, 651, 400, 710, 161, "Zip / Unzip", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered)
    If CreateGadgetList(WindowID(#Window_0))
      ButtonGadget(#Button_Valider, 278, 115, 160, 35, "Valider")
      StringGadget(#String, 10, 50, 490, 25, "", #PB_String_ReadOnly )
      TextGadget(#Text, 10, 10, 490, 25, "Choisir un Dossier à Zipper ou fichier Zip à Dézipper")
      ButtonGadget(#Button_Dossier, 510, 35, 190, 25, "Dossier (Zipper)")
      ButtonGadget(#Button_Fichier, 510, 65, 190, 25, "Fichier Zip (Dézipper)")
    EndIf
  EndIf
EndProcedure

OpenWindow_Window_0()

;{- Event loop
Repeat
  Select WaitWindowEvent()
      ; ///////////////////
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #Button_Valider
          Chaine.s = GetGadgetText(#String)
          Debug GetFilePart(Chaine)
          If GetFilePart(Chaine) = ""
            ; c'est un dossier, donc on zip
            count.l = CountString(Chaine, "\")
            Field.s = StringField(Chaine, count, "\")
            Dest.s = Left(Chaine, Len(Chaine) - Len(Field) - 1)
            Thread_Zip_Unzip(Dest + "New_zip.zip", Chaine, WindowID(#Window_0)) 
          Else
            ; c'est un zip donc on dézippe
            Fichier$ = GetFilePart(Chaine)
            Dossier$ = RemoveString(Chaine, Fichier$)
            Thread_Zip_Unzip(Dossier$, Chaine, WindowID(#Window_0))
          EndIf
          DisableGadget(#Button_Valider, 1)
          
        Case #Button_Dossier
          Chemin$ = PathRequester("Choisissez un Dossier", "C:\")
          SetGadgetText(#String, Chemin$)
          
        Case #Button_Fichier
          NomFichier$ = OpenFileRequester("Choisissez un fichier Zip", "C:\", "*.zip", 0)
          SetGadgetText(#String, NomFichier$)
      EndSelect
      
    Case #WM_USER + 1000
      DisableGadget(#Button_Valider, 0)
      If EventlParam() = 1
        MessageRequester("Info", "Opération réussie")
      Else
        MessageRequester("Erreur", "Echec, le temps alloué à été dépassé ou une erreur s'est produite")
      EndIf
      ; ////////////////////////
    Case #PB_Event_CloseWindow
      Select EventWindow()
        Case #Window_0
          CloseWindow(#Window_0)
          Break
      EndSelect
  EndSelect
ForEver
;
;}
Dernière modification par nico le mar. 05/juin/2012 18:56, modifié 1 fois.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Zipper / Dézipper avec les fonctions de Window

Message par nico »

reserve
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Zipper / Dézipper avec les fonctions de Window

Message par nico »

reserve
Répondre