2013-07-14 1 views
4

나는 이것으로 나를 도울 수있는 함수를 찾을 수 없으며, 필요한 Column의 좌표를 찾기 위해 ListView 영역의 모든 픽셀을 HitTest하는 미친 함수를 작성하고 싶지 않습니다. HitTest). Yair Nevet 주석에어쨌든 ListView에서 열의 왼쪽 위 모퉁이의 좌표를 결정할 수 있습니까?

enter image description here

덕분에, 내가 필요 칼럼의 왼쪽 위치를 결정하기 위해 다음 기능을 썼다 : 당신은 그것을 달성하기 위해 PointToScreenPointToClient 클래스를 사용할 수 있습니다

private int GetLeftOfColumn(ColumnHeader column, ListView lv) 
{ 
    if (!lv.Columns.Contains(column)) 
     return -1; 

    int calculated_left = 0; 

    for (int i = 0; i < lv.Columns.Count; i++) 
     if (lv.Columns[i] == column) 
      return calculated_left; 
     else 
      calculated_left += lv.Columns[i].Width + 1; 

    return calculated_left; 
} 
+1

이 질문에 대답 보이지 않는다. SendMessage()를 pinvoking하여 얻을 수 있습니다. TVM_GETHEADER 및 HDM_GETITEMRECT가 필요합니다. –

+0

글쎄, 어떻게 해야할지에 대한 아이디어를 얻었고 Yair Nevet의 의견을 토대로 자신의 기능을 썼다. 귀하는 즉시 사용할 수있는 답변을 게시 할 수 있으며 승인 될 것입니다. – Kosmos

+0

@HansPassant 나는 당신의 해결책을보고 싶습니다. –

답변

1

, 나는 그것을 해결하기 위해 필요로 할 때 난 그냥이 건너 온, 여기에 메시징을 사용하여 작업 버전입니다 네이티브 코드.

여기에 개인 NativeMethods 클래스에 싸여 몇 가지 필수 항목입니다 :

private static class NativeMethods { 
    private const int LVM_FIRST = 0x1000; 
    private const int LVM_GETHEADER = LVM_FIRST + 31; 

    private const int HDM_FIRST = 0x1200; 
    private const int HDM_GETITEMRECT = HDM_FIRST + 7; 

    private const int SB_HORZ = 0; 
    private const int SB_VERT = 1; 

    private const int SIF_POS = 0x0004; 

    [StructLayout(LayoutKind.Sequential)] 
    public class SCROLLINFO { 
     public int cbSize = Marshal.SizeOf(typeof(NativeMethods.SCROLLINFO)); 
     public int fMask; 
     public int nMin; 
     public int nMax; 
     public int nPage; 
     public int nPos; 
     public int nTrackPos; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct RECT { 
     public int Left; 
     public int Top; 
     public int Right; 
     public int Bottom; 
    } 

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam); 

    [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)] 
    public static extern IntPtr SendMessageGETRECT(IntPtr hWnd, int Msg, int wParam, ref RECT lParam); 

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] 
    public static extern bool GetScrollInfo(IntPtr hWnd, int fnBar, SCROLLINFO scrollInfo); 

    /// <summary> 
    /// Return the handle to the header control on the given list 
    /// </summary> 
    /// <param name="list">The listview whose header control is to be returned</param> 
    /// <returns>The handle to the header control</returns> 
    public static IntPtr GetHeaderControl(ListView list) { 
     return SendMessage(list.Handle, LVM_GETHEADER, 0, 0); 
    } 

    /// <summary> 
    /// Get the scroll position of the given scroll bar 
    /// </summary> 
    /// <param name="lv"></param> 
    /// <param name="horizontalBar"></param> 
    /// <returns></returns> 
    public static int GetScrollPosition(ListView lv, bool horizontalBar) { 
     int fnBar = (horizontalBar ? SB_HORZ : SB_VERT); 

     SCROLLINFO scrollInfo = new SCROLLINFO(); 
     scrollInfo.fMask = SIF_POS; 
     if (GetScrollInfo(lv.Handle, fnBar, scrollInfo)) { 
      return scrollInfo.nPos; 
     } 
     else { 
      return -1; 
     } 
    } 

    /// <summary> 
    /// Return the screen rectangle of the column header item specified 
    /// </summary> 
    /// <param name="handle">Handle to the header control to check</param> 
    /// <param name="index">Index of the column to get</param> 
    /// <returns></returns> 
    public static Rectangle GetHeaderItemRect(IntPtr handle, int index) { 
     RECT rc = new RECT(); 
     IntPtr result = NativeMethods.SendMessageGETRECT(handle, HDM_GETITEMRECT, index, ref rc); 
     if (result != IntPtr.Zero) { 
      return new Rectangle(rc.Left, rc.Top, rc.Right - rc.Left, rc.Bottom - rc.Top); 
     } 
     return Rectangle.Empty; 
    } 
} 

