2013-10-14 6 views
1

Я создаю логику для прокрутки элемента управления под мышью без фокуса (стиль внешнего вида) в моей форме. Я могу добиться такого поведения, используя IMessageFilter. Однако я испытываю трудности с применением горизонтальной прокрутки, если нажата клавиша «SHIFT».Горизонтальная прокрутка с помощью колеса мыши (C# и WinAPI)

using System; 
using System.ComponentModel; 
using System.Text; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 
using System.Drawing; 


public partial class UI : Form 
{ 
    MouseWheelMessageFilter mouseFilter = null; 
    public UI() 
    { 
     InitializeComponent(); 
     mouseFilter = new MouseWheelMessageFilter(); 
     Application.AddMessageFilter(mouseFilter); 
     this.FormClosed += (o, e) => Application.RemoveMessageFilter(mouseFilter); 
    } 
} 

public class MouseWheelMessageFilter : IMessageFilter 
{ 
    [DllImport("user32.dll")] 
    public static extern IntPtr WindowFromPoint(Point pt); 

    [DllImport("user32.dll")] 
    public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); 


    public const int MK_CONTROL = 0x0008; 
    public const int MK_SHIFT = 0x0004; 

    public const int WM_MOUSEWHEEL = 0x020A; 
    public const int WM_MOUSEHWHEEL = 0x020E; 


    public bool PreFilterMessage(ref Message m) 
    { 
     if (m.Msg == WM_MOUSEWHEEL) 
     { 
      var shiftKeyDown = (char)((Keys)m.WParam) == MK_SHIFT; 

      //apply the scroll to the control at mouse location 
      Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16); 
      IntPtr hWnd = WindowFromPoint(pos); 

      if (hWnd != IntPtr.Zero && hWnd != m.HWnd && Control.FromHandle(hWnd) != null) 
      { 
       if (shiftKeyDown) 
        //TODO: Horizontal scroll - Not working WM_MOUSEHWHEEL (0x020E) 
        //SendMessage(hWnd, WM_MOUSEHWHEEL, m.WParam, m.LParam); 
       else 
        //Vertical Scroll - working 
        SendMessage(hWnd, WM_MOUSEWHEEL, m.WParam, m.LParam); 
       return true; 
      } 
     }   
     return false; 
    } 
} 

Что мне нужно делать в разделе // TODO для работы горизонтальной прокрутки?

+0

A * lot * приложений не поддерживает WM_MOUSEHWHEEL. В проекте, над которым я работал, нам пришлось писать код, чтобы находить полосы прокрутки и программно манипулировать ими (у которых есть множество собственных проблем). –

+2

Еще несколько заметок: лучше использовать 'PostMessage' при отправке сообщений в ваши окна, а не' SendMessage'. Если вы * должны * отправлять сообщения (вместо публикации), используйте 'SendMessageTimeout'. –

ответ

2

Это только предположение, я не могу проверить это сам, но я заметил, что вы фильтруются только для:

if (m.Msg == WM_MOUSEWHEEL) 

вам нужно фильтровать WM_MOUSEHWHEEL отдельно сделать:

if (m.Msg == WM_MOUSEHWHEEL) 

Тогда, возможно, вам не нужно проверять ключ переключения?

редактировать: это то, что я думал:

public bool PreFilterMessage(ref Message m) 
{ 
    if (m.Msg == WM_MOUSEWHEEL || m.Msg == WM_MOUSEHWHEEL) 
    { 
     //apply the scroll to the control at mouse location 
     Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16); 
     IntPtr hWnd = WindowFromPoint(pos); 
     if (hWnd != IntPtr.Zero && hWnd != m.HWnd && Control.FromHandle(hWnd) != null) 
     { 
      SendMessage(hWnd, m.Msg, m.WParam, m.LParam); 
      return true; 
     } 
    } 
    return false; 
} 

К сожалению, если это не работает, я не в состоянии собрать это до, чтобы проверить это прямо сейчас, это только предположение, что вы выиграли» t получить WM_MOUSEWHEEL, если у пользователя SHIFT удерживается (вместо этого получить WM_MOUSEHWHEEL)

+0

Так как у меня нет мыши, поддерживающей горизонтальный свиток, я пытаюсь преобразовать «SHIFT + Mosuse Scroll» в горизонтальную прокрутку. btw, вы получите WM_MOUSEWHEEL, даже если вы нажали клавишу «Shift». – Riju