Goozo
Goozo

Reputation: 956

Change the cursor over a user control

I have a user control that shows an image and when hovering over the control the name of the image is displayed in a label beneath the image. I have put this user control in the TableLayoutPanel cells, which creates a table of images.

I am trying to change the cursor when the mouse goes over each control, or even over the form itself.

I have tried to put the

Cursor.Current = Cursors.Hand

In tried this in the MouseEnter event of the controller, the TableLayoutPanel and even in the parent form without any luck. Nothing happens. Why?

I have also noticed that this is something common in user controls and it is difficult to change the mouse cursor when entering a user control.

Does anyone have any clue how to change the cursor in a user control?

Upvotes: 3

Views: 4110

Answers (2)

Bharat Gupta
Bharat Gupta

Reputation: 2696

Add this line in the UserControl's constructor:

this.Cursor = Cursors.Hand;

There is a difference between setting Cursor.Current and this.Cursor. Check this post.

Just an addition:

To reset the Cursor for the entire UserControl even if one of the constituent controls has a different Cursor we can use a function like this:

private void SetCursor(Control rootControl, Cursor cursor)
{
    foreach (Control control in rootControl.Controls)
    {
        control.Cursor = cursor;
        if (control.HasChildren)
        {
            SetCursor(control, cursor);
        }
    }
}

Upvotes: 1

Cody Gray
Cody Gray

Reputation: 244782

Internally, each window has a cursor associated with it. (In Windows, controls are a type of window.) When the mouse pointer moves over that window, the operating system sends it a message (WM_SETCURSOR) asking it what cursor should be shown. The window responds with its associated cursor, and the system uses it. This is how a text box displays the I-beam cursor, for example.

Of course, the cursor is a global resource, so although it can be temporarily changed, as soon as the mouse pointer is moved over another control, the process described above will occur and the cursor will be changed back. This is what is happening when you set Cursor.Current. This makes a temporary change to the global cursor, but that temporary change is being essentially reverted by the cursor associated with your control. A temporary change like this is very convenient when, e.g., showing a busy cursor. It prevents you from having to remember to change the busy cursor back to the standard pointer.

If you always want a particular cursor to be displayed when the mouse pointer is over a control, you need to associate that cursor with that control. The operating system provides a means for doing this, and there is a very simple wrapper for it in WinForms. Just set the Cursor property of the control to whatever type of cursor you want. This can be one of the standard system-provided cursors, or a custom Cursor object that you create. You can set this property at design-time or in the control's constructor.

It is worth noting that the Cursor property is an ambient property, which is a special type of property. If an ambient property has not been explicitly set to a value, it will inherit its value from the control's parent. So this means that you can set the Cursor property for your entire Form, and all controls on the form will inherit that value and display the same cursor. (Internally, each control is actually a separate window, so without this, you'd need to go through and set the cursor for each control.)

If you have a sharp eye, though, you will immediately notice a problem. The Cursors.Hand cursor is ugly and non-standard. (This doesn't affect the other Cursors options.) Due to its age, WinForms doesn't actually use the system Hand cursor for this. It uses its own hard-coded black-and-white version, which will stick out like a sore thumb. If you want to fix it, it will take some extra work. I wrote up a solution a while back that shows how to subclass and fix the built-in LinkLabel control. You can adapt this for any control, including UserControl. All of the code will be identical, except for the names. After having read the background information in the beginning of my answer here, it should be clear to you exactly what the code is doing.

A final warning: the Cursors.Hand cursor often gets misused. Occasionally, you see people using this cursor over a button or some other control just to indicate that it can be "clicked". The hand cursor is intended to be used almost exclusively for web-style hyperlinks. The operating system itself follows this convention, and so should well-designed applications. That means it should not be used for standard buttons or anything that looks pliable—reserve its use for links that have a weak affordance and would not otherwise look clickable. I can't tell from the question if your use-case is appropriate. It may be, since it sounds like you have created a hyperlink. But I just feel like I should mention this for the benefit of future readers.

Upvotes: 6

Related Questions