Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsVB SyntaxEnterprise DevelopmentDatabase AccessControlsCOMWin APICrystal ReportDeploymentGeneralGeneral 2
Related Topics
VB.NET / ASP.NETMS SQL ServerMS AccessOther Database ProductsMore Topics ...

VB Forum / Win API / September 2008



Tip: Looking for answers? Try searching our database.

ListView ColumnHeader caption via API?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Markus Colorado - 08 Sep 2008 15:52 GMT
Hi,

I'm trying to read the column header (SysHeader32) captions of an ListView. So far
I'm sure to have the right processID and handle (hWnd) , beacause I can successfully
read the right number of columns, but I do not get any text (caption) for each
column. I always get back an empty string for each column-text, although SendMessage
returns "1" as result. I would really need the captions of the listview...

Below are the relevant code-snipplets (vb.net).
Concerning WinAPI I think it's not relevant if it's written in (classic) VB or in
.NET.

Has anybody a hint  - or even better a solution ;-)) - for me how to read the
captions of each column-header.

Thnaks for any help in advance.
Regards,
Markus

---------- [code begin] ----------
Public Enum HDM As Integer
  HDM_FIRST = &H1200
  HDM_GETITEMCOUNT = (HDM_FIRST + 0)
  HDM_GETITEMA = (HDM_FIRST + 3)
  HDM_GETITEM = HDM_GETITEMA
  HDM_SETITEM = (HDM_FIRST + 4)
  HDM_SETIMAGELIST = (HDM_FIRST + 8)
  HDM_GETIMAGELIST = (HDM_FIRST + 9)
End Enum

<StructLayout(LayoutKind.Sequential)> _
Public Structure HDITEM
  Public mask As Integer
  Public cxy As Integer
  Public pszText As String
  Public hbm As IntPtr
  Public cchTextMax As Integer
  Public fmt As Integer
  Public lParam As Integer
  Public iImage As Integer
  Public iOrder As Integer
  Public type As UInteger
  Public pvFilter As IntPtr
End Structure

<DllImport("user32.dll")> _
Private Overloads Shared Function SendMessage( _
                                       ByVal hWnd As IntPtr, _
                                       ByVal msg As Integer, _
                                       ByVal wParam As IntPtr, _
                                       ByVal lParam As IntPtr) As IntPtr
End Function

<DllImport("user32.dll")> _
Public Overloads Shared Function SendMessage( _
                                       ByVal hWnd As IntPtr, _
                                       ByVal msg As Integer, _
                                       ByVal wParam As Integer, _
                                       ByRef hdi As HDITEM) As Integer
End Function

Public Shared Sub ListView_GetColumnNames(ByVal hWnd As IntPtr)
  Dim iCols As Integer = SendMessage(hWnd, HDM.HDM_GETITEMCOUNT, 0, 0)
  Utilities.Debug(">> iCols: " & iCols.ToString)
  For i As Integer = 0 To iCols - 1
     Dim hditm As HDITEM = New HDITEM
     hditm.cchTextMax = 32
     hditm.pszText = New String(Chr(0), hditm.cchTextMax)      ''Space$(32)
     hditm.mask = CType(HDI.HDI_WIDTH, Integer) Or _
                          CType(HDI.HDI_FORMAT, Integer)
     hditm.fmt = CType(HDF.HDF_STRING, Integer) Or _
                       CType(HDF.HDF_BITMAP_ON_RIGHT, Integer)
     If SendMessage(hWnd, HDM.HDM_GETITEM, i, hditm) = 1 Then
        Dim sText As String = StripNulls(hditm.pszText) & _
               " {" & (hditm.pszText).Length & "}"
        Utilities.Debug("[" & i.ToString & "]: iRes=1 | sText = " & sText)
     Else
        Utilities.Debug("[" & i.ToString & "]: iRes<>1 | sText = #####")
     End If
  Next
End Function

Private Shared Function StripNulls(ByVal OriginalStr As String) As String
  ' This removes the extra Nulls so String comparisons will work
  If (InStr(OriginalStr, Chr(0)) > 0) Then
     OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
  End If
  Return OriginalStr
End Function
---------- [code end] ----------
MikeD - 09 Sep 2008 02:40 GMT
> Hi,
>
[quoted text clipped - 8 lines]
> Concerning WinAPI I think it's not relevant if it's written in (classic)
> VB or in .NET.

