2

I want to change my cursor image (everywhere on screen) when my program is running.

I try to load image with win32gui and then use win32api to change cursor image, but something is wrong and my cursor doesn't show up My cursor image is map.cur

import win32api
import time
import win32gui
import win32con

x = win32gui.LoadImage(0,'map.cur',win32con.IMAGE_CURSOR,0,0,win32con.LR_LOADFROMFILE)
win32api.SetCursor(x)

time.sleep(5)
ostry0728
  • 111
  • 2
  • 8
  • Have you check the return value of functions? If `x` is a valid `HCURSOR` and if SetCursor() execute successfully? – Rita Han May 03 '19 at 06:58
  • 1
    You're going to have to read the [documentation](https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setcursor) more carefully. Particular points of interest: *"The cursor is a shared resource. A window should set the cursor shape only when the cursor is in its client area or when the window is capturing mouse input. [...] If your application must set the cursor while it is in a window, make sure the class cursor for the specified window's class is set to NULL. If the class cursor is not NULL, the system restores the class cursor each time the mouse is moved."* – IInspectable May 03 '19 at 08:06
  • @RitaHan-MSFT I think it is valid 'HCURSOR' and it executes successfully because when I run my program cursor changes for like 0.1s but then changes back to my windows cursor. – ostry0728 May 03 '19 at 12:47
  • @IInspectable Sorry, I'm pretty new into programming and don't understand what should I do exactly. If I'm not wrong I can change cursor only in my program window? And when I try to go outside my window it will always change back to OEM? – ostry0728 May 03 '19 at 12:47

1 Answers1

5

Changing the system cursor is not recommended, because the cursor has to be restored after program exits, and if the program fails then user is stuck with custom cursor and must reset the cursor from system settings.

For the sake of curiosity, it can be done with SetSystemCursor, example

ctypes.windll.user32.SetSystemCursor(hcursor, 32512) #OCR_NORMAL

See documentation for OCR_NORMAL and other cursor constants.

You can try to save the old cursor and restore it, again, this method fails if your program exits abnormally.

import win32con
import win32api
import win32gui
import ctypes
import time
import atexit

#save system cursor, before changing it
cursor = win32gui.LoadImage(0, 32512, win32con.IMAGE_CURSOR, 
                            0, 0, win32con.LR_SHARED)
save_system_cursor = ctypes.windll.user32.CopyImage(cursor, win32con.IMAGE_CURSOR, 
                            0, 0, win32con.LR_COPYFROMRESOURCE)

def restore_cursor():
    #restore the old cursor
    print("restore_cursor");
    ctypes.windll.user32.SetSystemCursor(save_system_cursor, 32512)
    ctypes.windll.user32.DestroyCursor(save_system_cursor);

#Make sure cursor is restored at the end
atexit.register(restore_cursor)

#change system cursor
cursor = win32gui.LoadImage(0, "file.cur", win32con.IMAGE_CURSOR, 
                            0, 0, win32con.LR_LOADFROMFILE);
ctypes.windll.user32.SetSystemCursor(cursor, 32512)
ctypes.windll.user32.DestroyCursor(cursor);

time.sleep(3)
exit
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77