Big Cross Mouse Cursor [Windows]

Share your advanced PureBasic knowledge/code with the community.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Big Cross Mouse Cursor [Windows]

Post by RASHAD »

Tested with PB v4.61 x86 Windows XP x86 -Windows 7 x64
Escape to quit

Code: Select all

Global hWnd_0,hWnd_1,hhkLLMouse,Width,Height

ExamineDesktops()
Width = DesktopWidth(0)
Height = DesktopHeight(0)

Procedure MouseHook(nCode, wParam, lParam)
      Select wParam
         Case #WM_LBUTTONDOWN
            Debug "OK"
                     
         Case #WM_MOUSEMOVE
            GetCursorPos_(p.POINT)
            MoveWindow_(hWnd_0,0,p\y+2,Width,2,1)
            MoveWindow_(hWnd_1,p\x+2,0,2,Height,1)
            SetWindowPos_(hWnd_0, #HWND_TOPMOST, 0, 0, 0, 0,#SWP_NOSIZE|#SWP_NOMOVE| #SWP_SHOWWINDOW|#SWP_NOACTIVATE)
            SetWindowPos_(hWnd_1, #HWND_TOPMOST, 0, 0, 0, 0,#SWP_NOSIZE|#SWP_NOMOVE| #SWP_SHOWWINDOW|#SWP_NOACTIVATE)
      
      EndSelect
  ProcedureReturn CallNextHookEx_(0, nCode, wParam, lParam)
EndProcedure

hWnd_0 = OpenWindow(0,0,Height/2,Width,1,"",#PB_Window_BorderLess)
hWnd_1 = OpenWindow(1,Width/2,0,1,Height,"",#PB_Window_BorderLess,WindowID(0))
SetWindowColor(0,$0000FF)
SetWindowColor(1,$0000FF)

hhkLLMouse = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseHook(), GetModuleHandle_(0), 0)

Repeat
    Select WaitWindowEvent()      
       
    EndSelect
   
Until GetAsyncKeyState_(#VK_ESCAPE) & 1
UnhookWindowsHookEx_(hhkLLMouse)

Egypt my love
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Big Cross Mouse Cursor [Windows]

Post by IdeasVacuum »

Hi Rashad

Well, I really need a good cross hair cursor, my attempts so far either not good on XP or not good on Win7, or not good on both :cry:

Anything with the word MouseHook sounds lower-level to me (= more likely to be successful) but compiled as an exe, I see graphics problems with your cursor: Cursor on XP 32bit

Edit: In another post on this subject System-wide cross hair cursor
I linked to this solution by Mike Lin: CrossHair. This one works perfectly on XP and Win7 here and I think perhaps it does so by using a mouse-hook technique.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Big Cross Mouse Cursor [Windows]

Post by IdeasVacuum »

Well, I have made one that works here on both XP 32bit and Win7 64bit, compiled as a 32bit exe.

LoadImage() will allow a large file to be used - so I have simply created a giant bitmap. It's only 1 bit, but is still a large file at 1MB. That's an issue because it takes 4 or 5 seconds to load. I'm wondering if it would be possible to include it in a data section and if that would reduce the start-up time.

Code: Select all

Global ighBigCursor.i = LoadImage_(GetModuleHandle_(0),"BigCursor01",#IMAGE_CURSOR,0,0,0)

SetSystemCursor_(ighBigCursor,#OCR_NORMAL)

Repeat

Until GetAsyncKeyState_(#VK_ESCAPE) & 1

;### Reset Cursor Pointers Set
SystemParametersInfo_(#SPI_SETCURSORS,0,#Null,#Null)
                Delay(1)

End

;
;GlobalCursor.rc
;BigCursor01 CURSOR "C:\PROJECTS_DrvC\GlobalCursor\BigCursor01.cur"
;
Link to download the cursor file: BigCursor01
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Big Cross Mouse Cursor [Windows]

Post by IdeasVacuum »

...tried drawing the cursor instead of loading from Resource.
Two problems -
(1) Really simple image but I can't get the mask to work :oops:
(2) It is just as slow as loading from Resource

Code: Select all

#CursorMask01 = 1
#CursorImage02 = 2

CreateImage(#CursorMask01,2048,2048,24)
CreateImage(#CursorImage02,2048,2048,24)

If StartDrawing(ImageOutput(#CursorMask01))

                ;x1  ;y1  ;x2  ;y2
            Box(   0,    0, 2048, 2048, RGB(255,255,255))
         LineXY(1024,    0, 1024, 2048, RGB(0,0,255))
         LineXY(   0, 1024, 2048, 1024, RGB(0,0,255))
    StopDrawing()
EndIf

If StartDrawing(ImageOutput(#CursorImage02))

                 ;x1  ;y1  ;x2  ;y2
            Box(   0,    0, 2048, 2048, RGB(255,255,255))
         LineXY(1024,    0, 1024, 2048, RGB(0,0,0))
         LineXY(   0, 1024, 2048, 1024, RGB(0,0,0))
    StopDrawing()
EndIf

icoInf.ICONINFO
icoInf\fIcon = #False
icoInf\xHotspot = 1024
icoInf\yHotspot = 1024
icoInf\hbmMask = ImageID(#CursorMask01)
icoInf\hbmColor = ImageID(#CursorImage02) 

ighBigCursor = CreateIconIndirect_(icoInf)

SetSystemCursor_(ighBigCursor,#OCR_NORMAL)

Repeat

Until GetAsyncKeyState_(#VK_ESCAPE) & 1

;### Reset Cursor Pointers Set
SystemParametersInfo_(#SPI_SETCURSORS,0,#Null,#Null)
                Delay(1)

End
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Big Cross Mouse Cursor [Windows]

Post by RASHAD »

Hi

Code: Select all

ExamineDesktops()
Width = DesktopWidth(0)
Height = DesktopHeight(0)

CreateImage(0, Width*2,Height*2)
CreateImage(1,  Width*2,Height*2)
 
StartDrawing(ImageOutput(0))
  Box(0,0,Width*2,Height*2,#White)
  LineXY(0,Height,Width*2,Height,#Red)
  LineXY(Width,0,Width,Height*2,#Red)
  Circle(Width,Height,10,#Red)
  Circle(Width,Height,7,#White)
StopDrawing()

StartDrawing(ImageOutput(1))
  Box(0,0,Width*2,Height*2,#Red)
StopDrawing()

iinf.ICONINFO
iinf\fIcon = #False
iinf\xHotspot = Width
iinf\yHotspot = Height
iinf\hbmMask = ImageID(0)
iinf\hbmColor = ImageID(1)

curHnd = CreateIconIndirect_(iinf)

SetSystemCursor_(curHnd,#OCR_NORMAL)

Repeat

Until GetAsyncKeyState_(#VK_ESCAPE) & 1

SystemParametersInfo_(#SPI_SETCURSORS,0,#Null,#Null)
 Delay(1)

End

Edit :Modified for enhancement
Egypt my love
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Big Cross Mouse Cursor [Windows]

Post by IdeasVacuum »

Hi Rashad

Well, without the circle, the mask does not work properly :cry:
.... and still the issue is the slow loading.

I think Mike Lin must be doing something like this though because his app is so small. Perhaps a slow load is disguised by loading during PC boot-up.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Big Cross Mouse Cursor [Windows]

Post by Kwai chang caine »

The first code works fine on VISTA :D
It's crazy to see what you can do, with two windows :lol:
Thanks RASHAD 8)
ImageThe happiness is a road...
Not a destination
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Big Cross Mouse Cursor [Windows]

Post by RASHAD »

Hi KCC thanks

Hi IdeasVucuum
There is no way to speed the loading time(I did my best)
I still prefer the first solution(until now :mrgreen: )
Updated the code for XP check and for your information PB is using the Low Level Hook
See yourself
About the mask I have a doubt that Your PC needs some cleaning
What is your configuration mate?

Code: Select all

Global hWnd_0,hWnd_1,hhkLLMouse,Width,Height

ExamineDesktops()
Width = DesktopWidth(0)
Height = DesktopHeight(0)

Procedure MouseHook(nCode, wParam, lParam)
      
      Select wParam
         Case #WM_MBUTTONDOWN
            UnhookWindowsHookEx_(hhkLLMouse)
            SystemParametersInfo_(#SPI_SETCURSORS,0,0,0)               
            End
            
            
         Case #WM_LBUTTONDOWN,#WM_LBUTTONUP
              SHChangeNotify_($8000000, $1000, 0, 0)             
          
                     
         Case #WM_MOUSEMOVE
              GetCursorPos_(p.POINT)              
              SetWindowPos_(hWnd_0, #HWND_TOPMOST, 0,p\y+2,Width,1,#SWP_NOSIZE|#SWP_DRAWFRAME)
              SetWindowPos_(hWnd_1, #HWND_TOPMOST, p\x+2,0,1,Height,#SWP_NOSIZE|#SWP_DRAWFRAME)
              SHChangeNotify_($8000000, $10000, 0, 0)
              
     
      EndSelect
  ProcedureReturn CallNextHookEx_(0, nCode, wParam, lParam)
EndProcedure

hWnd_0 = OpenWindow(0,0,Height/2,Width,1,"",#PB_Window_BorderLess)
hWnd_1 = OpenWindow(1,Width/2,0,1,Height,"",#PB_Window_BorderLess)
SetWindowColor(0,#Yellow)
SetWindowColor(1,#Yellow)

hhkLLMouse = SetWindowsHookEx_(#WH_MOUSE_LL, @MouseHook(), GetModuleHandle_(0), 0)

Repeat
    Select WaitWindowEvent()     
       
    EndSelect   
Until GetAsyncKeyState_(#VK_ESCAPE) & 1




PB style :

Code: Select all

Global hWnd_0,hWnd_1,Width,Height,Quit

ExamineDesktops()
Width = DesktopWidth(0)
Height = DesktopHeight(0)

hWnd_0 = OpenWindow(0,0,Height/2,Width,1,"",#PB_Window_BorderLess)
hWnd_1 = OpenWindow(1,Width/2,0,1,Height,"",#PB_Window_BorderLess,WindowID(0))
SetWindowColor(0,$0000FF)
SetWindowColor(1,$0000FF)

SetSystemCursor_(curHnd,#OCR_NORMAL)

Repeat
    MoveWindow_(hWnd_0,0,DesktopMouseY()+2,Width,2,1)
    MoveWindow_(hWnd_1,DesktopMouseX()+2,0,2,Height,1)
    ;SetWindowPos_(hWnd_0, #HWND_TOPMOST, 0, 0, 0, 0,#SWP_NOSIZE|#SWP_NOMOVE| #SWP_SHOWWINDOW|#SWP_NOACTIVATE)
    ;SetWindowPos_(hWnd_1, #HWND_TOPMOST, 0, 0, 0, 0,#SWP_NOSIZE|#SWP_NOMOVE| #SWP_SHOWWINDOW|#SWP_NOACTIVATE)
Until GetAsyncKeyState_(#VK_ESCAPE) & 1

Egypt my love
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Big Cross Mouse Cursor [Windows]

Post by IdeasVacuum »

I have noticed something interesting with the app loading time - it is not LoadImage_ that is taking that time. As an experiment, I loaded 6 giant cursors (different colours). The time from app start to cursor on screen is the same as with one giant cursor being loaded. Once the app is running, switching between the different cursors is instant.

Concerning the mask issue, I don't think that is system/hardware persay. I do think it might be the rendering of the cursor image, where having the line start right at the edge of the cursor image border might break the transparency - I will test that later, unfortunately I have to drive the Mrs to town :mrgreen:
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Big Cross Mouse Cursor [Windows]

Post by IdeasVacuum »

OK, hunch about the cursor lines start/finish right at the edge of the image boundary was correct - just nipping them in a few pix removes the mask problem, which did have a wrinkle in it and that's fixed too in the code below:

Code: Select all

Enumeration
#CursorMask
#CursorImage
EndEnumeration

CreateImage(#CursorMask,2048,2048,24)
CreateImage(#CursorImage,2048,2048,24)

If StartDrawing(ImageOutput(#CursorMask))

                 ;x1  ;y1  ;x2  ;y2
            Box(   0,    0, 2048, 2048, RGB(255,255,255))
         LineXY(1014,   10, 1014, 2038, RGB(0,0,0))
         LineXY(  10, 1014, 2038, 1014, RGB(0,0,0))
    StopDrawing()

EndIf

;### Cursor 1
If StartDrawing(ImageOutput(#CursorImage))

                ;x1   ;y1   ;x2   ;y2
            Box(   0,    0, 2048, 2048, RGB(0,0,0))
         LineXY(1014,   10, 1014, 2038, RGB(255,0,0)) ;<-- Change this value for different colour cursor
         LineXY(  10, 1014, 2038, 1014, RGB(255,0,0)) ;<-- Change this value for different colour cursor
    StopDrawing()

EndIf

Cursor.ICONINFO
   Cursor\fIcon = #False
Cursor\xHotspot = 1024
Cursor\yHotspot = 1024
 Cursor\hbmMask = ImageID(#CursorMask)
Cursor\hbmColor = ImageID(#CursorImage) 
   ighBigCursor = CreateIconIndirect_(Cursor)

;### display cursor
SetSystemCursor_(ighBigCursor,#OCR_NORMAL)

;### Escape to Quit
Repeat : Until GetAsyncKeyState_(#VK_ESCAPE) & 1

;### Exit: Reset Cursor Pointers Set
SystemParametersInfo_(#SPI_SETCURSORS,0,#Null,#Null)
                Delay(1)

End
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Big Cross Mouse Cursor [Windows]

Post by RASHAD »

There is a good news for you mate :mrgreen:
The loop is the problem

Try the next

Code: Select all

Enumeration
#CursorMask
#CursorImage
EndEnumeration

CreateImage(#CursorMask,2048,2048,24)
CreateImage(#CursorImage,2048,2048,24)

If StartDrawing(ImageOutput(#CursorMask))

                 ;x1  ;y1  ;x2  ;y2
            Box(   0,    0, 2048, 2048, RGB(255,255,255))
         LineXY(1014,   10, 1014, 2038, RGB(0,0,0))
         LineXY(  10, 1014, 2038, 1014, RGB(0,0,0))
    StopDrawing()

EndIf

;### Cursor 1
If StartDrawing(ImageOutput(#CursorImage))

                ;x1   ;y1   ;x2   ;y2
            Box(   0,    0, 2048, 2048, RGB(0,0,0))
         LineXY(1014,   10, 1014, 2038, RGB(255,0,0)) ;<-- Change this value for different colour cursor
         LineXY(  10, 1014, 2038, 1014, RGB(255,0,0)) ;<-- Change this value for different colour cursor
    StopDrawing()

EndIf

Cursor.ICONINFO
   Cursor\fIcon = #False
Cursor\xHotspot = 1024
Cursor\yHotspot = 1024
 Cursor\hbmMask = ImageID(#CursorMask)
Cursor\hbmColor = ImageID(#CursorImage)
   ighBigCursor = CreateIconIndirect_(Cursor)

;### display cursor
SetSystemCursor_(ighBigCursor,#OCR_NORMAL)
end
Egypt my love
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: Big Cross Mouse Cursor [Windows]

Post by Josh »

RASHAD wrote:There is a good news for you mate :mrgreen:
The loop is the problem

Try the next

Code: Select all

.....
LineXY(1014,   10, 1014, 2038, RGB(0,0,0))
LineXY(  10, 1014, 2038, 1014, RGB(0,0,0))
.....
If you use 1024 instead of 1014, the hotspot will be shown correctly.

Any idea, that the shadow isn't shown for this cursor?

tested win7/64, PB 4.60
sorry for my bad english
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Big Cross Mouse Cursor [Windows]

Post by IdeasVacuum »

Hi Rashad

Yep, I actually fixed it 'accidentally' by adding a window front-end for choosing the cursor colour!

Josh, thanks for that note - had not noticed that the hotspot was out, at the time I was trying to ensure that the transparency always worked.

In my early days using computers, cross-hairs were all we had. I'm not sure how they fell out of favour so much that the OS does even have them as an option - they really are very handy at times!
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Big Cross Mouse Cursor [Windows]

Post by RASHAD »

Another trick

Ctrl + 1 Load Big Cursor
Ctrl + 2 Load Normal Cursor
Ctrl + 3 Exit

Tested with XP x86 Win 7 x64
Compile it as EXE file and you have the best application for the big cursor :)
And that is the beauty of Pure Basic (you can see your work as fast as you can)

Code: Select all

ExamineDesktops()
Width = DesktopWidth(0)
Height = DesktopHeight(0)

CreateImage(0, Width*2,Height*2)  
StartDrawing(ImageOutput(0))
  Box(0,0,Width*2,Height*2,#White)
  LineXY(0,Height,Width*2,Height,#Red)
  LineXY(Width,0,Width,Height*2,#Red)
  LineXY(Width-20,Height,Width+20,Height,#Yellow)
  LineXY(Width,Height-20,Width,Height+20,#Yellow)  
  ;Circle(Width,Height,10,#Red)
  ;Circle(Width,Height,7,#White)
StopDrawing()
;  
CreateImage(1,Width*2,Height*2)
StartDrawing(ImageOutput(1))
   Box(0,0,Width*2,Height*2,#Red)
   LineXY(Width-20,Height,Width+20,Height,#Yellow)
   LineXY(Width,Height-20,Width,Height+20,#Yellow)
StopDrawing()

iinf.ICONINFO
iinf\fIcon = #False
iinf\xHotspot = Width
iinf\yHotspot = Height
iinf\hbmMask = ImageID(0)
iinf\hbmColor = ImageID(1)

curHnd = CreateIconIndirect_(iinf)

temparrow    = CopyImage_(curHnd,#IMAGE_CURSOR,0,0,#LR_COPYFROMRESOURCE)
SetSystemCursor_(temparrow,32650)
 
temparrow    = CopyImage_(curHnd,#IMAGE_CURSOR,0,0,#LR_COPYFROMRESOURCE)
SetSystemCursor_(temparrow,32512)

Repeat
  Delay(1)
    If GetAsyncKeyState_(#VK_CONTROL) & $8000 = 32768 And GetAsyncKeyState_(#VK_1) & $8000 = 32768
       temparrow    = CopyImage_(curHnd,#IMAGE_CURSOR,0,0,#LR_COPYFROMRESOURCE)
       SetSystemCursor_(temparrow,#OCR_NORMAL)
    ElseIf GetAsyncKeyState_(#VK_CONTROL) & $8000 = 32768 And GetAsyncKeyState_(#VK_2) & $8000 = 32768
       SystemParametersInfo_(#SPI_SETCURSORS,0,#Null,#Null)
    ElseIf GetAsyncKeyState_(#VK_CONTROL) & $8000 = 32768 And GetAsyncKeyState_(#VK_3) & $8000 = 32768
       SystemParametersInfo_(#SPI_SETCURSORS,0,#Null,#Null)
       End
    EndIf
ForEver
Egypt my love
Post Reply