listviewvisual-studio-2015c++-clihorizontal-scrollingmotion-detection

How to detect horizontal scroll movement in Listview?(for VS2015 C++/CLI)


How do I detect horizontal scroll movement in Listview by mouse click, mouse scroll and keyboard ? There are similar topics like this. I've tried most of them but none worked so far.


Solution

  • Creating your own scrollbar is the only way i suppose.. Here it is the solution:

    using namespace System::Runtime::InteropServices;
    using namespace System::Security::Permissions;
    
    [DllImport("User32.dll")]
    [returnvalue:MarshalAs(UnmanagedType::Bool)]
    extern "C" System::Boolean ShowScrollBar(IntPtr hWnd, int wBar, bool bShow);
    [DllImport("User32.dll")]
    extern "C" System::Void SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
    
    public ref class myListView : ListView
    {
        public: myListView(void)
        {
            myVScrollBar = gcnew VScrollBar();
            myVScrollBar->Dock = DockStyle::Right;
            myVScrollBar->SmallChange = 1;
            myVScrollBar->LargeChange = 2;
            myVScrollBar->Minimum = 0;
            ViewableCount = 1;
            myVScrollBar->Visible = false;
            Wheeling = false;
            up = false;
    
            myVScrollBar->ValueChanged += gcnew EventHandler(this, &myListView::myVScrollBar_WheelChanged);
            myVScrollBar->Scroll += gcnew ScrollEventHandler(this, &myListView::myVScrollBar_ScrollChanged);
            Controls->Add(myVScrollBar);
        }
    
        private:
            int ViewableCount;
            bool Wheeling;
            bool up;
    
        public:
            VScrollBar^ myVScrollBar;
    
        [SecurityPermission(SecurityAction::Demand, Flags = SecurityPermissionFlag::UnmanagedCode)]
        virtual void WndProc(Message% m) override
        {
            ShowScrollBar(Handle, SB_VERT, false);
            __super::WndProc(m);
    
            switch (m.Msg)
            {
                case WM_MOUSEWHEEL:
                {
                    Wheeling = true;
                    up = (GET_WHEEL_DELTA_WPARAM(reinterpret_cast<int*>(m.WParam.ToPointer())) > 0);
                    if (up)
                    {
                        if (myVScrollBar->Value - ViewableCount > 0)
                            myVScrollBar->Value -= ViewableCount;
                        else
                            myVScrollBar->Value = 0;
                    }
                    else
                    {
                        if (myVScrollBar->Value + myVScrollBar->LargeChange + ViewableCount <= myVScrollBar->Maximum)
                            myVScrollBar->Value += ViewableCount;
                        else
                            myVScrollBar->Value = 1 + myVScrollBar->Maximum - myVScrollBar->LargeChange;
                    }
                }
                break;
                case WM_VSCROLL:
                {
                    switch (m.WParam.ToInt32())
                    {
                        case SB_PAGEUP:
                            if (myVScrollBar->Value - ViewableCount > 0)
                                myVScrollBar->Value -= ViewableCount-1;
                            else
                                myVScrollBar->Value = 0;
                            break;
                        case SB_PAGEDOWN:
                            if (myVScrollBar->Value + myVScrollBar->LargeChange + ViewableCount <= myVScrollBar->Maximum)
                                myVScrollBar->Value += ViewableCount-1;
                            break;
                    }
                }
                break;
            }
        }
    
        private: System::Void myVScrollBar_WheelChanged(Object^ sender, EventArgs^ e)
        {
            if (!Wheeling)
                return;
    
            SendMessage(Handle, 0x1000 + 20, 0, up ? -10 : 10);
        }
    
        private: System::Void myVScrollBar_ScrollChanged(Object^ sender, ScrollEventArgs^ e)
        {
            Wheeling = false;
    
            if (e->OldValue == e->NewValue)
                return;
    
            int t = e->NewValue;
            int i = e->OldValue;
            if (e->OldValue > e->NewValue)
            {
                t = e->OldValue;
                i = e->NewValue;
            }
            for (i; i < t; ++i)
                SendMessage(Handle, 0x1000 + 20, 0, e->NewValue - e->OldValue > 0 ? 10 : -10);
        }
    };
    

    Then you set maximum value for the scroll bar and make it visible:

    lvNufus->myVScrollBar->Visible = totalItems > 20 ? true : false;
    lvNufus->myVScrollBar->Maximum = totalItems > 20 ? (miktar - 20 + 1) : 1; 
    

    totalItems represents total amount of items added into myListView. And the value 20 represents items displayed in total. This is for vertical scroll.