No, it IS relevant. That code's quite different from what you'd write in
VB6...for one, data types are not the same.

If you want a VB.NET solution, you need to ask in a newsgroup with dotnet or
vsnet in the name.

Signature

Mike
Microsoft MVP Visual Basic

Markus Colorado - 09 Sep 2008 11:34 GMT
There is no .NET ng dealing with WinAPI; so I took this ng.
I will rewrite my code-snip in VB6....hoping anybody will give a helpful reply then.

Markus

>> Hi,
>>
[quoted text clipped - 14 lines]
> If you want a VB.NET solution, you need to ask in a newsgroup with dotnet or vsnet
> in the name.
Dean Earley - 09 Sep 2008 12:12 GMT
>>> Hi,
>>>
[quoted text clipped - 16 lines]
> There is no .NET ng dealing with WinAPI; so I took this ng.
> I will rewrite my code-snip in VB6....hoping anybody will give a helpful reply then.

As long as you confirm it is broken in exactly the same way.
You may also want to try cross posting to
microsoft.public.win32.programmer.ui and microsoft.public.platformsdk.ui
if the problem is not language specific.

Signature

Dean Earley (dean.earley@icode.co.uk)
i-Catcher Development Team

iCode Systems

expvb - 09 Sep 2008 14:48 GMT
> There is no .NET ng dealing with WinAPI; so I took this ng.
> I will rewrite my code-snip in VB6....hoping anybody will give a helpful
> reply then.

The only messages that copy string to another process is WM_GETTEXT,
WM_SETTEXT, and WM_COPYDATA. All other messages don't work as far as I know.
In some cases you get a pointer, but since each process has its own address
space, you won't see the data. If you use that pointer, you get garbage
data, sometimes 0 so you see an empty string, but sometimes points to an
invalid block in your process and you get a GPF. You have to use a function
like ReadProcessMemory(). Search for that function to see how it's used.
Markus Colorado - 09 Sep 2008 16:34 GMT
Hi,
that explains, why I can successfully read the number of items/columns, but don't get
any strings.
I'll try your suggestion and let y know.

Thanks so far.
Markus

>> There is no .NET ng dealing with WinAPI; so I took this ng.
>> I will rewrite my code-snip in VB6....hoping anybody will give a helpful reply
[quoted text clipped - 7 lines]
> a GPF. You have to use a function like ReadProcessMemory(). Search for that
> function to see how it's used.
Markus Colorado - 09 Sep 2008 20:16 GMT
Hi,

thanks to yr suggestion I'm able to read the ITEMS (rows) oa a foreign ListView, but
I still can't get the column-captions of my lv.
Why is it so hard to get the column-captions...?

Markus

>> There is no .NET ng dealing with WinAPI; so I took this ng.
>> I will rewrite my code-snip in VB6....hoping anybody will give a helpful reply
[quoted text clipped - 7 lines]
> a GPF. You have to use a function like ReadProcessMemory(). Search for that
> function to see how it's used.
Ken Halter - 09 Sep 2008 21:16 GMT
> Hi,
>
[quoted text clipped - 3 lines]
>
> Markus

If you're getting rows, it sounds like you're not using the correct window
handle.... the ListView hWnd and ColumnHeaders hWnd are different. The
listview is a container for the headers. Use the FindWindow functionality in
Spy++ to check it out....

btw, if this is "my listview" as in a listview running in your own app and
in the same process space as the code you're using, why not use the
listview's built in properties instead of mucking with API calls?

Signature

Ken Halter
Part time groupie

Markus Colorado - 09 Sep 2008 21:36 GMT
Hi Ken,

a) it's a listview of a foreign app.
b) I have solved to get the items of a foreign listview using SendMessge() with
LV_ITEMGETTEXT, allocating the memeory of the foreign app. But I'm not able to get
the 'pszText' from an ITEM (neither LV_ITEM or HD_ITEM).

Markus

>> Hi,
>>
[quoted text clipped - 12 lines]
> same process space as the code you're using, why not use the listview's built in
> properties instead of mucking with API calls?
Karl E. Peterson - 10 Sep 2008 00:15 GMT
> a) it's a listview of a foreign app.

