' These two events are very important for Importing. Respond to them
' So, always declare this class WithEvents
Public Event ImportSummary(ByVal ColumnHeadersIncluded As Boolean, ByVal ImageListsNeeded As Long, ByVal ListItems As Boolean, ByRef Continue As Boolean)
' This event is called to allow you to change any class properties and/or allow/prevent some things from being imported
' ColumnHeadersIncluded: Indicates whether or not the import file includes column headers.
' :: Here you should either allow or prevent column headers from being imported if the parameter is True
' :: To Allow
' ::: Ensure the class' IncludeColumnHeaders property is True
' ::: As a side note, set the class' IncludeHeaderTags property as desired
' :: To Prevent
' ::: Ensure the class' IncludeColumnHeaders property is False
' :: note... If no headers are provided or you prevent them from being imported, you should manually add them
' if the listview's View property is Report; otherwise, you may not see the items even though they exist
' ImageListsNeeded: If non-zero, ImageList(s) exist in the file and it is assumed that columnheaders and/or listitems use the imagelists
' :: Here you should either allow or prevent imagelists from being imported
' :: To Allow
' ::: Ensure the class' IncludeImageLists property is True
' ::: Reply to the SetImageList event and pass the ImportToImageList parameter when called
' -- At most, 3 image lists may be required. These can already exist or be created/destroyed dynamically
' -- Ensure any passed ImageList is not referenced by any other controls, else no images will be imported
' -- Images are never appended, the ImageList control is cleared and the exported images are uploaded
' -- The SetImageList event can be called up to 3 times
' :: To Prevent
' ::: Ensure the class' IncludeImageLists property is False
' ::: You may also reply to the SetImageList event and pass Nothing as the ImportToImageList parameter
' ::: If your ListView will be using an existing/populated imagelist control, ensure you set its references
' ListItems: FYI only, indicates how many list items exist in the file
' :: Here you should decide whether to clear the listview or not.
' :: If not cleared, the listitems will be appended to the listview
' ::: As a side note, set the class' IncludeListItemTags & IncludeTextFormatting properties as desired
' Continue: Passed as False. Set to True to allow import to continue else importing is aborted
Public Event SetImageList(ByVal ListViewSection As lvImportImageList, ByRef ImportToImageList As MSComctlLib.ImageList)
' Called only when these 2 cases are true
' 1. The file to import contains ImageList(s)
' 2. This class' IncludeImageLists property is True
' :: When called, it will only be called for each unique imagelist control required.
' -- If the SmallIcon and ColumnHeaderIcons ImageList references for the ListView are the same ImageList,
' then this is called only one time instead of twice
' -- This can be called from 1 to 3 times depending on how many unique ImageLists exist in the file to be imported
' :: If this event is not called (you prevented it from being called or there was no image list exported), you
' should manually set the listview's imagelist references if needed
' :: When Exporting, these properties should be set as desired BEFORE calling the ExportToFile function
' IncludeControlFormatting: Exports the ListView control's physical appearance both client & non-client area
' IncludeTextFormatting: Exports list item text forecolor & boldness
' IncludeColumnHeaders: Exports column headers and all their properties
' IncludeHeaderTags: Exports the column header tags, if any
' IncludeImageLists: Exports each ImageList control used by the ListView
' IncludeListItemTags: Exports each ListView ListItem & SubItem tag, if any
' Notes
' 1. The MsgBox calls in ImportFromFile & ExportToFile are more for debugging purposes. You may want to disable those lines & rely on the return function
' Kernel32/User32 APIs for Unicode Filename Support
Private Declare Function CreateFileW Lib "kernel32" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function SetFileAttributesW Lib "kernel32.dll" (ByVal lpFileName As Long, ByVal dwFileAttributes As Long) As Long
Private Declare Function SetFileAttributes Lib "kernel32.dll" Alias "SetFileAttributesA" (ByVal lpFileName As String, ByVal dwFileAttributes As Long) As Long
Private Declare Function GetFileAttributesW Lib "kernel32.dll" (ByVal lpFileName As Long) As Long
Private Declare Function GetFileAttributes Lib "kernel32.dll" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
Private Declare Function GetDesktopWindow Lib "user32.dll" () As Long
Private Declare Function IsWindowUnicode Lib "user32.dll" (ByVal hWnd As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, Optional ByVal lpOverlapped As Long = 0&) As Long
Private Declare Function ReadFile Lib "kernel32.dll" (ByVal hFile As Long, ByRef lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, ByRef lpNumberOfBytesRead As Long, Optional ByVal lpOverlapped As Long = 0&) As Long
Private Declare Function SetFilePointer Lib "kernel32.dll" (ByVal hFile As Long, ByVal lDistanceToMove As Long, ByRef lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Const INVALID_HANDLE_VALUE = -1
Private Const FILE_ATTRIBUTE_NORMAL = &H80&
' used for workaround of VB not exposing IStream interface
Private Declare Function DispCallFunc Lib "oleaut32" (ByVal ppv As Long, ByVal oVft As Long, ByVal cc As Long, ByVal rtTYP As VbVarType, ByVal paCNT As Long, ByVal paTypes As Long, ByVal paValues As Long, ByRef fuReturn As Variant) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal uFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function CreateStreamOnHGlobal Lib "ole32" (ByVal hGlobal As Long, ByVal fDeleteOnRelease As Long, pPStm As Any) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GetHGlobalFromStream Lib "ole32" (ByVal pPStm As Long, hGlobal As Long) As Long
Private Declare Function OleSaveToStream Lib "ole32.dll" (ByVal pPStm As Long, ByVal pStm As stdole.IUnknown) As Long
Private Declare Function OleLoadPicture Lib "olepro32" (pStream As Any, ByVal lSize As Long, ByVal fRunmode As Long, riid As Any, ppvObj 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)
' These structures are used to help organize code & make code more user-friendly
Private Type StructureFileHeader
MagicNumber As Long ' identifier for this type of file
Version As Single ' version (integer=Ansi, decimal=Unicode)
ImageListOffset As Long
HeadersOffset As Long ' position in file where column headers begin
ListItemOffset As Long ' position in file where listitems begin
Columns As Long ' number of column headers
Items As Long ' how many list items
ImageLists As Long ' number of exported listimages
Flags As Long ' whether headers/imagelists/tags are written to file
ListViewStructSize As Long ' size of the StructureListview used
End Type ' 36 bytes used for import/export
Private Type StructureListView
AllowColumnReorder As Byte
AppearanceFlat As Byte
BorderStyleNone As Byte
Checkboxes As Byte
FlatScrollBar As Byte
FullRowSelect As Byte
GridLines As Byte
HideColumnHeaders As Byte
HotTracking As Byte
HoverSelection As Byte
LabelEditManual As Byte
LabelWrap As Byte
MultiSelect As Byte
Sorted As Byte
SortOrderDesc As Byte
TextBkgOpaque As Byte ' 16 bytes
Arrange As Integer
PictureAlignment As Integer
SortKey As Integer
View As Integer ' 8 bytes
BackColor As Long
ForeColor As Long ' 8 bytes
Tag As String ' 4 bytes (not used for export, used for import)
End Type ' 32 bytes used for export
Private Type StructureHeaders
Position As Long
Left As Single
Width As Single ' 12 bytes
Alignment As Integer
TagType As Integer
IconType As Integer ' 6 bytes (18 bytes used for export)
Text As String ' 4 bytes (following used during import only)
Key As String ' 4 bytes
Tag As Variant ' 16 bytes
Icon As Variant ' 16 bytes
End Type
Private Type StructureImageList
Count As Long
BackColor As Long
MaskColor As Long ' 12 bytes
ImageWidth As Integer
ImageHeight As Integer
UseMaskColor As Boolean ' 6 bytes
Tag As String ' 4 bytes
End Type ' 18 bytes used for export
Private Type StructureListItem
SubCount As Long
ForeColor As Long
IconTypes As Long ' 12 bytes
TagType As Integer
BoldChecked As Integer ' 4 bytes
Text As String
Tooltip As String
Key As String
IconSm As Variant
IconLg As Variant
Tag As Variant ' 16 bytes used for export, all used for import
End Type
Private Type StructureListSubItem
ForeColor As Long ' 4 bytes
IconType As Integer
TagType As Integer ' 4 bytes
Bold As Byte ' 1 byte
Text As String
Tooltip As String
Key As String
ReportIcon As Variant
Tag As Variant ' 9 bytes used for export, all used for import
End Type
Private Type StructureFont
Attributes As Long ' bold,italic,underline,strikethru
CharSet As Integer
Weight As Integer
Size As Currency ' 16 bytes used for export, all used for import
Name As String
End Type
Public Enum lvImportImageList
ilColumnHeaders = 1
ilLargeIcons = 2
ilSmallIcons = 3
End Enum
Private Enum lvFlags
fgHasImageList = 1
fgHasHeaderTags = 2
fgHasItemTags = 4
fgHasHeaders = 8
fgHasCtrlFormat = 16
fgHasTextFormat = 32
End Enum
Private c_Flags As Long
Private lvObject As MSComctlLib.ListView
Public Property Let IncludeImageLists(ByVal bInclude As Boolean)
' initialized to False during class load
' Exporting: If True, will cache the imagelist controls used by the listview to the same file, including all images else will not
' Importing: If True, will overwrite existing imagelist controls (see 3 ImageList properties below) control & repopulate with the one saved in the file
' :: If no imagelist was saved in the file, nothing will be done the imagelists
' :: If property is False, no images will be extracted from the file
If bInclude <> Me.IncludeImageLists Then c_Flags = c_Flags Xor fgHasImageList
End Property
Public Property Get IncludeImageLists() As Boolean
IncludeImageLists = CBool(c_Flags And fgHasImageList)
End Property
Public Property Let IncludeColumnHeaders(ByVal bInclude As Boolean)
' initialized to True during class load
' Exporting: If True, will include column headers and their individual properties else will not
' Importing: If True, will clear the listiview and repopulate the headers from the file
' :: If no column headers were saved in the file, then nothing will be done to the listview's original header columns
' :: If property is False, no column headers will be extracted from the file
If bInclude <> Me.IncludeColumnHeaders Then c_Flags = c_Flags Xor fgHasHeaders
End Property
Public Property Get IncludeColumnHeaders() As Boolean
IncludeColumnHeaders = CBool(c_Flags And fgHasHeaders)
End Property
Public Property Let IncludeHeaderTags(ByVal bInclude As Boolean)
' initialized to False during class load
' Exporting: If True, column header tags will be exported to the file else they will not
' Importing: Applies only if IncludeColumnHeaders is True
' :: If True, exported column header tags will be added to new column headers else null tags will be set
' :: If the file was exported without column header tags, no action is taken
If bInclude <> Me.IncludeHeaderTags Then c_Flags = c_Flags Xor fgHasHeaderTags
End Property
Public Property Get IncludeHeaderTags() As Boolean
IncludeHeaderTags = CBool(c_Flags And fgHasHeaderTags)
End Property
Public Property Let IncludeListItemTags(ByVal bInclude As Boolean)
' initialized to False during class load
' Exporting: If True, list item tags & subItem tags will be exported to the file else they will not
' Importing: If True, exported tags will be added to listItems & subItems else null tags will be set
' :: if the file was exported without tags, no action is taken
If bInclude <> Me.IncludeListItemTags Then c_Flags = c_Flags Xor fgHasItemTags
End Property
Public Property Get IncludeListItemTags() As Boolean
IncludeListItemTags = CBool(c_Flags And fgHasItemTags)
End Property
Public Property Let IncludeControlFormatting(ByVal bInclude As Boolean)
' initialized to True during class load
' Exporting: If True, the physical appearance of the listview control will be exported (borders, colors, font, picture, etc)
' Importing: If True, the imported listview control will be changed to match the exported appearance
' :: if the file was exported without the appearance, no action is taken
If bInclude <> Me.IncludeControlFormatting Then c_Flags = c_Flags Xor fgHasCtrlFormat
End Property
Public Property Get IncludeControlFormatting() As Boolean
IncludeControlFormatting = CBool(c_Flags And fgHasCtrlFormat)
End Property
Public Property Let IncludeTextFormatting(ByVal bInclude As Boolean)
' initialized to True during class load
' Exporting: If True, the physical appearance of the listview items will be exported (colors, boldness)
' Importing: If True, the imported listitems will be changed to match the exported appearance
' :: if the file was exported without the appearance, no action is taken
If bInclude <> Me.IncludeTextFormatting Then c_Flags = c_Flags Xor fgHasTextFormat
End Property
Public Property Get IncludeTextFormatting() As Boolean
IncludeTextFormatting = CBool(c_Flags And fgHasTextFormat)
End Property
Public Property Get ListViewReference() As MSComctlLib.ListView
' ReadOnly property. Can be called during one of the public events if desired
' to see which listview is being imported into
Set ListViewReference = lvObject
End Property
Public Function ExportToFile(ListView As MSComctlLib.ListView, FileName As String, Optional SaveStringsANSI As Boolean = True) As Boolean
' Parameter SaveStringsANSI
' :: can reduce filesize, but is slower overall
' :: if using unicode strings for any part of the listview, set this to False
If ListView Is Nothing Then Exit Function
If FileName = vbNullString Then Exit Function
Dim fileNum As Long, useUnicode As Boolean, bSuccess As Boolean
Dim offsetHDR As Long, offsetLI As Long, offsetIL As Long
Dim vWritten As Long, imgListCount As Long
If IsWindowUnicode(GetDesktopWindow) Then useUnicode = True
Private Function WritePicture(fileNum As Long, thePicture As StdPicture) As Boolean
' Writes a picture property to file, preceding it with byte length
Dim o_hMem As Long, o_lpMem As Long
Dim o_lngByteCount As Long
Dim vWritten As Long, bSuccess As Integer
' In order to use the OLESaveToStream function, we need the pointer to the IPersistStream interface
' This portion will return that pointer if the interface is implemented
Dim varRtn As Variant, pIPS As Long
Dim aGUID(0 To 3) As Long, IFauxStream As IUnknown
Dim pvTypes(0 To 1) As Integer, pvPtrs(0 To 1) As Long, pValues(0 To 1) As Variant
Const IUnknownQueryInterface As Long = 0& ' IUnknown vTable offset to Query implemented interfaces
Const IUnknownRelease As Long = 8& ' IUnkownn vTable offset to decrement reference count
Const CC_STDCALL As Long = 4&
aGUID(0) = &H109 ' GUID for IPersistStream (00000109-0000-0000-C000-000000000046)
aGUID(2) = &HC0
aGUID(3) = &H46000000
If Not thePicture Is Nothing Then
If thePicture.Handle Then
On Error GoTo CATCH_EXCEPTION
g, IFauxSpvPtrverts variable typ he inteAs Long = 8&x)uted in Lo (000Pn ryInterL_EXCEPTION
nkn he inteAs Long ew beO (000Pn rLror GVong tream , IFauxSpvPtrveIng, IFauxSpvPtrverts variable typ he inIng, n1nteAs r(theStrihe inI)riteF
00Pnp-g, n1nteAs r(theeeeeeeeeeeeeeeee(000PPn otg ewng, Im ,anp-g, n1nteAs r(theeeeeeeeeeeeeeeee(000PPn otRNSI or Unicode sct Case VarType(.Tag)SGinteAs Lerence (sct C10PPn of Notng ew eee(000PPn otg ewng, Im ,anp-g, n1nteAs r(theeeeeeeeeeeeeeeee(000PPn otRNSI or Unicode sct Case VarType(-otg e sct Case VarType(-otg e sct nW(StrPtadFile fileNum,_heeeeeeeeeeeeeeeee(000PPn otRNSI or Unicode scte(-otg e sd Fu otRNSI or Unicode scte(-ote
Rea n1nteAs r(theeeeeeicodeI or Unicode scte(-ote
Rea n1nteAs r(theeeeeeicodeI or Unicode scte(-ote
Rea n1nteAs r(theeeeeeicodeI or Unicode scte(-ote
oo,Lrence (sct C10PPnISTING = & otRNSI or UnicoUnicoUnicoUnicoUnicoUnicoUnicoUd iS, vWricoUnicoUnicoUnicoUnren at As Booleanleanleanleanleanleatnicode scte(-otg e sd Fu otRNSI eadFile fileNum, ByVal StrrType(-otg e sct= Dim sDazcnleanltTTRIBUFauxSpvPtrverts vaT,sd Fu otRNSI eanicoUnren at As igU= de vWric/p& refm sDat eadFile fileNum, ByVric/p& refm sDat eadFt Fu Trver6e Function ReadImagev TAion = CREATE_ALWAYS prompted: 4ReadImagev Longee(-ote2, Longee(-gee(-o(theten AsaIf lLen Theneten AsaIf lLen Theneten A= CREATE_ALWAYS prompted: 4ReadImagev LongeeWAYS pren at As Booleanleanleanleanleanleatnicode scte(-otg e sd Fu otRNSI eadFile fileNum, ByVal StyVric/p& refm ansiStrings As n at As Booleanleat AWnt, pIPS As Long
Dim aGUID(0 To 3) As Long, IFa' This pope0 To 3Wnt, pPS As Long
D(-ote.theeeeeeicodeI or Unicode scte(-gT
If Not thengnicoUniicoUnicoUnicoUnicoUnicoUnicoUnicoUd iS,ecod istSEnd If
If Flags < 0& Theny imeteIfUnico VFile fil rnd Ifinf Flany (End If
cNI( If Not ttttt byeger de vUd iSTag
Retute.BdFir de vUd iSTaB Case vbInteger
IFat As Long
Dim vWrit CoV, p
e scte Thenoe The de vUdoV, ng, Im ,anp-g, n1nteAWrit CoV, pe vUdoV, ng, Im ,anp ,iicoUnicoUnicccccccccc Rea n1nteAs r(thWrit CoV, p
e scte Thenoe The de vUdosposition, Flags, 0&)
As n at As sctI r(thWrit CoV (000Pn ryInterL_EXCEslee poag)tr Flags, 0&)
As n at As sctI r(thWrit Pcte &)
As n at A LoPit YS = l r(toStRea n1ntf
vWrit Pcte &)
As n at A LoPlPn otRNSI or UnicoiR ConsV, ng, Im ,anp-g, n1nteAWrit CoV, pe OSnp-g, n1nteAWrL As Long = 4&
Colose vbLtt ConsVooooooleatn Cas vaAs Lo As n at A LoPiEI Read As n at A, vRead
IUnknownReleasGn = 2&)
Case vbBooleao As n at UnknownRen bAs n at A, vRead
tr Flags, 0&)
As Dim As n at A, vReadie pos1nteAWrt A, K
Case vbLong
End If
End , v Long, vWrnAemeTo 3eadFileadFileadFileadFibAsnrt A, K
Case vbLong
ansiSt,onsVooooooleatn Cas vaAs,pt A LoPil it wi Wr6a(StrPtr(F at UnknK
C
AexItm.Tag = udtLI.T iSTLItm.T.Keyoleatn Cas vaAWrit Petr Flagcte &)r9p(RaareicodeI or Unicode scte(-t wi Wr6 As Long iSTLItm.T. aGUID(2) = &HC0
WAWrit Petr Flagcte &)r9p(rtIco otg ewng, Im ,anp-g, n1nteAs r(theeeeeeeeeeeeeeeR As Long iSTLItm.T. aGUID(2) = nteger
C0
WAWrit Petr Flagcte &)r9p(rtIor eeeeee, tSizttena8&)
Case El 2&)
P If vRead = lLen Then
toString = StrConv(sData(), vbUnicode)
ReadString = ToEWrL As Lt A, vReadie pos1nteAWrt Rea_schoC
bUnicode)
icture)eicode)ts =f vRead = lLen Then
c CSAs Boolean,tt byege= ToEWrL Aase VarType(.Tag)
Case vb As n at As sct As Dim n
c CSAs Boolean,tiHte(vTag), 1&, vWritten
tT. aGUID(2) = ntegerad = lit YSSSSSSSSSSS ConsV,
c CSAs Boolean,t Case vb As n r6a(StrPtr(F at Unric/p& refm sDat ,(sct C10PPwStructureListSubItem
Dim vnGUID(nicoUn
P If vR EATEV,
tream , IFauxSpveanleAs LonqvnGUID(nicoUn
P LonqvneeeeeeeR As Long iSTLItm.T. aGUID(1nteAWrt Re
P Lonqvneeeeeong
DnicoUn
FT. aGUID(at UnknownRen bAs If vAs Lture)ei_rnicoUnt:ings As BooleaoU IFauxSpveanleAs LonqvnGUID(tUnt:ings A As Boolo Re