MikeD
8/30/2010 2:47:00 PM
"MikeD" <nobody@nowhere.edu> wrote in message
news:i5gbn9$ghp$1@news.eternal-september.org...
> Another way you may want to consider IF you're only supporting Windows XP
> and later AND IF you're using the VB5 version of the ListView control is
> to use flags that were added to the Common Controls Library beginning with
> XP. These flags are HDF_SORTUP and HDF_SORTDOWN. You specify them in an
> HDITEM structure (assign one or the other to the fmt member of the
> structure) and send the HDM_SETITEM message to the Header control. To get
> the hwnd of the Header control, you have to send the ListView an
> LVM_GETHEADER message.
Here's some example code that I just threw together if you're interested
further in this method. As mentioned, you have to use the VB5 version
ListView. Additionally, you will need to use a manifest file because you
must use version 6 of Windows' Common Control DLL (which is also why you
must use the VB5 ListView since the VB6 ListView is not dynamically linked
to this DLL). This will work in the IDE *IF* you use a manifest file for
VB6. Here's the contents of the manifest file that I use:
---------------------
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="Microsoft.VB6.VisualStyles"
type="win32"
/>
<description>Manifest for Visual Basic 6 IDE</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
---------------------
Copy and paste into Notepad what's between the dashed lines. Name the file
"vb6.exe.manifest" and put it in the same directory where vb6.exe is
located.
Here's the code (watch out for any possible word-wrapping):
-----BEGIN CODE
Option Explicit
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As
Any) As Long
Private Type DLLVERSIONINFO
cbSize As Long
dwMajor As Long
dwMinor As Long
dwBuildNumber As Long
dwPlatformID As Long
End Type
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA"
(ByVal lpLibFileName As String) As Long
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As
Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As
Long, ByVal lpProcName As String) As Long
Private Declare Function DllGetVersion Lib "comctl32" (pdvi As
DLLVERSIONINFO) As Long
Private Declare Sub InitCommonControls Lib "comctl32" ()
Private Const LVM_FIRST As Long = &H1000
Private Const LVM_GETHEADER As Long = LVM_FIRST + 31
Private Type HDITEM
mask As Long
cxy As Long
' pszText As String
pszText As Long
hbm As Long
cchTextMax As Long
fmt As Long
lParam As Long
iImage As Long
iOrder As Long
End Type
Private Const HDM_FIRST As Long = &H1200
Private Const HDM_SETITEM As Long = HDM_FIRST + 4
Private Const HDI_FORMAT As Long = &H4
Private Const HDF_STRING As Long = &H4000
Private Const HDF_SORTUP As Long = &H400&
Private Const HDF_SORTDOWN As Long = &H200&
Private Sub Form_Initialize()
InitCommonControls
End Sub
Private Sub ListView1_ColumnClick(ByVal ColumnHeader As
ComctlLib.ColumnHeader)
Dim hd As HDITEM
Dim lSortArrowFlag As Long
Dim hHeader As Long
Dim lAlignment As Long
Dim Index As Long
'(code for sorting column)
With ListView1
.SortKey = ColumnHeader.Index - 1
If .SortOrder = lvwAscending Then
.SortOrder = lvwDescending
lSortArrowFlag = HDF_SORTDOWN
Else
.SortOrder = lvwAscending
lSortArrowFlag = HDF_SORTUP
End If
.Sorted = True
End With
'Can only use sort arrow flags for common controls DLL version 6 or
later
If GetCommonControlsDLLVersion >= 600 Then
'Get a handle to the listview header control
hHeader = SendMessage(ListView1.hwnd, LVM_GETHEADER, 0&, ByVal 0&)
'The sort arrow is not automatically removed from column headers,
'so we must do this; easiest (IMO) to just loop through all column
headers
'but you could cache the previous column header's index if you
wanted.
For Index = 1 To ListView1.ColumnHeaders.Count
lAlignment = ColumnHeader.Alignment
With hd
.mask = HDI_FORMAT
.pszText = StrPtr(ColumnHeader.Text)
.fmt = HDF_STRING Or lAlignment
'Modify the header; Need to subtract 1 for the column
header's index because the API is 0-based
Call SendMessage(hHeader, HDM_SETITEM, Index - 1, hd)
End With
Next
'Now add the appropriate sort arrow for the sorted column
With hd
.mask = HDI_FORMAT
.pszText = StrPtr(ColumnHeader.Text)
lAlignment = ColumnHeader.Alignment
.fmt = HDF_STRING Or lSortArrowFlag Or lAlignment
'Modify the header; Need to subtract 1 for the column header's
index because the API is 0-based
Call SendMessage(hHeader, HDM_SETITEM, ColumnHeader.Index - 1,
hd)
End With
End If
End Sub
Private Function GetCommonControlsDLLVersion() As Long
'Version 4.71 is shipped with IE 4.00
'Version 4.72 is shipped with IE 4.01
'Version 5.80 is shipped with IE 5.0
'Version 5.81 is shipped with IE 5.01
'Version 5.82 is shipped with Windows XP, Vista, and Server 2008
(returns this version if not using a manifest)
'Version 6.00 is shipped with Windows XP, Vista, and Server 2008
(returns this version if using a manifest)
Dim hModule As Long
Dim lDllGetVersionAddress As Long
Dim dvi As DLLVERSIONINFO
Dim lRet As Long
Dim lMajor As Long
Dim lMinor As Long
hModule = LoadLibrary("comctl32.dll")
If hModule Then
'See if the DllGetVersion function is exported by commctrl.dll
lDllGetVersionAddress = GetProcAddress(hModule, "DllGetVersion")
If lDllGetVersionAddress = 0 Then
'The function is not exported which means the version
'of comctl32.dll is 4.0 or 4.70....assume the lesser
lMajor = 4
lMinor = 0
Else
'It is, so let's get the version of it
With dvi
.cbSize = Len(dvi)
lRet = DllGetVersion(dvi)
If lRet = 0 Then
lMajor = .dwMajor
lMinor = .dwMinor
End If
End With
End If
'Make sure we free the library
FreeLibrary hModule
End If
GetCommonControlsDLLVersion = CLng(Format$(lMajor, "00") &
Format$(lMinor, "00"))
End Function
-----END CODE
If your Listview isn't named ListView1, be sure to change the code.
--
Mike