Exactly.

> b) I have solved to get the items of a foreign listview using SendMessge() with
> LV_ITEMGETTEXT, allocating the memeory of the foreign app. But I'm not able to get
> the 'pszText' from an ITEM (neither LV_ITEM or HD_ITEM).

So which part of the explanation you got XX messages ago didn't you understand?  The
pszText is a *pointer* into the other process's address space.  WTF good does that
do *your* process?
Signature

.NET: It's About Trust!
http://vfred.mvps.org

Markus Colorado - 10 Sep 2008 12:42 GMT
Hi Karl,

>> So which part of the explanation you got XX messages ago didn't you understand?
>> The pszText is a *pointer* into the other process's address space.
>> WTF good does that do *your* process?
??? - sorry, I do not understand that statement.
WTF - "What the f..." ????

I've done a step forward. I'm able to get the items of the external ListView now via
LVM_GETITEM and read the item text, but I can't do that with the column captions of
the ListView heder (via HDM_GETITEM).

Below ist my code (VB6) for reading the items and the columns of an external
listview. As said, I can read the items (rows) without any problems, but I never get
any text (caption) for the column header; sometimes I run into a AccessViolation
inside the foreign process. - Does anybody see any failure in
ListViewColumnGetText()??

Thanks in advance,
Markus

---------- [code begin] ----------
'//
'// Utilities.DebugPrint() is a wrapped method for
'// OutputDebugString() in a module called Utilities.
'//

'// ListView item
Private Type LVITEM
  mask As Long
  iItem As Long
  iSubitem As Long
  state As Long
  stateMask As Long
  pszText As Long
  cchTextMax As Long
  iImage As Long
  lParam As Long
  iIndent As Long
End Type

'// ListView header item
Private Type HDITEM
  mask As Long
  cxy As Long
  pszText As String
  hbm As Long
  cchTextMax As Long
  fmt As Long
  lParam As Long
  iImage As Long
  iOrder As Long
End Type

Declare Function CloseHandle Lib "kernel32" ( _
                           ByVal hObject As Long) As Long

Declare Function GetWindowThreadProcessId Lib "user32" ( _
                           ByVal hWnd As Long, _
                           lpdwProcessId As Long) As Long

Declare Function OpenProcess Lib "kernel32" ( _
                           ByVal dwDesiredAccess As Long, _
                           ByVal bInheritHandle As Long, _
                           ByVal dwProcessId As Long) As Long

Declare Function ReadProcessMemory Lib "kernel32" ( _
                           ByVal hProcess As Long, _
                           lpBaseAddress As Any, _
                           lpBuffer As Any, _
                           ByVal nSize As Long, _
                           lpNumberOfBytesWritten As Long) As Long

Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
                           ByVal hWnd As Long, _
                           ByVal wMsg As Long, _
                           ByVal wParam As Long, _
                           lParam As Any) As Long

Declare Function VirtualAllocEx Lib "kernel32" ( _
                           ByVal hProcess As Long, _
                           ByVal lpAddress As Long, _
                           ByVal dwSize As Long, _
                           ByVal flAllocationType As Long, _
                           ByVal flProtect As Long) As Long

Declare Function VirtualFreeEx Lib "kernel32" ( _
                           ByVal hProcess As Long, _
                           lpAddress As Any, _
                           ByVal dwSize As Long, _
                           ByVal dwFreeType As Long) As Long

Declare Function WriteProcessMemory Lib "kernel32" ( _
                           ByVal hProcess As Long, _
                           lpBaseAddress As Any, _
                           lpBuffer As Any, _
                           ByVal nSize As Long, _
                           lpNumberOfBytesWritten As Long) As Long

Private Const HDM_FIRST = &H1200
Private Const HDM_GETITEMCOUNT = (HDM_FIRST + 0)
Private Const HDM_GETITEMA = (HDM_FIRST + 3)
Private Const HDM_GETITEM = HDM_GETITEMA

Private Const HDI_TEXT = &H2

Private Const LVIF_TEXT = &H1

Private Const LVM_FIRST As Long = &H1000
Private Const LVM_GETITEM As Long = (LVM_FIRST + 5)
Private Const LVM_GETITEMCOUNT = (LVM_FIRST + 4)
Private Const LVM_GETHEADER = (LVM_FIRST + 31)

