⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 自解压过程.bas

📁 新魔剑压缩机。采用新的压缩算法对文件压缩。
💻 BAS
字号:
Attribute VB_Name = "自解压过程"
Public Declare Function SHBrowseForFolder Lib "shell32.dll" Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long
Public Declare Function SHGetPathFromIDList Lib "shell32.dll" (ByVal pidl As Long, pszPath As String) As Long
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (ByRef Ptr() As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Public Type BROWSEINFO
        hOwner   As Long
        pidlRoot   As Long
        pszDisplayName   As String
        lpszTitle   As String
        ulFlage   As Long
        lpfn   As Long
        lparam   As Long
        iImage   As Long
End Type

Type FileParameter
  FileAttr  As Byte
  FileDeep  As Byte
  FilePos   As Long
  FileLen   As Long
End Type

Type FileInform
  FileNme() As Byte
  FileParam As FileParameter
End Type

Type RePlaceCode
  DicCode(1 To 2) As Byte
  AscCode As Byte
End Type

Public List() As FileInform
Public RePlaceLim As Byte, Pro As Single, Cancel As Boolean, FileName As String
Private Const ReadLen As Long = 65535

Sub Main()
Dim FSO As New FileSystemObject, s As String
s = App.Path & "\" & App.EXEName & ".EXE"
If FSO.FileExists(s) Then
  Open s For Binary As #1
  Call GetList(1)
  Dim Path As String
  Path = ShowDir(FrmProgress.hWnd, "目标路径")
  If Path <> "" Then
    Cancel = False
    FrmProgress.Show
    Call ReleaseFile(Path, 0, 1)
  End If
End If
End Sub

Function ShowDir(MehWnd As Long, Optional Title As String) As String
Dim BI As BROWSEINFO
Dim TempID As Long
Dim TempStr As String
        
TempStr = String$(255, Chr$(0))
With BI
  .hOwner = MehWnd
  .pidlRoot = 0
  .lpszTitle = Title + Chr$(0)
  .ulFlage = &H1
End With
        
TempID = SHBrowseForFolder(BI)
        
If SHGetPathFromIDList(ByVal TempID, ByVal TempStr) Then ShowDir = Left$(TempStr, InStr(TempStr, Chr$(0)) - 1)
End Function

Sub GetList(FileNum As Integer)
On Error GoTo Err
Dim AllCount As Long, EachNameLen() As Byte
Dim ListPos As Long
Dim i As Long
Seek #FileNum, LOF(FileNum) - 3
Get #FileNum, , ListPos
Seek #FileNum, ListPos
Get #FileNum, , AllCount
ReDim List(0 To AllCount)
If AllCount > 0 Then
  ReDim EachNameLen(1 To AllCount)
  Get #FileNum, , EachNameLen
  For i = 1 To AllCount
    ReDim List(i).FileNme(0 To EachNameLen(i))
    Get #FileNum, , List(i).FileNme
    Get #FileNum, , List(i).FileParam
  Next
End If
Exit Sub
Err:
  ReDim List(0)
  Seek #FileNum, LOF(FileNum) + 1
  Put #FileNum, , LOF(FileNum)
End Sub

Sub ReleaseFile(Path As String, ListPos As Long, FileNum As Integer)
On Error GoTo Err
Dim t As FileInform, r As Folder, FSO As New FileSystemObject, Name As String
Dim k As Long
If ListPos > 0 Then
  t = List(ListPos)
  If t.FileParam.FileLen >= 0 Then
    Name = Path & "\" & StrConv(t.FileNme, vbUnicode)
    If t.FileParam.FileAttr And vbDirectory Then
      If FSO.FolderExists(Name) Then
        Set r = FSO.GetFolder(Name)
      Else
        Set r = FSO.CreateFolder(Name)
      End If
      r.Attributes = t.FileParam.FileAttr
      Call ReleaseFolder(r, ListPos, FileNum)
    Else
      If FSO.FileExists(Name) Then If MsgBox("文件已存在,是否覆盖?", vbOKCancel + vbExclamation) = vbOK Then Kill Name Else Exit Sub
      k = UnExtract(FileNum, t.FileParam.FilePos, t.FileParam.FilePos + t.FileParam.FileLen, Name)
      SetAttr Name, t.FileParam.FileAttr
    End If
  End If
Else
  Call ReleaseFolder(FSO.GetFolder(Path), ListPos, FileNum)
End If
Unload FrmProgress
Exit Sub
Err:
  Unload FrmProgress
  MsgBox "Error!"
End Sub

Sub ReleaseFolder(ParFolder As Folder, ListPos As Long, FileNum As Integer)
Dim Name As String, TListPos As Long
Dim t As FileInform, r As Folder, FSO As New FileSystemObject
Dim k As Long
TListPos = ListPos
If ListPos < UBound(List) Then
  If List(ListPos + 1).FileParam.FileDeep > List(ListPos).FileParam.FileDeep Then
    Do
      ListPos = ListPos + 1
      Do While List(ListPos).FileParam.FileLen < 0
        ListPos = ListPos + 1
        If ListPos = UBound(List) Then Exit Sub
      Loop
      t = List(ListPos)
      Name = ParFolder.Path & "\" & StrConv(t.FileNme, vbUnicode)
      If t.FileParam.FileAttr And vbDirectory Then
        If FSO.FolderExists(Name) Then
          Set r = FSO.GetFolder(Name)
        Else
          Set r = FSO.CreateFolder(Name)
        End If
        r.Attributes = t.FileParam.FileAttr
        Call ReleaseFolder(r, ListPos, FileNum)
        If Cancel Then Exit Sub
      Else
        If FSO.FileExists(Name) Then If MsgBox("文件已存在,是否覆盖?", vbOKCancel + vbExclamation) = vbOK Then Kill Name Else Exit Sub
        k = UnExtract(FileNum, t.FileParam.FilePos, t.FileParam.FilePos + t.FileParam.FileLen, Name)
        SetAttr Name, t.FileParam.FileAttr
      End If
      If ListPos = UBound(List) Then Exit Sub
    Loop Until List(ListPos + 1).FileParam.FileDeep <= List(TListPos).FileParam.FileDeep
  End If
End If
End Sub

Private Sub ClearArray(Arr() As Byte, Pos As Long)
Dim t As Long
ReDim Arr(Pos To Pos)
Call CopyMemory(t, ByVal VarPtrArray(Arr), 4)
Call CopyMemory(ByVal t + 16, 0&, 4)
End Sub

Private Sub SwapArray(a() As Byte, b() As Byte)
Dim t As Long
Call CopyMemory(t, ByVal VarPtrArray(a), 4)
Call CopyMemory(ByVal VarPtrArray(a), ByVal VarPtrArray(b), 4)
Call CopyMemory(ByVal VarPtrArray(b), t, 4)
End Sub


Private Sub UnPointCode(SouData() As Byte, DesData() As Byte)
'变量定义
Static TempData() As Byte
Dim PointCol(1 To 16383) As Integer 'int(65535/4)=16383
Dim RealLen As Long
Dim i As Long, j As Long, k As Long
Dim l As Byte, r As Long, t As Long
Dim PointPos As Long
Dim SouPos As Long, TempPos As Long
Dim TempData2() As Byte

SouPos = LBound(SouData)

If UBound(SouData) - LBound(SouData) + 1 = 0 Then
  Erase TempData
Else
  If LBound(SouData) = 1 Then
    Call ClearArray(DesData, 1)
    Call ClearArray(TempData, 1)
  End If


  l = SouData(SouPos)
  SouPos = SouPos + 1
  RealLen = SouData(SouPos) * 256& Or SouData(SouPos + 1)
  TempPos = SouPos + 2
  SouPos = TempPos + RealLen
  PointPos = SouData(SouPos) * 256& Or SouData(SouPos + 1)
  SouPos = SouPos + 2
  Call CopyMemory(PointCol(1), SouData(SouPos), PointPos * 2)
  SouPos = SouPos + 2 * PointPos

  j = UBound(TempData)
  ReDim Preserve TempData(LBound(TempData) To j + ReadLen) '初始化目标单元大小
  PointPos = 0
  For k = TempPos To TempPos + RealLen - 1
    j = j + 1
    If SouData(k) = l Then
      PointPos = PointPos + 1
      t = PointCol(PointPos) And &HFFF
      For r = 0 To (PointCol(PointPos) And &HFFFF&) \ 4096 + 3
        TempData(j + r) = TempData(j - t + r)
      Next
      j = j + r - 1
    Else
      TempData(j) = SouData(k)
    End If
  Next
    
  'ReDim Preserve TempData(LBound(TempData) To j)  '确定目标单元真实大小
'  ReDim Preserve DesData(LBound(DesData) To j)
'  Call CopyMemory(DesData(LBound(DesData)), TempData(LBound(DesData)), j - LBound(DesData) + 1)
  If j - 4095 > LBound(DesData) Then i = j - 4095 Else i = LBound(DesData)
  
  If SouPos > UBound(SouData) Then
    Call ClearArray(SouData, SouPos)
  Else
    ReDim TempData2(SouPos To UBound(SouData))
    Call CopyMemory(TempData2(SouPos), SouData(SouPos), UBound(SouData) - SouPos + 1)
    Call SwapArray(TempData2, SouData)
  End If

  k = LBound(DesData)
  If i < k Then
    Call SwapArray(TempData, DesData)
    ReDim TempData(i To j)
    Call CopyMemory(TempData(i), DesData(i), j - i + 1)
    ReDim DesData(k To j)
    Call CopyMemory(DesData(k), TempData(k), j - k + 1)
  Else
    If k > j Then
      Call ClearArray(DesData, k)
    Else
      ReDim DesData(k To j)
      Call CopyMemory(DesData(k), TempData(k), j - k + 1)
      ReDim TempData(i To j)
      Call CopyMemory(TempData(i), DesData(i), j - i + 1)
    End If
  End If
End If

End Sub


Private Sub UnRePlaceCode(SouData() As Byte, DesData() As Byte)
Static RePlaceDic(1 To 255) As RePlaceCode '替换表
Dim RealLen As Long
Dim CycleDic(1 To 255) As RePlaceCode, CycleMap(1 To 255) As Byte
Dim CycleCount As Byte
Dim AscMap(0 To 255) As Byte   'Asc映射
Dim i As Long, j As Long, k As Byte
Dim SouPos As Long
Dim TempData() As Byte
SouPos = LBound(SouData)
'开始计时
If UBound(SouData) - LBound(SouData) + 1 = 0 Then
  Erase RePlaceDic
Else
  If LBound(SouData) = 1 Then Call ClearArray(DesData, 1)
  CycleCount = SouData(SouPos)
  SouPos = SouPos + 1
  Call CopyMemory(CycleMap(1), SouData(SouPos), CycleCount)
  For i = 1 To CycleCount
    CycleDic(i) = RePlaceDic(CycleMap(i))
  Next
  SouPos = SouPos + CycleCount
  k = SouData(SouPos)
  SouPos = SouPos + 1
  Call CopyMemory(RePlaceDic(1), SouData(SouPos), 3 * k)
  SouPos = SouPos + 3 * k
  Call CopyMemory(RePlaceDic(k + 1), CycleDic(1), 3 * CycleCount)
  k = k + CycleCount
  '读取处理单元大小
  RealLen = SouData(SouPos) * 256& Or SouData(SouPos + 1)
  SouPos = SouPos + 2
  '生成Asc映射
  'Erase AscMap
  For i = 1 To k
    AscMap(RePlaceDic(i).AscCode) = i
  Next
  j = UBound(DesData)
  ReDim Preserve DesData(LBound(DesData) To UBound(DesData) + ReadLen) '初始化目标单元大小
  For i = SouPos To SouPos + RealLen - 1
    j = j + 1
    If AscMap(SouData(i)) = 0 Then
      DesData(j) = SouData(i) '无替换
    Else
      DesData(j) = RePlaceDic(AscMap(SouData(i))).DicCode(1) '替换
      j = j + 1
      DesData(j) = RePlaceDic(AscMap(SouData(i))).DicCode(2)
    End If
  Next
  ReDim Preserve DesData(LBound(DesData) To j) '确定目标单元真实大小
    Debug.Print j - LBound(DesData) + 1
  If i <= UBound(SouData) Then
    Call SwapArray(TempData, SouData)
    ReDim SouData(i To UBound(TempData))
    Call CopyMemory(SouData(i), TempData(i), UBound(TempData) - i + 1)
  Else
    Call ClearArray(SouData, i)
  End If
End If
End Sub


Public Function UnExtract(SouFileNum As Integer, StartPos As Long, EndPos As Long, DesFile As String) As Long
On Error GoTo Err
'变量定义
Dim RealLen As Long
Dim buffer1() As Byte, buffer2() As Byte, buffer3() As Byte
Dim SouFileLen As Long   '原文件长
Dim DesFileNum As Integer  '文件号
  
Pro = 0
FileName = Mid$(DesFile, InStrRev(DesFile, "\") + 1)
SouFileLen = EndPos - StartPos
Seek #SouFileNum, StartPos
DesFileNum = FreeFile
Open DesFile For Binary As #DesFileNum

If Seek(SouFileNum) < EndPos Then
  Call ClearArray(buffer1, StartPos)
  Call ClearArray(buffer2, 1)
  Call UnRePlaceCode(buffer1, buffer2)
  Call UnPointCode(buffer1, buffer2)
  Do
    Do Until Seek(SouFileNum) = EndPos And UBound(buffer1) - LBound(buffer1) = -1 Or UBound(buffer2) - LBound(buffer2) + 1 >= 65535 * 2
      DoEvents '防卡死
      Pro = Round((Seek(SouFileNum) - StartPos) / SouFileLen, 4) '进度计算
      If Cancel Then
        Close #DesFileNum
        UnExtract = -1
        Exit Function
      End If
      Seek #SouFileNum, LBound(buffer1)
      If EndPos - Seek(SouFileNum) >= 65535 * 2 Then RealLen = 65535 * 2 Else RealLen = EndPos - Seek(SouFileNum)
      ReDim buffer1(LBound(buffer1) To LBound(buffer1) + RealLen - 1)
      Seek #SouFileNum, LBound(buffer1)
      Get #SouFileNum, , buffer1
      Call UnRePlaceCode(buffer1, buffer2)
    Loop
    Call UnPointCode(buffer2, buffer3)
    Put #DesFileNum, , buffer3
    Call ClearArray(buffer3, UBound(buffer3) + 1)
  Loop Until UBound(buffer2) - LBound(buffer2) = -1 And Seek(SouFileNum) = EndPos And UBound(buffer1) - LBound(buffer1) = -1

End If

UnExtract = LOF(DesFileNum)
Close #DesFileNum '关闭文件
Pro = 1
Exit Function
Err: '错误处理
  Close #DesFileNum
  UnExtract = -1
  MsgBox "Error!"
End Function


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -