DataGridView가 마우스 휠을 사용하여 한 번에 한 항목씩 스크롤하도록 하려면 어떻게 해야 합니까?
-
02-07-2019 - |
문제
이 컨트롤과 함께 마우스 휠을 사용할 때 DataGridView의 기본 동작을 재정의하고 싶습니다.기본적으로 DataGridView는 SystemInformation.MouseWheelScrollLines 설정과 동일한 수의 행을 스크롤합니다.우리가 원하는 것은 한 번에 하나의 항목만 스크롤하는 것입니다.
(DataGridView에 이미지가 표시되는데 크기가 다소 큽니다.이로 인해 세 행(일반적인 시스템 설정)을 너무 많이 스크롤하여 사용자가 볼 수 없는 항목까지 스크롤하게 되는 경우가 많습니다.)
나는 이미 몇 가지를 시도했지만 지금까지 많은 성공을 거두지 못했습니다.내가 겪은 몇 가지 문제는 다음과 같습니다.
MouseWheel 이벤트를 구독할 수 있지만 해당 이벤트를 처리된 것으로 표시하고 내 작업을 수행할 수 있는 방법은 없습니다.
OnMouseWheel을 재정의할 수 있지만 이는 호출되지 않는 것 같습니다.
기본 스크롤 코드에서 이를 수정할 수 있지만 다른 유형의 스크롤(예:키보드를 사용하여) 동일한 파이프라인을 통과합니다.
누구든지 좋은 제안이 있나요?
주어진 훌륭한 답변을 사용한 최종 코드는 다음과 같습니다.
/// <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
그것을 캐스팅합니다 Handled
MouseEventArgs
.이는 다음을 처리할 때도 작동합니다. MouseWheel
이벤트. OnMouseWheel()
실제로 전화를 받았고, DataGridView
의 재정의가 사용됩니다. SystemInformation.MouseWheelScrollLines
.
그래서:
당신은 실제로 그 일을 처리할 수 있었습니다
MouseWheel
이벤트, 캐스팅MouseEventArgs
에게HandledMouseEventArgs
그리고 설정Handled = true
, 그럼 원하는 대로 하세요.아강
DataGridView
, 우세하다OnMouseWheel()
여기에서 읽은 모든 코드를 다시 만들어 보세요. 반사기 교체를 제외하고SystemInformation.MouseWheelScrollLines
~와 함께1
.
후자는 많은 개인 변수( ScrollBar
s) 일부를 자신의 것으로 바꾸고 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}");
}
}