Private Const PAGE_READWRITE = &H4&
Private Const MEM_RESERVE = &H2000
Private Const MEM_COMMIT = &H1000
Private Const MEM_RELEASE = &H8000
Private Const PROCESS_VM_OPERATION = &H8
Private Const PROCESS_VM_READ = &H10
Private Const PROCESS_VM_WRITE = &H20

Private Sub ListView_GetItems(ByVal hWnd As Long)

   '// get number of rows and columns
   '// hWnd = handle of ListView (SysListView32)

   Dim hWnd_hd As Long       ' handle of 'SysHeader32'
   Dim iCols As Integer      ' number of columns in ListView
   Dim iRows As Integer      ' number of rows in ListView
   Dim iColCurr As Integer   ' current column index
   Dim iRowCurr As Integer   ' current row index

   hWnd_hd = SendMessage(hWnd, LVM_GETHEADER, 0, 0)
   iCols = SendMessage(hWnd_hd, HDM_GETITEMCOUNT, 0, 0)
   iRows = SendMessage(hWnd, LVM_GETITEMCOUNT, 0, 0)

   Utilities.DebugPrint ("  >> hWnd_hd: " & hWnd_hd)
   Utilities.DebugPrint ("  >> iCols: " & iCols)
   Utilities.DebugPrint ("  >> iRows: " & iRows)

   For iRowCurr = 0 To iRows - 1
       For iColCurr = 0 To iCols - 1
           Utilities.DebugPrint ("[" & iRowCurr & "][" & iColCurr & "] " & _
                                 ListViewGetText(hWnd, iColCurr, iRowCurr))
       Next
       Utilities.DebugPrint ("------------------------------")
   Next

End Sub

Sub ListViewHeader_GetItems(ByVal hWnd As Long)

   '// get number of columns
   '// hWnd = handle of Header (SysHeader32)

   Dim iCols As Integer        ' number of columns in ListView
   Dim iColCurr As Integer     ' current column index

   iCols = SendMessage(hWnd, HDM_GETITEMCOUNT, 0, 0)
   Utilities.DebugPrint ("  >> iCols: " & iCols)

   For iColCurr = 0 To iCols - 1
       Utilities.DebugPrint ("[" & iColCurr & "] " & _
                                       ListViewColumnGetText(hWnd, iColCurr))
   Next

End Sub

