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

📄 cicoparser.cls

📁 AeroSuite--一组非常漂亮的VISTA控件集
💻 CLS
📖 第 1 页 / 共 3 页
字号:
VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "cICOparser"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

' No APIs are declared public. This is to prevent possibly, differently
' declared APIs, or different versions of the same API, from conflciting
' with any APIs you declared in your project. Same rule for UDTs.
' Note: I did take some liberties in several API declarations throughout

' Used for creating array overlays at other memory addresses
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (ByRef Ptr() As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)

' used to create images as needed
Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As Long, ByVal hDC As Long) As Long
Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hDC As Long) As Long
Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hDC As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
Private Declare Function CreateDIBitmap Lib "gdi32.dll" (ByVal hDC As Long, ByRef lpInfoHeader As BITMAPINFOHEADER, ByVal dwUsage As Long, ByRef lpInitBits As Any, ByRef lpInitInfo As Any, ByVal wUsage As Long) As Long
Private Declare Function GetDIBits Lib "gdi32.dll" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, ByRef lpBits As Any, ByRef lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
Private Declare Function GetGDIObject Lib "gdi32.dll" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, ByRef lpObject As Any) As Long
Private Declare Function GetIconInfo Lib "user32.dll" (ByVal hIcon As Long, ByRef piconinfo As ICONINFO) As Long
Private Declare Function DrawIcon Lib "user32.dll" (ByVal hDC As Long, ByVal x As Long, ByVal y As Long, ByVal hIcon As Long) As Long

Private Type ICONINFO
    fIcon As Long
    xHotspot As Long
    yHotspot As Long
    hbmMask As Long
    hbmColor As Long
End Type
Private Type BITMAP
    bmType As Long
    bmWidth As Long
    bmHeight As Long
    bmWidthBytes As Long
    bmPlanes As Integer
    bmBitsPixel As Integer
    bmBits As Long
End Type
Private Type BITMAPINFOHEADER
    biSize As Long
    biWidth As Long         ' +4 from .biSize
    biHeight As Long        ' +8
    biPlanes As Integer     ' +12
    biBitCount As Integer   ' +14
    biCompression As Long   ' +16
    biSizeImage As Long     ' +20
    biXPelsPerMeter As Long ' +24
    biYPelsPerMeter As Long ' +28
    biClrUsed As Long       ' +32
    biClrImportant As Long  ' 40th byte
End Type
Private Type BITMAPINFO
    bmiHeader As BITMAPINFOHEADER
    bmiPalette(0 To 255) As Long
End Type

Private Type SafeArrayBound
    cElements As Long
    lLbound As Long
End Type
Private Type SafeArray          ' used as DMA overlay on a DIB
    cDims As Integer
    fFeatures As Integer
    cbElements As Long
    cLocks As Long
    pvData As Long
    rgSABound(0 To 1) As SafeArrayBound ' reusable UDT for 1 & 2 dim arrays
End Type

Private Type ICONDIRENTRY
    bWidth As Byte '// Width, in pixels, of the image
    bHeight As Byte '// Height, in pixels, of the image
    bColorCount As Byte '// Number of colors in image (0 if >=8bpp)
    bReserved As Byte '// Reserved ( must be 0)
    wPlanes As Integer '// Color Planes
    wBitCount As Integer '// Bits per pixel
    dwBytesInRes As Long '// How many bytes in this resource?
    dwImageOffset As Long '// Where in the file is this image?
End Type

Private Type ICONDIR
    idReserved As Integer '// Reserved (must be 0)
    idType As Integer '// Resource Type (1 for icons)
    idCount As Integer '// How many images?
    idEntries() As ICONDIRENTRY '// An entry for each image (idCount of 'em)
End Type

Private Const png_Signature1 As Long = 1196314761   ' 1st 8 bytes of a PNG file start with these 8 bytes
Private Const png_Signature2 As Long = 169478669

Private m_icDirE() As ICONDIRENTRY  ' collection of icon directory entries
Private m_icDir As ICONDIR          ' icon directory
Private m_Bits() As Byte            ' icon bits

Public Property Get Height(Index As Long) As Long
    Height = m_icDirE(Index).bHeight    ' height of icon
    If Height = 0& Then Height = 256&   ' 256x256 icons are identified as 0 in the icon structure
End Property
Public Property Get Width(Index As Long) As Long
    Width = m_icDirE(Index).bHeight     ' width of icon
    If Width = 0& Then Width = 256&     ' 256x256 icons are identified as 0 in the icon structure
End Property

Public Property Get IsIconPNG(Index As Long) As Boolean
    IsIconPNG = m_icDirE(Index).wPlanes = 255   ' custom flag to distinguish PNG from icon
End Property
Public Property Get bitDepth(Index As Long) As Long
    bitDepth = m_icDirE(Index).wBitCount    ' bit count/depth of icon
End Property

Public Property Get IconCount() As Long
    IconCount = m_icDir.idCount
End Property

Public Property Get ColorCount(Index As Long) As Long
    ' for paletted non-PNG images, number of colors that exist
    ' This should be straight forward and is generally supplied in the icon entry's .bColorCount
    ' member. But maybe .bColorCount may not be telling us the truth or it may be missing.
    
    ' To get the proper number supplied with the icon/bitmap, we will add the total bytes
    ' used for the image & mask bytes, then add that to the bytes used for the header.
    ' The difference/4 will always be correct.
    Dim imageBits As Long, headerBits As Long
    If m_icDirE(Index).wBitCount < 9 Then
        imageBits = ColorByteCount(Index) + MaskByteCount(Index)
        headerBits = m_Bits(m_icDirE(Index).dwImageOffset)
        ColorCount = (m_icDirE(Index).dwBytesInRes - (imageBits + headerBits)) \ 4&
    End If
