>
며칠 전에 나는 syslistview32 에서 열의 텍스트를 얻기 위해 "LVM_GETCOLUMN"함수에 대한 질문을 받았습니다.   LVM_GETCOLUMN은 결과를 반환하지 않습니다 .

여기서 사용자에게 감사합니다. 나중에이 기능은 첫 번째 열의 텍스트 만 제공한다는 것을 알고 있습니다.

아무도, LV_COLUMN 구조체의 어떤 매개 변수가 대상 열을 정의해야하는지 알고 있습니까? 나는 iOrder 를 시도  그리고 iSubItem  그러나 어떤 매개 변수를 변경하거나 두 매개 변수를 모두 변경하더라도 항상 첫 번째 열 헤더의 텍스트를 얻습니다. 사용중인 코드는 다음과 같습니다.

[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
struct LV_COLUMN
{
    public System.Int32 mask;
    public System.Int32 fmt;
    public System.Int32 cx;
    public System.IntPtr pszText;
    public System.Int32 cchTextMax;
    public System.Int32 iSubItem;
    public System.Int32 iImage;
    public System.Int32 iOrder;
}
    public static string GetListViewColumn(System.IntPtr hwnd, uint processId, int Column)
    {
        const int dwBufferSize = 2048;
        const int LVM_FIRST = 0x1000;
        const int LVM_GETCOLUMNA = LVM_FIRST + 25;
        const int LVM_GETCOLUMNW = LVM_FIRST + 95;
        const int LVCF_FMT = 0x00000001;
        const int LVCF_TEXT = 0x00000004;
        int bytesWrittenOrRead = 0;
        LV_COLUMN lvCol;
        string retval;
        bool bSuccess;
        System.IntPtr hProcess = System.IntPtr.Zero;
        System.IntPtr lpRemoteBuffer = System.IntPtr.Zero;
        System.IntPtr lpLocalBuffer = System.IntPtr.Zero;
        try
        {
            lvCol = new LV_COLUMN();
            lpLocalBuffer = System.Runtime.InteropServices.Marshal.AllocHGlobal(dwBufferSize);
            hProcess = OpenProcess(Win32ProcessAccessType.AllAccess, false, processId);
            if (hProcess == System.IntPtr.Zero)
                throw new System.ApplicationException("Failed to access process!");
            lpRemoteBuffer = VirtualAllocEx(hProcess, System.IntPtr.Zero, dwBufferSize, Win32AllocationTypes.MEM_COMMIT, Win32MemoryProtection.PAGE_READWRITE);
            if (lpRemoteBuffer == System.IntPtr.Zero)
                throw new System.SystemException("Failed to allocate memory in remote process");
            lvCol.mask = LVCF_TEXT;
            lvCol.pszText = (System.IntPtr)(lpRemoteBuffer.ToInt32() + System.Runtime.InteropServices.Marshal.SizeOf(typeof(LV_COLUMN)));
            lvCol.cchTextMax = 500;
            lvCol.iOrder = Column;
            lvCol.iSubItem = Column;
            bSuccess = WriteProcessMemoryGETCOLUMN(hProcess, lpRemoteBuffer, ref lvCol, (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(LV_COLUMN)), out bytesWrittenOrRead);
            if (!bSuccess)
                throw new System.SystemException("Failed to write to process memory");

            SendMessage(hwnd, LVM_GETCOLUMNW, System.IntPtr.Zero, lpRemoteBuffer);
            bSuccess = ReadProcessMemory(hProcess, lpRemoteBuffer, lpLocalBuffer, dwBufferSize, out bytesWrittenOrRead);
            if (!bSuccess)
                throw new System.SystemException("Failed to read from process memory");
            retval = System.Runtime.InteropServices.Marshal.PtrToStringUni((System.IntPtr)(lpLocalBuffer.ToInt32() + System.Runtime.InteropServices.Marshal.SizeOf(typeof(LV_COLUMN))));
        }
        finally
        {
            if (lpLocalBuffer != System.IntPtr.Zero)
                System.Runtime.InteropServices.Marshal.FreeHGlobal(lpLocalBuffer);
            if (lpRemoteBuffer != System.IntPtr.Zero)
                VirtualFreeEx(hProcess, lpRemoteBuffer, 0, Win32AllocationTypes.MEM_RELEASE);
            if (hProcess != System.IntPtr.Zero)
                CloseHandle(hProcess);
        }
        return retval; /*Always returns the name of the first column*/
    }

  • 답변 # 1

    문제는 SendMessage 기능에 있습니다.

    "wparam"인수는 검색하고자하는 열의 인덱스입니다

    int index = 2;
    SendMessage(hwnd, LVM_GETCOLUMNW, index, lpRemoteBuffer);
    
    

  • 답변 # 2

    Laurijssen에게 감사합니다. 다음은 작동 코드입니다.

    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    struct LV_COLUMN
    {
        public System.Int32 mask;
        public System.Int32 fmt;
        public System.Int32 cx;
        public System.IntPtr pszText;
        public System.Int32 cchTextMax;
        public System.Int32 iSubItem;
        public System.Int32 iImage;
        public System.Int32 iOrder;
    }
    
        public static string GetListViewColumn(System.IntPtr hwnd, uint processId, int Column)
        {
            const int dwBufferSize = 2048;
            const int LVM_FIRST = 0x1000;
            const int LVM_GETCOLUMNA = LVM_FIRST + 25;
            const int LVM_GETCOLUMNW = LVM_FIRST + 95;
            const int LVCF_FMT = 0x00000001;
            const int LVCF_TEXT = 0x00000004;
            int bytesWrittenOrRead = 0;
            LV_COLUMN lvCol;
            string retval;
            bool bSuccess;
            System.IntPtr hProcess = System.IntPtr.Zero;
            System.IntPtr lpRemoteBuffer = System.IntPtr.Zero;
            System.IntPtr lpLocalBuffer = System.IntPtr.Zero;
            try
            {
                lvCol = new LV_COLUMN();
                lpLocalBuffer = System.Runtime.InteropServices.Marshal.AllocHGlobal(dwBufferSize);
                hProcess = OpenProcess(Win32ProcessAccessType.AllAccess, false, processId);
                if (hProcess == System.IntPtr.Zero)
                    throw new System.ApplicationException("Failed to access process!");
                lpRemoteBuffer = VirtualAllocEx(hProcess, System.IntPtr.Zero, dwBufferSize, Win32AllocationTypes.MEM_COMMIT, Win32MemoryProtection.PAGE_READWRITE);
                if (lpRemoteBuffer == System.IntPtr.Zero)
                    throw new System.SystemException("Failed to allocate memory in remote process");
                lvCol.mask = LVCF_TEXT;
                lvCol.pszText = (System.IntPtr)(lpRemoteBuffer.ToInt32() + System.Runtime.InteropServices.Marshal.SizeOf(typeof(LV_COLUMN)));
                lvCol.cchTextMax = 500;
                lvCol.iOrder = Column;
                lvCol.iSubItem = Column;
                bSuccess = WriteProcessMemoryGETCOLUMN(hProcess, lpRemoteBuffer, ref lvCol, (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(LV_COLUMN)), out bytesWrittenOrRead);
                if (!bSuccess)
                    throw new System.SystemException("Failed to write to process memory");
    
                SendMessage(hwnd, LVM_GETCOLUMNW, (System.IntPtr)Column, lpRemoteBuffer);
                bSuccess = ReadProcessMemory(hProcess, lpRemoteBuffer, lpLocalBuffer, dwBufferSize, out bytesWrittenOrRead);
                if (!bSuccess)
                    throw new System.SystemException("Failed to read from process memory");
                retval = System.Runtime.InteropServices.Marshal.PtrToStringUni((System.IntPtr)(lpLocalBuffer.ToInt32() + System.Runtime.InteropServices.Marshal.SizeOf(typeof(LV_COLUMN))));
            }
            finally
            {
                if (lpLocalBuffer != System.IntPtr.Zero)
                    System.Runtime.InteropServices.Marshal.FreeHGlobal(lpLocalBuffer);
                if (lpRemoteBuffer != System.IntPtr.Zero)
                    VirtualFreeEx(hProcess, lpRemoteBuffer, 0, Win32AllocationTypes.MEM_RELEASE);
                if (hProcess != System.IntPtr.Zero)
                    CloseHandle(hProcess);
            }
            return retval;
        }
    
    

관련 자료

  • 이전 php - 라 라벨 - 마이그레이션 오류, nullable 기본값?
  • 다음 machine learning - 파이썬에서 공분산이 고정 된 가우시안 혼합