Function ListViewGetText(ByVal hWnd As Long, _
                        ByVal iSubitem As Integer, _
                        ByVal iItem As Integer) As String

   Dim lngProcID As Long, lngProcHandle As Long
   Dim typLvItem As LVITEM
   Dim strLvItem As String
   Dim lngVarPtr1 As Long, lngVarPtr2 As Long
   Dim lngMemVar1 As Long, lngMemVar2 As Long
   Dim lngMemLen1 As Long, lngMemLen2 As Long

   Call GetWindowThreadProcessId(hWnd, lngProcID)

   If lngProcID <> 0 Then

       lngProcHandle = OpenProcess(PROCESS_VM_OPERATION Or _
                                           PROCESS_VM_READ Or _
                                           PROCESS_VM_WRITE, False, lngProcID)

       If lngProcHandle <> 0 Then

           strLvItem = String(255, vbNullChar)
           lngVarPtr1 = StrPtr(strLvItem)
           lngVarPtr2 = VarPtr(typLvItem)
           lngMemLen1 = LenB(strLvItem)
           lngMemLen2 = LenB(typLvItem)
           lngMemVar1 = VirtualAllocEx(lngProcHandle, 0, lngMemLen1, _
                  MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
           lngMemVar2 = VirtualAllocEx(lngProcHandle, 0, lngMemLen2, _
                  MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)

           With typLvItem
               .cchTextMax = 255
               .iItem = iItem
               .iSubitem = iSubitem
               .mask = LVIF_TEXT
               .pszText = lngMemVar1
           End With

           Call WriteProcessMemory(lngProcHandle, ByVal lngMemVar1, _
                            ByVal lngVarPtr1, lngMemLen1, 0)
           Call WriteProcessMemory(lngProcHandle, ByVal lngMemVar2, _
                            ByVal lngVarPtr2, lngMemLen2, 0)
           Call SendMessage(hWnd, LVM_GETITEM, ByVal 0, ByVal lngMemVar2)
           Call ReadProcessMemory(lngProcHandle, ByVal lngMemVar1, _
                            ByVal lngVarPtr1, lngMemLen1, 0)

           strLvItem = StrConv(strLvItem, vbUnicode)
           strLvItem = Left(strLvItem, InStr(1, strLvItem, vbNullChar) - 1)
           ListViewGetText = strLvItem

           Call VirtualFreeEx(lngProcHandle, ByVal lngMemVar1, _
                        lngMemLen1, MEM_RELEASE)
           Call VirtualFreeEx(lngProcHandle, ByVal lngMemVar2, _
                        lngMemLen2, MEM_RELEASE)

           Call CloseHandle(lngProcHandle)

       End If

   End If

End Function

Function ListViewColumnGetText(ByVal hWnd, iColumn As Integer) As String

   Dim lngProcID As Long, lngProcHandle As Long
   Dim typHdItem As HDITEM
   Dim strHdItem As String
   Dim lngVarPtr1 As Long, lngVarPtr2 As Long
   Dim lngMemVar1 As Long, lngMemVar2 As Long
   Dim lngMemLen1 As Long, lngMemLen2 As Long
   Dim iMaxLen As Integer

   iMaxLen = 64

   Call GetWindowThreadProcessId(hWnd, lngProcID)

   If lngProcID <> 0 Then

       lngProcHandle = OpenProcess(PROCESS_VM_OPERATION Or _
                  PROCESS_VM_READ Or PROCESS_VM_WRITE, _
                  False, lngProcID)

       If lngProcHandle <> 0 Then

           strHdItem = String(iMaxLen, vbNullChar)
           lngVarPtr1 = StrPtr(strHdItem)
           lngVarPtr2 = VarPtr(typHdItem)
           lngMemLen1 = LenB(strHdItem)
           lngMemLen2 = LenB(typHdItem)
           lngMemVar1 = VirtualAllocEx(lngProcHandle, 0, lngMemLen1, _
                     MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
           lngMemVar2 = VirtualAllocEx(lngProcHandle, 0, lngMemLen2, _
                     MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)

           With typHdItem
               .cchTextMax = iMaxLen
               .mask = HDI_TEXT
               .pszText = lngMemVar1
           End With

           Call WriteProcessMemory(lngProcHandle, ByVal lngMemVar1, _
                              ByVal lngVarPtr1, lngMemLen1, 0)
           Call WriteProcessMemory(lngProcHandle, ByVal lngMemVar2, _
                              ByVal lngVarPtr2, lngMemLen2, 0)
           Call SendMessage(hWnd, HDM_GETITEM, CLng(iColumn), _
                              ByVal lngMemVar2)
           Call ReadProcessMemory(lngProcHandle, ByVal lngMemVar1, _
                              ByVal lngVarPtr1, lngMemLen1, 0)

           strHdItem = StrConv(strHdItem, vbUnicode)
           strHdItem = Left(strHdItem, InStr(1, strHdItem, vbNullChar) - 1)
           ListViewColumnGetText = strHdItem

           Call VirtualFreeEx(lngProcHandle, ByVal lngMemVar1, _
                               lngMemLen1, MEM_RELEASE)
           Call VirtualFreeEx(lngProcHandle, ByVal lngMemVar2, _
                               lngMemLen2, MEM_RELEASE)

           Call CloseHandle(lngProcHandle)

       End If

   End If

End Function
---------- [code end] ----------

>> a) it's a listview of a foreign app.
>
[quoted text clipped - 7 lines]
> The pszText is a *pointer* into the other process's address space.  WTF good does
> that do *your* process?
Schmidt - 10 Sep 2008 21:00 GMT
> Below ist my code (VB6) for reading the items and
> the columns of an external listview. As said, I can read
> the items (rows) without any problems, but I never get
> any text (caption) for the column header;

> Private Type HDITEM
>    mask As Long
>    cxy As Long
>    pszText As String '<----- !!!

Change that to a Long and it will work.

Olaf
Markus Colorado - 10 Sep 2008 21:33 GMT
Hi Olaf, that's it!! - You are my hero ;-))

Thank you so much for that 'last missing link' and 'expvb' for guiding me to the
right direction concerning memory allocation.

Markus

>> Below ist my code (VB6) for reading the items and
>> the columns of an external listview. As said, I can read
[quoted text clipped - 9 lines]
>
> Olaf
Karl E. Peterson - 10 Sep 2008 21:31 GMT
> Hi Karl,
>
[quoted text clipped - 3 lines]
> ??? - sorry, I do not understand that statement.
> WTF - "What the f..." ????

I may have misunderestimated you.  If so, my apologies.
Signature

.NET: It's About Trust!
http://vfred.mvps.org

Henri - 09 Sep 2008 18:48 GMT
> There is no .NET ng dealing with WinAPI; so I took this ng.

see Adv. Win32 api ng
(news://194.177.96.26/comp.os.ms-windows.programmer.win32)
where this has been answered... hundreds of times...
Markus Colorado - 09 Sep 2008 20:12 GMT
Hi Henri,

excuse my ignorance, but in the given ng I could not find one single post/message
concerning my problem.
Once aganin: I'd like to get the caption of each column of an EXTERNAL (foreign)
application ui.

Markus

>> There is no .NET ng dealing with WinAPI; so I took this ng.
>
> see Adv. Win32 api ng (news://194.177.96.26/comp.os.ms-windows.programmer.win32)
> where this has been answered... hundreds of times...
Vinchenzo vinç - 09 Sep 2008 20:57 GMT
> Hi Henri,
>
> excuse my ignorance, but in the given ng I could not find one single
> post/message concerning my problem.
> Once aganin: I'd like to get the caption of each column of an EXTERNAL
> (foreign) application ui.

   Once again?, sorry, I think I missed something. Where did you said
*before* external, foreign, o an other aplicacion's ListView?

Signature

   Regards
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
( ! ) Preceding answers in Google:
   http://groups.google.com/group/microsoft.public.vb.winapi
( i ) Temperance in the forum:
   http://www.microsoft.com/communities/conduct/default.mspx
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Markus Colorado - 09 Sep 2008 21:05 GMT
>    Once again?, sorry, I think I missed something. Where did you said *before*
> external, foreign, o an other aplicacion's ListView?

Uuups, I'm sorry! - I really missed to write, that the ListView is in a foreign
application.
The only hint was the "processId"...

Markus
Vinchenzo vinç - 09 Sep 2008 21:23 GMT
Hi Markus,
   see if some of the following results, in the newsgroup already suggested
by Henri, helps you:

http://groups.google.com/group/comp.os.ms-windows.programmer.win32/search?group=
comp.os.ms-windows.programmer.win32&q=OpenProcess+PROCESS_VM_READ+ReadProcessMem
ory&qt_g=Buscar+en+este+grupo


Signature

   Regards
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
( ! ) Preceding answers in Google:
   http://groups.google.com/group/microsoft.public.vb.winapi
( i ) Temperance in the forum:
   http://www.microsoft.com/communities/conduct/default.mspx
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Markus Colorado - 09 Sep 2008 15:50 GMT
Hi MikeD,

I've rewritten the posted VB.NET code in VB6 (see below).
In VB6 it's exactly the same; I do net get the needed column captions of my ListView
header.
Any idea how to solve my problem??

regards
Markus

---------- [code begin] ----------
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 Const HDM_FIRST = &H1200
Private Const HDM_GETITEMCOUNT = (HDM_FIRST + 0)
Private Const HDM_GETITEMA = (HDM_FIRST + 3)
Private Const HDM_GETITEM = HDM_GETITEMA
Private Const HDM_SETITEM = (HDM_FIRST + 4)
Private Const HDM_SETIMAGELIST = (HDM_FIRST + 8)
Private Const HDM_GETIMAGELIST = (HDM_FIRST + 9)

Private Const HDI_WIDTH = &H1
Private Const HDI_HEIGHT = HDI_WIDTH
Private Const HDI_TEXT = &H2
Private Const HDI_FORMAT = &H4
Private Const HDI_LPARAM = &H8
Private Const HDI_BITMAP = &H10

Private Const HDF_LEFT = 0
Private Const HDF_RIGHT = 1
Private Const HDF_CENTER = 2
Private Const HDF_JUSTIFYMASK = &H3
Private Const HDF_RTLREADING = 4
Private Const HDF_BITMAP_ON_RIGHT = &H1000
Private Const HDF_IMAGE = &H800
Private Const HDF_OWNERDRAW = &H8000
Private Const HDF_STRING = &H4000
Private Const HDF_BITMAP = &H2000

Private Type HDITEM
  mask As Long
  cxy As Long
  pszText As String
  hbm As Long
  cchTextMax As Long
  fmt As Long
  lParam As Long
  iImage As Long
  iOrder As Long
End Type

Public Sub ListView_GetColumnNames(ByVal hWnd As Long)
  '// hWnd ist the handle of our 'SysHeader32'
  Dim iCols As Integer
  Dim i As Integer
  iCols = SendMessage(hWnd, HDM_GETITEMCOUNT, 0, 0)
  Utilities.DebugPrint ("  >> iCols: " & iCols)
  ' iterate through columns
  For i = 0 To iCols - 1
     Dim hditm As HDITEM
     Dim iRes As Integer
     Dim sText As String
     hditm.cchTextMax = 32
     hditm.pszText = String$(hditm.cchTextMax, Chr$(0))
     hditm.mask = HDI_FORMAT Or HDI_TEXT
     hditm.fmt = HDF_STRING
     If SendMessage(hWnd, HDM_GETITEM, i, hditm) = 1 Then
        sText = StripNulls(hditm.pszText) & " {" & Len(hditm.pszText) & "}"
        Utilities.DebugPrint ("[" & i & "]: iRes=1 | sText = " & sText)
     Else
        Utilities.DebugPrint ("[" & i & "]: iRes<>1 | sText = #####")
     End If
  Next
End Sub

Private Function StripNulls(OriginalStr As String) As String
  ' This removes the extra Nulls so String comparisons will work
  If (InStr(OriginalStr, Chr(0)) > 0) Then
     OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
  End If
  StripNulls = OriginalStr
End Function
---------- [code end] ----------

>> Hi,
>>
[quoted text clipped - 14 lines]
> If you want a VB.NET solution, you need to ask in a newsgroup with dotnet or vsnet
> in the name.
Vinchenzo vinç - 09 Sep 2008 18:03 GMT
> Hi MikeD,
>
> I've rewritten the posted VB.NET code in VB6 (see below).
> In VB6 it's exactly the same; I do net get the needed column captions of
> my ListView header.

   Hi Markus,
   your code works perfectly (the only required change to work in Visual
Basic is replace "Utilities.DebugPrint" with "Debug.Print"), and add the
declarations for 'GetWindow' and GW_CHILD to obtain the handle to the column
header window associated with the ListView.

> Any idea how to solve my problem??

   Of course:

<MODE MideD ON>
If you want a VB.NET solution, you need to ask in a newsgroup with dotnet or
vsnet in the name.
<MODE MideD OFF>

Signature

   Regards
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
( ! ) Preceding answers in Google:
   http://groups.google.com/group/microsoft.public.vb.winapi
( i ) Temperance in the forum:
   http://www.microsoft.com/communities/conduct/default.mspx
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

expvb - 09 Sep 2008 19:09 GMT
>> Hi MikeD,
>>
[quoted text clipped - 7 lines]
> declarations for 'GetWindow' and GW_CHILD to obtain the handle to the
> column header window associated with the ListView.

This works if the control belongs to your own process. If it's another
process, you get empty string, garbage string, or GPF, depending on what
happens to be in the same location in your process. You can use
IsBadStringPtr() or IsBadReadPtr() to avoid a GPF, but you still get
incorrect data.
Vinchenzo vinç - 09 Sep 2008 21:01 GMT
Yes, but althought I agree with you, please read again what Markus said:

> Hi MikeD,
> I've rewritten the posted VB.NET code in VB6 (see below).
> In VB6 it's exactly the same; I do net get the needed column captions
> ****of my ListView header****.

   And a later:

> I still can't get the column-captions **of my lv**.

   So, well, his VB6 code works very well...

Signature

   Regards
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
( ! ) Preceding answers in Google:
   http://groups.google.com/group/microsoft.public.vb.winapi
( i ) Temperance in the forum:
   http://www.microsoft.com/communities/conduct/default.mspx
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.