End Property

Public Property Get ColorByteOffset(Index As Long) As Long
    ' Return the position in the source stream where the 1st byte of the color image
    ' can be found; not called for PNGs
    Dim Offset As Long
    CopyMemory Offset, m_Bits(m_icDirE(Index).dwImageOffset), 4& ' header bytes
    Offset = m_icDirE(Index).dwImageOffset + Offset ' shift offset to where icon structure begins
    ' when image is paletted, the palette is included too
    If m_icDirE(Index).wBitCount < 16 Then          ' get number of colors used in image
        Offset = Offset + (2& ^ m_icDirE(Index).wBitCount) * 4& ' add that to the offset
    End If
    ColorByteOffset = Offset
End Property

Private Property Get MaskByteOffset(Index As Long) As Long
    ' Return the position in the source stream where the 1st byte of the mask image
    ' can be found; not called for PNGs. Here we work from the end of the icon structure
    Dim Offset As Long
    
    ' Note: 32bpp icons have masks too
    Offset = m_icDirE(Index).dwImageOffset + m_icDirE(Index).dwBytesInRes
    Offset = Offset - MaskByteCount(Index)
    MaskByteOffset = Offset
End Property

Private Property Get ColorByteCount(Index As Long) As Long
    ' Return the number of image bytes used for the color image; not PNGs
    ColorByteCount = iparseByteAlignOnWord(m_icDirE(Index).bWidth, m_icDirE(Index).wBitCount) * m_icDirE(Index).bHeight
End Property
Private Property Get MaskByteCount(Index As Long) As Long
    ' Return the number of image bytes used for the mask image; not PNGs
    MaskByteCount = iparseByteAlignOnWord(m_icDirE(Index).bWidth, 1&) * m_icDirE(Index).bHeight
End Property

Public Function LoadStream(inStream() As Byte, _
                ByVal desiredWidth As Long, ByVal desiredHeight As Long, _
                cHost As c32bppDIB, streamOffset As Long, streamLength As Long, _
                icoBitDepth As Long, Optional GlobalToken As Long) As Boolean

    ' Purpose: Parse byte stream to determine if it is an icon file.
    '   If it is an icon file, then select the best match for the passed
    '   size and create our application's main image from the icon
    ' Note: GIF, JPG, BMP, PNG & other formats have a magic number that
    '   indicates what type of file it is. Icons/cursors do not; so we parse & error check
    
    ' Parameters:
    ' inStream() :: an array of the icon file; can consist of more than one icon
    ' desiredWidth :: width of icon to use, if available, else used for closest match
    ' desiredHeight :: height of icon to use, if available, else used for closest match
    ' cHost :: the application's image class
    
    ' IMPORTANT: the array offset & length are not checked in this class.
    '   They were checked before this class was called. If this class is to
    '   be pulled out and put in another project, ensure you include the
    '   validation shown in c32bppDIB.LoadPicture_Stream
    
    Dim icEntry As Long, icValue As Long
    Dim icPtr As Long, icBytesNeed As Long
    Dim bIconFile As Boolean
    
    Dim tDC As Long, hDib As Long, dDC As Long, hObj As Long
    Dim tSA As SafeArray
    Dim tBMPI As BITMAPINFO
    Dim cPNG As cPNGparser
    
    With tSA                    ' overlay the passed stream with our module-level array
        .cbElements = 1         ' as byte
        .cDims = 1              ' as 1 dimensional
        .pvData = VarPtr(inStream(LBound(inStream)))
        If streamLength = 0 Then streamLength = UBound(inStream) + 1
        .rgSABound(0).cElements = streamLength
    End With
    CopyMemory ByVal VarPtrArray(m_Bits), VarPtr(tSA), 4& ' establish overlay
    
    icBytesNeed = 6&                        ' length of the ICONDIRECTORY
    If icPtr + icBytesNeed <= streamLength Then    ' ensure enough bytes exist
        bIconFile = True                    ' good, let's continue
        ' cache the ICONDIRECTORY
        CopyMemory m_icDir.idReserved, m_Bits(icPtr), icBytesNeed
        If m_icDir.idCount < 1 Then         ' no icons or not an icon file
            bIconFile = False
        ElseIf Not m_icDir.idReserved = 0 Then  ' per MSDN, must be zero
            bIconFile = False
        ElseIf m_icDir.idType < 1 Or m_icDir.idType > 2 Then
            bIconFile = False               ' per MSDN, must be 1 or 2 (1=icon,2=cursor)
        Else
            icPtr = icPtr + icBytesNeed     ' move array pointer
            icBytesNeed = 16&               ' length of directory entry
            If icPtr + icBytesNeed * m_icDir.idCount > streamLength Then
                bIconFile = False           ' not enough bytes for expected entries
            Else
                ReDim m_icDirE(1 To m_icDir.idCount)        ' size our entries
                icBytesNeed = m_icDir.idCount * icBytesNeed ' & cache them
                CopyMemory m_icDirE(1).bWidth, m_Bits(icPtr), icBytesNeed
                icBytesNeed = icBytesNeed + 6&       ' move array pointer
                For icEntry = 1 To m_icDir.idCount
                    ' each entry indicates how many bytes are used for it.
                    ' total the bytes and ensure enough bytes exist
                    icBytesNeed = icBytesNeed + m_icDirE(icEntry).dwBytesInRes
                Next
                If icBytesNeed > streamLength Then bIconFile = False ' not enough bytes
            End If

⌨️ 快捷键说明

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