Page 1 of 1

Want to change mouse Cursor inside GUI? Here is how

Posted: 28 Jan 2019, 16:41
by kyuuuri
First of all, we won't be using OnMessage or a timer here, we are going to directly change the cursor for the gui.

First: We are going to create a GUI

Code: Select all

gui, +HwndMyGui
gui, add, edit, +HwndMyEdit backgroundtrans
gui, show, w100 h100
I decided to add an edit just as an example.

Second: We are going to load the cursor

Code: Select all

path := "G:\Cursor.ani"
test := DllCall("LoadImageW", "Uint", 0, "Ptr", &path, "Uint", 0x2, "int", 0, "int", 0, "Uint", 0x10)
There are more ways to load a cursor, see: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-loadimagew and https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-loadcursorfromfilew for more details.

Third: We are going to set the cursor class for our gui

Code: Select all

DllCall("SetClassLongPtrW", "Uint", MyGui, "int", -12, "Ptr", test)
And that's all!
This is the finished code:

Code: Select all

; Variables:
;MyGui = is the Hwnd for our main gui, it's declared on the first line where we create our gui.
;MyEdit = is the Hwnd for our edit control, it's declared on the second line where we create add edit control.
;Path = is the path to the cursor.
;test = is the handle to our cursor, it's the return value from the LoadImageW function

gui, +HwndMyGui
gui, add, edit, +HwndMyEdit backgroundtrans
gui, show, w100 h100
path := "G:\Cursor.ani"
test := DllCall("LoadImageW", "Uint", 0, "Ptr", &path, "Uint", 0x2, "int", 0, "int", 0, "Uint", 0x10)
DllCall("SetClassLongPtrW", "Uint", MyGui, "int", -12, "Ptr", test)
But wait, what if I want to use a custom cursor for each control?
You can do the same you did with this tutorial and change the hwnd on the last step. (The hwnd is "MyGui" in the example) Of course you will have to load each cursor.
It would be like this:

Code: Select all

; Variables:
;MyGui = is the Hwnd for our main gui, it's declared on the first line where we create our gui.
;MyEdit = is the Hwnd for our edit control, it's declared on the second line where we create add edit control.
;Path = is the path to the cursor.
;test = is the handle to our cursor, it's the return value from the LoadImageW function

gui, +HwndMyGui
gui, add, edit w100 h20, +HwndMyEdit backgroundtrans
gui, show, w100 h100
path := "G:\Cursor.ani"
path2 := "G:\Cursor2.ani"
test := DllCall("LoadImageW", "Uint", 0, "Ptr", &path, "Uint", 0x2, "int", 0, "int", 0, "Uint", 0x10)
test2 := DllCall("LoadImageW", "Uint", 0, "Ptr", &path2, "Uint", 0x2, "int", 0, "int", 0, "Uint", 0x10)
DllCall("SetClassLongPtrW", "Uint", MyGui, "int", -12, "Ptr", test)
DllCall("SetClassLongPtrW", "Uint", MyEdit, "int", -12, "Ptr", test2)
Troubleshooting:
My cursor goes back to normal when mouse is over a control's border
That's because the border of some controls (like the border of an Edit control) is not part of the Client Area (The client area is where our cursor is changed). We can fix this by removing that border using WinSet.
For my second example it would be like this:

Code: Select all

WinSet, Region, 2-2 w96 h16, ahk_id %MyEdit%
2-2 This will remove 2 pixels of every direction.
w96 h16 This will tell the WinSet command that our control now has w96 and h16. It's the result of removing 2 pixels north and south from the height, and 2 pixels east and west from the width. That is 100-2-2= 96 and 20-2-2=16
ahk_id %MyEdit% This is the Window's Handle (hwnd) of my control.

Special thanks to:
@CloakerSmoker (that's his/her discord name) who helped me with this. This was teamwork he/she made 99.999999999999% of the code (for the changing cursor thing), and I added a return and asked a lot of questions.
@SALZKARTOFFEEEL (that's his discord name) who helped me to fix the problem with control's borders, again teamwork, I asked how to fix it and he made 100% of the code.
Teamwork is the key to success(?)

Re: Want to change mouse Cursor inside GUI? Here is how

Posted: 29 Jan 2019, 03:11
by SL5
thanks for this tutorial :) i never did a cursor change by programming. your solution looks easy, good documenttad :)

Re: Want to change mouse Cursor inside GUI? Here is how

Posted: 12 Mar 2019, 18:36
by DRocks
@kyuuuri
Dude, this is fabulous.
Very nice stuff.

It opens possibilities too with that WinSet region for a CONTROL. How did I never think about that :D
Also its really nice that it can skip the OnMessage part and only be set once and for all.