DataGridViewはマウスホイールの水平スクロールのメッセージ (WM_MOUSEHWHEEL) に応答しないため、それでスクロールさせるにはDataGridViewを拡張する必要があります。
protected override void WndProc(ref Message m) { const int WM_MOUSEHWHEEL = 0x020E; if (m.Msg == WM_MOUSEHWHEEL) { int n = (int)(long)m.WParam; // int delta = (int)(short)((n >> 16) & 0xFFFF); int delta = n >> 16; int offset = HorizontalScrollingOffset + delta; if (offset < 0) offset = 0; HorizontalScrollingOffset = offset; m.Result = IntPtr.Zero; } base.WndProc(ref m); }
この方法ではWM_MOUSEHWHEELメッセージを処理しているため、このメッセージを送信するデバイスならば、タッチパッドのスクロールのジェスチャにも対応できます。
マウスポインタの移動でスクロールするようにするには、Reader modeを用います。
[DllImport("comctl32.dll", EntryPoint = "#383")] // 383は、DoReaderMode()の序数 public static extern void DoReaderMode(ref READERMODEINFO prmi); public delegate bool ReaderScroll(ref READERMODEINFO prmi, int dx, int dy); public delegate bool TranslateDispatch(ref MSG lpmsg); [StructLayout(LayoutKind.Sequential)] public struct READERMODEINFO { public uint cbSize; public IntPtr hwnd; public UInt32 fFlags; public IntPtr prc; public ReaderScroll pfnScroll; public TranslateDispatch pfnTranslate; public IntPtr lParam; } [StructLayout(LayoutKind.Sequential)] public struct MSG { public IntPtr hwnd; public uint message; public IntPtr wParam; public IntPtr lParam; public UInt32 time; public POINT pt; public UInt32 lPrivate; } [StructLayout(LayoutKind.Sequential)] public struct POINT { public Int32 x; public Int32 y; } [StructLayout(LayoutKind.Sequential)] public struct RECT { public Int32 left; public Int32 top; public Int32 right; public Int32 bottom; } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (e.Button == MouseButtons.Middle) { // マウスの中ボタンの押下で、Reader modeに入る EnterReaderMode(e.Location); } } private void EnterReaderMode(Point point) { // カーソルのサイズを基準に、スクロール領域を算出 Size size = Cursor.Current.Size; int width = size.Width / 2; int height = size.Height / 2; RECT scrollingArea = new RECT { left = point.X - width, right = point.X + width, top = point.Y - height, bottom = point.Y + height, }; IntPtr pScrollingArea = Marshal.AllocHGlobal(Marshal.SizeOf<RECT>()); Marshal.StructureToPtr(scrollingArea, pScrollingArea, false); const uint RMF_ZEROCURSOR = 0x01; READERMODEINFO readerInfo = new READERMODEINFO { cbSize = (uint)Marshal.SizeOf<READERMODEINFO>(), hwnd = Handle, fFlags = RMF_ZEROCURSOR, prc = pScrollingArea, pfnScroll = new ReaderScroll(ReaderScrollCallback), pfnTranslate = new TranslateDispatch(TranslateDispatchCallback), lParam = IntPtr.Zero, }; DoReaderMode(ref readerInfo); Marshal.FreeHGlobal(pScrollingArea); } private bool ReaderScrollCallback(ref READERMODEINFO prmi, int dx, int dy) { // コントロールをスクロールする HorizontalScrollingOffset += dy; FirstDisplayedScrollingRowIndex += dy; return true; } private bool TranslateDispatchCallback(ref MSG lpmsg) { return false; }