如何使用wm_notify捕获LVN_BEGINSCROLL,以获取ListView的子类



这里建议使用它以使用鼠标滚轮产生滚动事件。我阅读了官方文档,但仍然不知道如何在C#中使用它。我有这个答案主要有代码。

我的代码是:

internal class EnhancedListView : ListView
{
    internal event ScrollEventHandler ScrollEnded,
        ScrollStarted;
    const int WM_NOTIFY = 0x004E;
    internal EnhancedListView()
    {
        Scroll += EnhancedListView_Scroll;
    }
    ScrollEventType mLastScroll = ScrollEventType.EndScroll;
    private void EnhancedListView_Scroll(object sender, ScrollEventArgs e)
    {
        if (e.Type == ScrollEventType.EndScroll)
        {
            ScrollEnded?.Invoke(this, e);
        }
        else if (mLastScroll == ScrollEventType.EndScroll)
        {
            ScrollStarted?.Invoke(this, e);
        }
        mLastScroll = e.Type;
    }
    internal event ScrollEventHandler Scroll;
    protected virtual void OnScroll(ScrollEventArgs e)
    {
        Scroll?.Invoke(this, e);
    }
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == 0x115)
        {
            // WM_VSCROLL
            OnScroll(
                new ScrollEventArgs(
                    (ScrollEventType)(m.WParam.ToInt32() & 0xffff),
                    0
                )
            );
        }
        else if (m.Msg == WM_NOTIFY)
        {
            // What should I put here?
        }
    }
}

我偶然发现了您的问题,同时试图解决相同的问题。我已经从此答案中综合了以下内容(关于处理WM_NOTIFY消息)和葡萄酒源代码(为LVN_BEGINSCROLL提供整数值):

[StructLayout(LayoutKind.Sequential)]
private struct NMHDR
{
    public IntPtr hwndFrom;
    public IntPtr idFrom;
    public int code;
}
const int LVN_FIRST = -100;
const int LVN_BEGINSCROLL = LVN_FIRST - 80;
const int WM_REFLECT = 0x2000;
...
else if(m.Msg == WM_NOTIFY + WM_REFLECT)
{
    var notify = (NMHDR)Marshal.PtrToStructure(m.LParam, typeof(NMHDR));
    if(notify.code == LVN_BEGINSCROLL)
    {
        OnScroll(new ScrollEventArgs((ScrollEventType)(m.WParam.ToInt32() & 0xffff), 0));
    }
}

最新更新