Change Mouse cursor for all Gadgets

Share your advanced PureBasic knowledge/code with the community.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Danilo.

Change the mouse cursor for gadgets with API:

Code: Select all

;
; Open a Window with Gadgets
;
hWnd = OpenWindow(1,10,10,400,200,#PB_Window_SystemMenu,"")
CreateGadgetList(hWnd)
  Button1   = ButtonGadget(1,210,10,100,25,"WAIT")
  Button2   = ButtonGadget(2,210,40,100,25,"HELP")
  ListView  = ListViewGadget(3,10,10,200,150)
;
; Set default cursor in all classes to 0
; Without doing this, flickering occurs
;
SetClassLong_(hWnd,#GCL_HCURSOR,0)
SetClassLong_(Button1,#GCL_HCURSOR,0)
SetClassLong_(Button2,#GCL_HCURSOR,0)
SetClassLong_(ListView,#GCL_HCURSOR,0)
;
; Load the cursors
;
#IDC_HELP = 32651
cur0 = LoadCursor_(0, #IDC_CROSS)
cur1 = LoadCursor_(0, #IDC_WAIT)
cur2 = LoadCursor_(0, #IDC_HELP)
cur3 = LoadCursor_(0, #IDC_NO)
;
; Main loop
;
Repeat
  Event = WaitWindowEvent()
  Gosub changecursor
  ;Select Event
  ;EndSelect
Until Event = #PB_EventCloseWindow
;
; End
;
DestroyCursor_(cur0)
DestroyCursor_(cur1)
DestroyCursor_(cur2)
DestroyCursor_(cur3)
End
;
; SUB for changing cursor
;
changecursor:
  GetCursorPos_(cursorpos.POINT)
  MapWindowPoints_(0, hWnd, cursorpos, 1)
    Select ChildWindowFromPoint_(hWnd, cursorpos\x, cursorpos\y)
      Case Button1   : SetCursor_(cur1)  ; Cursor over Button 1
      Case Button2   : SetCursor_(cur2)  ; Cursor over Button 2
      Case ListView  : SetCursor_(cur3)  ; Cursor over ListView
      Case hWnd      : SetCursor_(cur0)  ; Default, for the main window
    EndSelect
Return
cya,
...Danilo

(registered PureBasic user)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by PB.

> Change the mouse cursor for gadgets with API:

Thanks, but how do we load a cursor from a file?

UPDATE: Never mind -- I realised I needed LoadCursorFromFile_() to do it.

PB - Registered PureBasic Coder

Edited by - PB on 14 July 2002 12:16:18
User avatar
Michael Vogel
Addict
Addict
Posts: 2810
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

Does anybody know, if the mouse can be changed "globally"?

I failed with code like...

Code: Select all

hWnd = GetDesktopWindow_()
SetClassLong_(hWnd,#GCL_HCURSOR,0)
  
  For i=0 To 99
  SetCursor_(LoadCursor_(0, #IDC_WAIT))
   WaitWindowEvent()
   Delay(10)
   Next i
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

You can do it using the SetSystemCursor API, but it must be done with some care as the command destroys the current cursor. So before you execute it, you have to copy the current cursor to a safe place, then it can be restored later.

Have a look here:

http://msdn.microsoft.com/library/defau ... cursor.asp

Note that while Microsoft seems to imply that CopyCursor_() is a function, it is actually not. It is a macro mapped to the CopyIcon_() Api, and you can use CopyIcon_() anywhere you would like to use CopyCursor_().

Here is a (safe) little test :

Code: Select all

OpenWindow(0,0,0,320,240,"System Cursor Changer",#PB_Window_ScreenCentered) 
CreateGadgetList(WindowID(0)) 
ButtonGadget(0,100,100,100,20,"New Cursor") 
ButtonGadget(1,100,130,100,20,"Old Cursor") 
ButtonGadget(2,100,160,100,20,"Quit") 

Repeat 
  quit=0 
  ev=WaitWindowEvent() 
  If ev=#PB_Event_Gadget 
    Select EventGadget() 
      Case 0 
        newcursor=LoadImage_(0,OpenFileRequester("Select a Cursor","c:\windows\cursors\","Cursors (*.cur)|*.cur",0),#IMAGE_CURSOR,0,0,#LR_LOADFROMFILE|#LR_DEFAULTSIZE) 
        oldcursor=GetCursor_()          ;get a handle to the current cursor 
        oldcursor=CopyIcon_(oldcursor)  ;save a copy of the cursor 
        If newcursor
          SetSystemCursor_(newcursor, #OCR_NORMAL) 
          DisableGadget(0,1)
        EndIf 
      Case 1 
        SetSystemCursor_(oldcursor, #OCR_NORMAL) 
        DisableGadget(0,0) 
      Case 2 
        SetSystemCursor_(oldcursor, #OCR_NORMAL) 
        quit=1 
    EndSelect 
  EndIf 
Until quit
Just don't use the debugger to kill the program while a test cursor is set, or you won't be able to get the standard Windows cursor back without a restart (afaik).
BERESHEIT
User avatar
Michael Vogel
Addict
Addict
Posts: 2810
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

If you want to see the wait cursor also outside a "please wait a moment" message, I did the following workaround...

Code: Select all

Global MouseWait

Procedure Waiting(Nothing.l)
	MouseWait=#True
	Protected win=OpenWindow(0,0,0,4,4,"",#PB_Window_BorderLess)
	SetClassLong_(win,#GCL_HCURSOR,0)
	Protected punkt.POINT
	SetTimer_(win,0,10,0)
	Protected cursor=LoadCursor_(0,#IDC_WAIT)
	Repeat
		GetCursorPos_(@punkt)
		ResizeWindow(0,punkt\x-2,punkt\y-2,#PB_Ignore,#PB_Ignore)
		WaitWindowEvent()
		SetCursor_(cursor)
	Until MouseWait=#False
	DestroyCursor_(cursor)
	KillTimer_(win,0)
EndProcedure

CreateThread(@waiting(),0); Mouse changed to wait...
Debug "on"

If #False
	; not so perfect for such things...
	MessageRequester("Mouse Cursor","Waiting....")
Else
	; but works fine for "Wait a moment" messages...
	OpenWindow(1,0,0,200,80,"Waiting....",#PB_Window_ScreenCentered)
	CreateGadgetList(WindowID(1))
	TextGadget(1,10,10,150,30,"Mouse changed to IDC_Wait")
	Delay(2000)
	CloseWindow(1)
EndIf

MouseWait=#False;	Mouse again normal...
Debug "off"


Delay(5000);				check Mouse
Debug "ok"
User avatar
Blue
Addict
Addict
Posts: 967
Joined: Fri Oct 06, 2006 4:41 am
Location: Canada

Post by Blue »

Thank you, both of you.
With that i can finally show a MOVE cursor in my borderless dialog box window.

NetMaestro's code clearly shows how, with a few modifications, one could integrate icon DATA in the executable to then catch this image for the cursor...

But i still have a question:  How do you call on the system's built-in icons (à la Visual Basic, not to name it) for a particular situation ?

I find the PB built-in mouse functions to be lacking both in number and flexibility. You have to be an API expert to get most things done.

Oopsy...
Brain finally operating !!!
Of course, cursors are *.CUR files, not *.ICO files, so my plan to Catch a cursor image from a DATA section appears doomed, unless someone has a very bright idea.

Looks like i'll have to study NetMaestro's code (see following message) a lot longer than i expected.
Last edited by Blue on Fri Oct 17, 2008 6:08 am, edited 2 times in total.
PB Forums : Proof positive that 2 heads (or more...) are better than one :idea:
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Look in the IDE's structure viewer for constants beginning with #IDC_, they're all system cursors and there's lots in there. They can all be used with LoadCursor_() etc. For using different cursors when hovering over specific objects in your window, you can subclass the affected gadgets and trap the #WM_SETCURSOR message where you will use SetCursor_() to show the one you want and return 0. Have fun!

Code: Select all

Global hand = LoadCursor_(0, #IDC_HAND)
[..]

  Case #WM_SETCURSOR
    SetCursor_(hand)
    ProcedureReturn 0
BERESHEIT
User avatar
Blue
Addict
Addict
Posts: 967
Joined: Fri Oct 06, 2006 4:41 am
Location: Canada

Post by Blue »

netmaestro wrote:Look in the IDE's structure viewer for constants beginning with #IDC_ [...]
Gee ! That was quick. I was still changing my message when the answer was posted.
I'll have to study (no kidding!) your answer, Maestro, before I can make use of it.
I'm still working on modifying your sample code so I can load icon data with IncludeBinary "..." and use that with one of the Catch instructions.

Thanks a lot.
Last edited by Blue on Fri Oct 17, 2008 6:10 am, edited 1 time in total.
PB Forums : Proof positive that 2 heads (or more...) are better than one :idea:
User avatar
Blue
Addict
Addict
Posts: 967
Joined: Fri Oct 06, 2006 4:41 am
Location: Canada

Post by Blue »

OK. I think I get it. (think is the key word here!)
netmaestro wrote:[...] you can subclass the affected gadgets and trap the #WM_SETCURSOR message [...] Have fun!

Code: Select all

  Case #WM_SETCURSOR
    SetCursor_(hand)
    ProcedureReturn 0
The Case selector quoted above would become part of a Callback function just waiting to jump on whatever I specify ?

Wooo... I'm not there yet, but am i ever glad you caught up with me and pointed me in the right direction. I was on my way, by camel back, across the Sahara when you called!

Fun, you were saying ? Yep.

Thanks again.
PB Forums : Proof positive that 2 heads (or more...) are better than one :idea:
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Post by Rook Zimbabwe »

This has been incredibly hhelpful! I have read the code and read the API stuff from PureArea.net and learned much!

Now to HIDE the cursor!
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
Post Reply