Change Windows cursor globally in WPF

It is very obvious that we can change the cursor in WPF using FrameworkElement.Cursor. But the trick is, it only works within your application and not outside your application Main Window. In case if you want to change the cursor for the entire OS, we don’t have any direct way in WPF. But most of the developers worried why we need to change the entire Windows cursor. But take an example, if we are developing an eye dropper control in WPF (used to pick color). Not like the one in Illustrator or Photoshop (cannot pick color outside the application), but the one we have in Expression Blend or Visual Studio designer (can pick color even outside the application also).

In that cases, the cursor should be changed, because arrow cursor will not be a comfortable one to pick color. Normally cursor values resides in registry.

Registry Key : HKEY_CURRENT_USER\Control Panel\Cursors

Changing the values here will change the cursor, but your system needs a reboot to take effect (I can understand, none of the developers will accept this). To avoid that and make your app. taking immediate effect, you need to invoke a pinvoke call.

The following method will refresh the cursor  values,

        [DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
        public static extern bool SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni); 

Iterate through registry values and change the cursor path.

        private void ChangeCursor()
        {
            RegistryKey pRegKey = Registry.CurrentUser;
            pRegKey = pRegKey.OpenSubKey(@"Control Panel\Cursors");
            paths.Clear();
            foreach (var key in pRegKey.GetValueNames())
            {
                Object _key = pRegKey.GetValue(key);
                //Take a backup.

                paths.Add(key, _key.ToString());                 Object val = Registry.GetValue(@"HKEY_CURRENT_USER\Control Panel\Cursors", key, null);                 Registry.SetValue(@"HKEY_CURRENT_USER\Control Panel\Cursors", key, "foo.cur");             }                         SystemParametersInfo(InteropHelper.SPI_SETCURSORS, 0, null, InteropHelper.SPIF_UPDATEINIFILE | InteropHelper.SPIF_SENDCHANGE);           }

Make sure you store the registry values before change it, so that you can restore the cursor to the default values.

              private void ResetCursorToDefault()
        {

            RegistryKey pRegKey = Registry.CurrentUser;
            pRegKey = pRegKey.OpenSubKey(@"Control Panel\Cursors");
            foreach (string key in paths.Keys)
            {
                string path = paths[key];
                Registry.SetValue(@"HKEY_CURRENT_USER\Control Panel\Cursors", key, path);
            }
            InteropHelper.SystemParametersInfo(InteropHelper.SPI_SETCURSORS, 0, null, InteropHelper.SPIF_UPDATEINIFILE | InteropHelper.SPIF_SENDCHANGE);
        }

The InteropHelper class has been posted in this article.

2 thoughts on “Change Windows cursor globally in WPF

Add yours

Leave a comment

Up ↑