4
votes

I'm trying to change the cursor that appears on a standard ListView when the cursor appears over an item. However I am getting a flickering effect as the mouse is changed to a finger cursor, and then back to what I asked it to be.

I'm trying to isolate this flicker/changing to the hand cursor but can't figure out where it's occuring or how to stop it. To replicate this...

1) Create a form with a ListView on it. 2) Add an image list and some images. Set the view to the large icon mode. 3) Add some items to the ListView.

Add a MouseMove event to the ListView:

private void listView1_MouseMove(object sender, MouseEventArgs e)
{
    ListViewItem selected = this.listView1.GetItemAt(e.X, e.Y);
    if (selected == null)
    {
        base.Cursor = Cursors.Default;
    }
    else
    {
        base.Cursor = Cursors.No;
    }
}

Execute the app, moving the mouse over an item. You should see the cursor flickering between the No (no entry cursor) and the finger pointer when you're over an item. The question is how to ensure it just displays the No cursor and to not flicker. (C# .NET).

I've tried override both OnMouseMove and OnMouseHover to returning to ensure these don't set anything. I've also tried overriding the Cursor property and saying 'only set to default or no cursors' and that didn't work either.

Any help's appreciated.

Ian

2
Does it happen elsewhere? For example, when navigating over hyperlinks or in other applications? Or does it only happen in your application? If so, it is probably more an OS issue... - Razzie
It's cross platform, cross application. If you read my comment to teknohippy... The problem is exaggerated with manual drawing of items and hottracking. I've tried overriding WndProc to return if the (m.Msg == 0x020) to change cursor. Something switches it to a hand, but I'm not sure what. - Ian
What do you have the ListView's Activation property set to? If it's OneClick, then the control itself will change the cursor to the Hand cursor when you hover over an item. - EricLaw

2 Answers

8
votes

The problem is that C# ListView Control is basically a wrapper around windows List View Control. So when we set the cursor to Arrow, the underlying listview control always defaulted to Hand cursor while our setting in the C# ListView class wanted it to be an Arrow. That's why we were getting that flickering, because underlying control was reverting back to Hand.

Here is the code that you need to add:

public const uint LVM_SETHOTCURSOR = 4158;

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

SendMessage(listView1.Handle, LVM_SETHOTCURSOR, IntPtr.Zero, Cursors.Arrow.Handle);

It's very important that you call the SendMessage from your Form's onLoad event because by then the underlying ListView control is completely initialized!

It's pretty simple actually, Have a great day! :)

0
votes

Without having tried it, cursors are normally changed in response to WM_ SETCURSOR, so maybe you are in conflict with the default WM_ SETCURSOR handling of the ListView. I would try to create a new UserControl deriving from ListView and then trap WM_ SETCURSOR in WndProc and see if that helps.