Skip to content

[RESOLVED]Width of a ListView control

Viewing 15 posts - 1 through 15 (of 18 total)
  • Author
    Posts
  • #191423
    nooob
    Member

    hi all

    Using an ApiSpy, i am able to get the handle to a ListView control whose class name is SysListView32…now i want to get its width (the no of rows), i tried the following but it alwasy returns 0:

    [DllImport("user32.dll", EntryPoint = "SendMessage")]
    public static extern int SendMessageLong(IntPtr hWnd, uint Msg,
    int wParam, StringBuilder lParam);
    const int LVM_GETCOLUMNWIDTH = 0xF126;
    int count = SendMessageLong(hListView, LVM_GETCOLUMNWIDTH, 0, null);//returns 0

    i am not sure if LVM_GETCOLUMNWIDTH is declared correctly.
    any tips plz?
    nanomachine dude are u there! 😀

    nooob

    #191440

    hehehe I dont understand what you try to do, for what purpose you want to know width column of listview. btw I never try it, hope you can get help from other…

    #191439
    nooob
    Member

    lol…i am not sure if i were correct in saying the “width” of a column…but to be clear i meant to get the number of entries or rows in a column.

    dude…since i m trying to learn c# with a bit of api, i decided to write some simple pal programs 😀

    the listview that i am talking about is the name list of any pal room… 😛
    in fact…i would need e.g. to get a name from that list…etc. if you guys can tell me how to get e.g. the width of that list, i might be able to go further on myself

    nanomachine..in fact i came across one of ur posts…where u get a nick in pal room in Delphi 5…from the topic of ur post..it seems that i am looking for the same thing only in c#…but unfortunately its no longer there…the post is here:

    hoping for more tips 🙄

    nooob

    #191438

    ah you want to get the nick list right? that post was removed cuz nobody said thanks to me so I decided to removed it but there a some code in vb6 you can convert to c# cuz it’s the same, all u have to do is import api function

    like this c++ code count how many item in list view

    int count=(int)::SendMessage(listview, LVM_GETITEMCOUNT, 0, 0);

    try to convert this code from vbnet to c# is not diffecult, just the way define api a little bit different

    Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcId As Integer) As Integer
    Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Integer, ByVal lpAddress As Integer, ByVal dwSize As Integer, ByVal flAllocationType As Integer, ByVal flProtect As Integer) As Integer
    Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Integer, ByVal lpAddress As Integer, ByVal dwSize As Integer, ByVal dwFreeType As Integer) As Integer
    Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As LV_ITEMA, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
    Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As LV_ITEMA, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
    Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As Byte, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
    Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Integer, ByRef lpdwProcessId As Integer) As Integer
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer
    Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Short, ByVal lParam As Integer) As Integer
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
    Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Integer, ByVal hWnd2 As Integer, ByVal lpsz1 As String, ByVal lpsz2 As String) As Integer
    Private Const PROCESS_QUERY_INFORMATION As Short = 1024
    Private Const PROCESS_VM_OPERATION As Short = &H8S
    Private Const PROCESS_VM_READ As Short = &H10S
    Private Const PROCESS_VM_WRITE As Short = &H20S
    Private Const STANDARD_RIGHTS_REQUIRED As Integer = &HF0000
    Private Const MAX_LVMSTRING As Integer = 255
    Private Const MEM_COMMIT As Short = &H1000S
    Private Const PAGE_READWRITE As Short = &H4S
    Private Const LVIF_TEXT As Integer = &H1S
    Private Const MEM_RELEASE As Short = &H8000S
    Public Const LVM_GETITEMCOUNT = LVM_FIRST + 4
    Public Const LVM_FIRST = &H1000
    Private Const LVM_GETITEMTEXT As Integer = (LVM_FIRST + 45)
    Public Const WM_USER As Int32 = &H400
    
    Private Structure LV_ITEMA
    Dim mask As Integer
    Dim iItem As Integer
    Dim iSubItem As Integer
    Dim state As Integer
    Dim stateMask As Integer
    Dim pszText As Integer
    Dim cchTextMax As Integer
    Dim iImage As Integer
    Dim lParam As Integer
    Dim iIndent As Integer
    End Structure
    Public Function GetListviewItem(ByVal lstviewhwnd As Integer) As String
    Dim result As Integer
    Dim myItem As LV_ITEMA
    Dim pHandle As Integer
    Dim pStrBufferMemory As Integer
    Dim pMyItemMemory As Integer
    Dim strBuffer() As Byte
    Dim index As Integer
    Dim tmpString As String
    Dim strLength As Integer
    Dim ProcessID As Integer
    Dim usernum As Integer
    Dim i As Short
    usernum = SendMessage(lstviewhwnd, LVM_GETITEMCOUNT, 0, 0)
    '**********************
    'init the string buffer
    '**********************
    ReDim strBuffer(MAX_LVMSTRING)
    '***********************************************************
    'open a handle to the process and allocate the string buffer
    '***********************************************************
    Call GetWindowThreadProcessId(lstviewhwnd, ProcessID)
    pHandle = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, ProcessID)
    pStrBufferMemory = VirtualAllocEx(pHandle, 0, MAX_LVMSTRING, MEM_COMMIT, PAGE_READWRITE)
    '************************************************************************************
    'initialize the local LV_ITEM structure
    'The myItem.iSubItem member is set to the index of the column that is being retrieved
    '************************************************************************************
    myItem.mask = LVIF_TEXT
    myItem.iSubItem = 2
    myItem.pszText = pStrBufferMemory
    myItem.cchTextMax = MAX_LVMSTRING
    '**********************************************************
    'write the structure into the remote process's memory space
    '**********************************************************
    pMyItemMemory = VirtualAllocEx(pHandle, 0, Len(myItem), MEM_COMMIT, PAGE_READWRITE)
    result = WriteProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), 0)
    For i = 0 To usernum - 1
    '*************************************************************
    'send the get the item message and write back the memory space
    '*************************************************************
    result = SendMessage(lstviewhwnd, LVM_GETITEMTEXT, i, pMyItemMemory)
    result = ReadProcessMemory(pHandle, pStrBufferMemory, strBuffer(0), MAX_LVMSTRING, 0)
    result = ReadProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), 0)
    '**************************************************
    'turn the byte array into a string and send it back
    '**************************************************
    For index = LBound(strBuffer) To UBound(strBuffer)
    If Chr(strBuffer(index)) = vbNullChar Then Exit For
    tmpString = tmpString & Chr(strBuffer(index))
    Next index
    tmpString = Trim(tmpString) & ";"
    MessageBox.Show(tmpString)
    Next
    '**************************************************
    'deallocate the memory and close the process handle
    '**************************************************
    result = VirtualFreeEx(pHandle, pStrBufferMemory, 0, MEM_RELEASE)
    result = VirtualFreeEx(pHandle, pMyItemMemory, 0, MEM_RELEASE)
    result = CloseHandle(pHandle)
    If Len(tmpString) > 0 Then GetListviewItem = tmpString
    End Function
    #191437

    or c++ code

    int count=(int)::SendMessage(listview, LVM_GETITEMCOUNT, 0, 0);
    int i;
    
    LVITEM lvi, *_lvi;
    char item[512], subitem[512];
    char *_item, *_subitem;
    unsigned long pid;
    HANDLE process;
    
    GetWindowThreadProcessId(listview, &pid);
    process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);
    
    _lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
    
    _item=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT, PAGE_READWRITE);
    
    lvi.cchTextMax=512;
    
    
    for(i=0; i
    

    all these codes work correctly, cuz I do copy and past my old project
    listview is handle of listview

    have fun, I think you are busy for a couple of hour 😉

    #191436
    nooob
    Member

    nice..buddy…THANX ALOT nanomachine
    i am going to study ur code

    lol..i am gonna be busy for quite some time to come… 8)

    noob

    #191435
    nooob
    Member

    ok i made some progress but had a problem in getting a nick from room listview.

    //constants
    const int LVM_FIRST = 0x1000;
    const int LVM_GETITEMCOUNT = LVM_FIRST + 4;
    const int LVM_GETITEMTEXT = (LVM_FIRST + 45);
    
    private void button1_Click(object sender, EventArgs e)
    {
    IntPtr hRoom = FindWindow("My Window Class", null);
    IntPtr hSplitter = FindWindowEx(hRoom, IntPtr.Zero, "WTL_SplitterWindow", null);
    IntPtr hSplitter1 = FindWindowEx(hSplitter, IntPtr.Zero, "WTL_SplitterWindow", null);
    IntPtr hSplitter2 = FindWindowEx(hSplitter1, IntPtr.Zero, "WTL_SplitterWindow", null);
    IntPtr hSysList = FindWindowEx(hSplitter2, IntPtr.Zero, "ATL:0053C8D0", null);
    IntPtr hList = FindWindowEx(hSysList, IntPtr.Zero, "SysListView32", null);
    int count = SendMessageLong(hList, LVM_GETITEMCOUNT , 0, null);
    StringBuilder selectedNick = new StringBuilder(256);
    MessageBox.Show(count.ToString());
    SendMessageLong(hList, LVM_GETITEMTEXT, 0, selectedNick);
    MessageBox.Show(selectedNick.ToString());
    }

    i was able to get the no of entries in the listview using this:

    int count = SendMessageLong(hList, LVM_GETITEMCOUNT , 0, null);

    the following line should get the first nick from the listview…but it does not:

    SendMessageLong(hList, LVM_GETITEMTEXT, 0, selectedNick);

    can see whats wrong??

    ty nanomachine

    nooob

    #191434

    dealing with external listview to get item or select an item, you have to allocate virtual memory and not sendmessage direct like that. check the vbnet code. for counting item yes you can sendmessage normally like that but not get item or select an item with position.

    #191433

    c++ code is more clair cuz you dont have to declare api constants or import api functions but the way to allocate virtual is like c++. vbnet code look like forest…

    open process
    allocate memory
    write process memory
    read process memory
    deallocate memory before exit function
    close process

    you have to follow those steps to get listview item

    #191432
    nooob
    Member

    nanomachine…any sites about this process in vc#?
    or if u can elaborate on it….plz
    coz…i could compile only half way…not sure if it work

    nooob

    #191431

    nope I can’t cuz i’m busy with my project live cam streamming with c++. look around google or go to microsoft codezone, there are many forums for c#.net

    #191430
    nooob
    Member

    hi nanomachine
    i know you are busy…but if you sometime get a bit free plz have a look at the following code and lets hope that you find out the problem:

    Note: I have found this code at a site

    [StructLayout(LayoutKind.Sequential)]
    public struct LV_ITEM
    {
    public uint   mask;
    public int    iItem;
    public int    iSubItem;
    public uint   state;
    public uint   stateMask;
    public IntPtr pszText;
    public int    cchTextMax;
    public int    iImage;
    }
    
    
    public static string ReadListViewItem( IntPtr hWnd, int item )
    {
    const int dwBufferSize = 1024;
    
    int         dwProcessID;
    LV_ITEM     lvItem;
    string      retval;
    bool        bSuccess;
    IntPtr      hProcess        = IntPtr.Zero;
    IntPtr      lpRemoteBuffer  = IntPtr.Zero;
    IntPtr      lpLocalBuffer   = IntPtr.Zero;
    IntPtr      threadId        = IntPtr.Zero;
    
    try
    {
    lvItem = new LV_ITEM();
    lpLocalBuffer = Marshal.AllocHGlobal(dwBufferSize);
    // Get the process id owning the window
    threadId = GetWindowThreadProcessId( hWnd, out dwProcessID );
    if ( (threadId == IntPtr.Zero) || (dwProcessID == 0) )
    throw new ArgumentException( "hWnd" );
    
    // Open the process with all access
    hProcess = OpenProcess( PROCESS_ALL_ACCESS, false, dwProcessID );
    if ( hProcess == IntPtr.Zero )
    throw new ApplicationException( "Failed to access process" );
    
    // Allocate a buffer in the remote process
    lpRemoteBuffer = VirtualAllocEx( hProcess, IntPtr.Zero, dwBufferSize, MEM_COMMIT,
    PAGE_READWRITE );
    if ( lpRemoteBuffer == IntPtr.Zero )
    throw new SystemException( "Failed to allocate memory in remote process" );
    
    // Fill in the LVITEM struct, this is in your own process
    // Set the pszText member to somewhere in the remote buffer,
    // For the example I used the address imediately following the LVITEM stuct
    lvItem.mask = LVIF_TEXT;
    lvItem.iItem = item;
    lvItem.pszText = (IntPtr)(lpRemoteBuffer.ToInt32() + Marshal.SizeOf(typeof(LV_ITEM)));
    lvItem.cchTextMax = 50;
    
    // Copy the local LVITEM to the remote buffer
    bSuccess = WriteProcessMemory( hProcess, lpRemoteBuffer, ref lvItem,
    Marshal.SizeOf(typeof(LV_ITEM)), IntPtr.Zero );
    if ( !bSuccess )
    throw new SystemException( "Failed to write to process memory" );
    
    // Send the message to the remote window with the address of the remote buffer
    SendMessage( hWnd, LVM_GETITEM, 0, lpRemoteBuffer);
    
    // Read the struct back from the remote process into local buffer
    bSuccess = ReadProcessMemory( hProcess, lpRemoteBuffer, lpLocalBuffer, dwBufferSize,
    IntPtr.Zero );
    if ( !bSuccess )
    throw new SystemException( "Failed to read from process memory" );
    
    // At this point the lpLocalBuffer contains the returned LV_ITEM structure
    // the next line extracts the text from the buffer into a managed string
    
    retval = Marshal.PtrToStringAnsi((IntPtr)(lpLocalBuffer.ToInt32() +
    Marshal.SizeOf(typeof(LV_ITEM))));
    
    
    }
    finally
    {
    if ( lpLocalBuffer != IntPtr.Zero )
    Marshal.FreeHGlobal( lpLocalBuffer );
    if ( lpRemoteBuffer != IntPtr.Zero )
    VirtualFreeEx( hProcess, lpRemoteBuffer, 0, MEM_RELEASE );
    if ( hProcess != IntPtr.Zero )
    CloseHandle( hProcess );
    }
    return retval;
    }

    the problem is that it returns null?!

    the author has used LVM_GETITEM…i also tried with LVM_GETITEMTEXT….but no luck

    thnx for your time

    nooob

    #191429

    if you dont change anything it should work by adding this line after the line

    lvItem.iItem = item;
    add this line
    lvItem.iSubItem=2;

    that code is really nice 😆

    call that function by passing listview handle and the position of item you want to get like 0 is the first nick in paltalk room, 1 is second nick, 2 is third ect…

    I copy that code to the project for testing and it works correctly with sending message LVM_GETITEM, author of that code get item by position and not all the item in listview

    if you want get all item using that code
    do like this
    for int pos; pos<icount;pos++
    {
    nick=hisfunction (listviewhandle,pos);

    }

    or just change his code but the performance is after you undertand the code 8)

    btw the iSubItem =2 is just for paltalk, item is the row of listview, iSubItem is like column.

    #191428
    nooob
    Member

    yesssssssssss….got it…. 😀

    thanx alot….for your time and effort nanomachine 😛

    i would not have made it without your quick replies…ty

    i get most of the code..that i had pasted (from the site)…but still have problems with LV_ITEM struc….as how it works…

    can you elaborate a little more on your this line:

    btw the iSubItem =2 is just for paltalk, item is the row of listview, iSubItem is like column.

    i tried iSubItem = 1…but it didn work…why is that?

    thanx once again…nanomachine

    nooob

    #191427

    iSubItem is the column of your listview. you can create a app that has a listview with some rows and some columns and try to get the item and subitem. dont do the test with pt listview, create your own listview and try change value of iItem and iSubItem, you will understand better what it is.

    item1|subitem1|subitem2|subitem3
    item2|subitem1|subitem2|subitem3
    item3|subitem1|subitem2|subitem3

    create a listview like that and do the test. dont try with pt listview 🙄

Viewing 15 posts - 1 through 15 (of 18 total)
  • You must be logged in to reply to this topic.