여기에 사용자의 위치를 ​​얻는 코드입니다 :

/// <summary> 
/// Get's the location coordinate of the specified column header's top/left corner 
/// </summary> 
/// <param name="oListView">ListView control to get the column header location from</param> 
/// <param name="iColumn">Column to find the location for</param> 
/// <param name="bAsScreenCoordinate">Whether the location returned is for the screen or the local ListView control</param> 
/// <returns>Location of column header or <see cref="Point.Empty"/> if it could not be retrieved</returns> 
public static Point GetColumnHeaderTopLeft(this ListView oListView, int iColumn, bool bAsScreenCoordinate) { 
    if (oListView == null) { 
     throw new ArgumentNullException(); 
    } 
    if ((iColumn < 0) || (iColumn >= oListView.Columns.Count)) { 
     throw new ArgumentOutOfRangeException(); 
    } 

    // Get the header control's rectangle 
    IntPtr hndHeader = NativeMethods.GetHeaderControl(oListView); 
    Rectangle oHeaderRect = NativeMethods.GetHeaderItemRect(hndHeader, iColumn); 
    if (oHeaderRect.IsEmpty) { 
     return Point.Empty; 
    } 

    // Get the scroll bar position to adjust the left 
    int iScroll = NativeMethods.GetScrollPosition(oListView, true); 

    // Create the local coordinate 
    Point oLocation = new Point(oHeaderRect.Left - iScroll, oHeaderRect.Top); 

    // Return the local or screen coordinate 
    return bAsScreenCoordinate ? oListView.PointToScreen(oLocation) : oLocation; 
} 
1

을 보면 :

이제 수신 된 포인트의 X 및 Y 좌표와 열의 너비와 높이를 ord로 사용하십시오. 어 그것은 폼의 위치의 계산하려면 : USER32 메시지는 위에서 언급 되었으나 구현이 주어지지 않았기 때문에

private int GetLeftOfColumn(ColumnHeader column, ListView lv) 
{ 
    if (!lv.Columns.Contains(column)) 
     return -1; 

    int calculated_left = 0; 

    for (int i = 0; i < lv.Columns.Count; i++) 
     if (lv.Columns[i] == column) 
      return calculated_left; 
     else 
      calculated_left += lv.Columns[i].Width + 1; 

    return calculated_left; 
} 
+0

저를 끌어 올려주세요. 적어도 저 ColumnHeader의 좌표는 어디에서 얻었습니까? 그것은 통제가 아니며 위치 필드를 포함하지 않습니다. 상단 및 왼쪽과 동일합니다. – Kosmos

+1

목록보기 위치와 열 너비를 고려하여 계산할 수 있습니다. –

+0

감사합니다. 이것은 적어도 몇 가지 아이디어입니다. 국경 등으로 인해 100 % 정확도가 아니지만 여전히 사용할 수있는 것이 있습니다 ... – Kosmos

관련 문제