DataGridView가 마우스 휠을 사용하여 한 번에 한 항목씩 스크롤하도록 하려면 어떻게 해야 합니까?

StackOverflow https://stackoverflow.com/questions/135105

  •  02-07-2019
  •  | 
  •  

문제

이 컨트롤과 함께 마우스 휠을 사용할 때 DataGridView의 기본 동작을 재정의하고 싶습니다.기본적으로 DataGridView는 SystemInformation.MouseWheelScrollLines 설정과 동일한 수의 행을 스크롤합니다.우리가 원하는 것은 한 번에 하나의 항목만 스크롤하는 것입니다.

(DataGridView에 이미지가 표시되는데 크기가 다소 큽니다.이로 인해 세 행(일반적인 시스템 설정)을 너무 많이 스크롤하여 사용자가 볼 수 없는 항목까지 스크롤하게 되는 경우가 많습니다.)

나는 이미 몇 가지를 시도했지만 지금까지 많은 성공을 거두지 못했습니다.내가 겪은 몇 가지 문제는 다음과 같습니다.

  1. MouseWheel 이벤트를 구독할 수 있지만 해당 이벤트를 처리된 것으로 표시하고 내 작업을 수행할 수 있는 방법은 없습니다.

  2. OnMouseWheel을 재정의할 수 있지만 이는 호출되지 않는 것 같습니다.

  3. 기본 스크롤 코드에서 이를 수정할 수 있지만 다른 유형의 스크롤(예:키보드를 사용하여) 동일한 파이프라인을 통과합니다.

누구든지 좋은 제안이 있나요?

주어진 훌륭한 답변을 사용한 최종 코드는 다음과 같습니다.

    /// <summary>
    /// Handle the mouse wheel manually due to the fact that we display
    /// images, which don't work well when you scroll by more than one
    /// item at a time.
    /// </summary>
    /// 
    /// <param name="sender">
    /// sender
    /// </param>
    /// <param name="e">
    /// the mouse event
    /// </param>
    private void mImageDataGrid_MouseWheel(object sender, MouseEventArgs e)
    {
        // Hack alert!  Through reflection, we know that the passed
        // in event argument is actually a handled mouse event argument,
        // allowing us to handle this event ourselves.
        // See http://tinyurl.com/54o7lc for more info.
        HandledMouseEventArgs handledE = (HandledMouseEventArgs) e;
        handledE.Handled = true;

        // Do the scrolling manually.  Move just one row at a time.
        int rowIndex = mImageDataGrid.FirstDisplayedScrollingRowIndex;
        mImageDataGrid.FirstDisplayedScrollingRowIndex =
            e.Delta < 0 ?
                Math.Min(rowIndex + 1, mImageDataGrid.RowCount - 1):
                Math.Max(rowIndex - 1, 0);
    }
도움이 되었습니까?

해결책

방금 제가 직접 약간의 검색과 테스트를 수행했습니다.나는 사용했다 반사기 몇 가지를 조사하고 발견했습니다.그만큼 MouseWheel 이벤트는 MouseEventArgs 매개변수이지만 OnMouseWheel() 재정의 DataGridView 그것을 캐스팅합니다 HandledMouseEventArgs.이는 다음을 처리할 때도 작동합니다. MouseWheel 이벤트. OnMouseWheel() 실제로 전화를 받았고, DataGridView의 재정의가 사용됩니다. SystemInformation.MouseWheelScrollLines.

그래서:

  1. 당신은 실제로 그 일을 처리할 수 있었습니다 MouseWheel 이벤트, 캐스팅 MouseEventArgs 에게 HandledMouseEventArgs 그리고 설정 Handled = true, 그럼 원하는 대로 하세요.

  2. 아강 DataGridView, 우세하다 OnMouseWheel() 여기에서 읽은 모든 코드를 다시 만들어 보세요. 반사기 교체를 제외하고 SystemInformation.MouseWheelScrollLines ~와 함께 1.

후자는 많은 개인 변수( ScrollBars) 일부를 자신의 것으로 바꾸고 Reflection을 사용하여 다른 것을 가져오거나 설정했을 것입니다.

다른 팁

DataGridView를 내 자신의 사용자 정의 컨트롤로 하위 클래스합니다 (새로운 Windows 양식을 추가하고 사용자 정의 제어 파일을 추가하고 기본 클래스를 Control에서 DatagridView로 변경합니다).

public partial class MyDataGridView : DataGridView

그런 다음 wndproc 메소드를 무시하고와 같은 것을 대체하십시오.

protected override void WndProc(ref Message m)
{
    if (m.Msg == 0x20a)
    {
        int wheelDelta = ((int)m.WParam) >> 16;

        // 120 = UP 1 tick
        // -120 = DOWN 1 tick

        this.FirstDisplayedScrollingRowIndex -= (wheelDelta / 120);
    }
    else
    {
        base.WndProc(ref m);
    }
}

물론, 당신은 당신이 그리드 등의 범위를 벗어난 숫자로 FirstDisplayedScrollingRowIndex를 설정하지 않는지 확인할 수 있습니다. 그러나 이것은 매우 잘 작동합니다!

리차드

onMousewHeel을 우선하고 Base를 호출하지 않습니다. 일부 휠 마우스에는 제대로 작동하도록 설정해야 할 특별한 설정이 있습니다. 이 게시물을 참조하십시오 http://forums.microsoft.com/msdn/showpost.aspx?postid=126295&siteid=1

업데이트: 내가 지금 그것을 배웠기 때문에 DataGridView a MouseWheel 이벤트, 두 번째, 더 간단한 재정의를 추가했습니다.

이것을 달성하는 한 가지 방법은 서브 클래스입니다 DataGridView 그리고 WndProc 특수 처리를 추가하려면 WM_MOUSEWHEEL 메시지.

이 예제는 마우스 휠 움직임을 포착하고 호출로 대체합니다. SendKeys.Send.

(이것은 단지 스크롤링과 약간 다릅니다. 또한 다음/이전 행을 선택하므로 DataGridView. 그러나 그것은 작동합니다.)

public class MyDataGridView : DataGridView
{
    private const uint WM_MOUSEWHEEL = 0x20a;

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_MOUSEWHEEL)
        {
            var wheelDelta = ((int)m.WParam) >> 16;

            if (wheelDelta < 0)
            {
                SendKeys.Send("{DOWN}");
            }

            if (wheelDelta > 0)
            {
                SendKeys.Send("{UP}");
            }

            return;
        }

        base.WndProc(ref m);
    }
}

두 번째 테이크 (위에서 언급 한 것과 동일한 경고와 함께) :

public class MyDataGridView : DataGridView
{
    protected override void OnMouseWheel(MouseEventArgs e)
    {
        if (e.Delta < 0)
            SendKeys.Send("{DOWN}");
        else
            SendKeys.Send("{UP}");
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top