Author Topic: How to change the mouse cursor inside a program  (Read 4094 times)

0 Members and 1 Guest are viewing this topic.

Offline random1

  • Newbie
  • Posts: 86
    • View Profile
How to change the mouse cursor inside a program
« on: December 25, 2020, 02:36:53 am »
Hi all

I am making a simple shooter game and want to use a custom mouse pointer, "gunsight", then change
back to the to the windows default when the program is exited.  I tried searching but got nothing in the
results. 

Thanks in advance.

R1

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: How to change the mouse cursor inside a program
« Reply #1 on: December 25, 2020, 02:48:46 am »
Wouldn't you just use_MOUSEHIDE to hide the cursor, and then draw what you want on the screen where it's normally at?

_MOUSEHIDE
CIRCLE (_MOUSEX, _MOUSEY), 10,_RGB(255,0,0)
« Last Edit: December 25, 2020, 02:50:11 am by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: How to change the mouse cursor inside a program
« Reply #2 on: December 25, 2020, 04:04:04 am »
.. then I personally would add...
CIRCLE(_MOUSEX,_MOUSEY), 1, _RGB(255,0,0)  (maybe 2 instead of 1 for the centre of the sight)
Logic is the beginning of wisdom.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: How to change the mouse cursor inside a program
« Reply #3 on: December 25, 2020, 08:21:55 am »
Try:
        _MOUSESHOW "LINK" will display an upward pointing hand cursor used to denote hypertext
        _MOUSESHOW "TEXT" will display the I cursor often used in text entry areas
        _MOUSESHOW "CROSSHAIR" will display a crosshair cursor
        _MOUSESHOW "VERTICAL" will display vertical arrow cursor for movement
        _MOUSESHOW "HORIZONTAL" will display horizontal arrow cursor for movement
        _MOUSESHOW "TOPLEFT_BOTTOMRIGHT" will display bottom diagonal arrow cursor for movement
        _MOUSESHOW "TOPRIGHT_BOTTOMLEFT" will display bottom diagonal arrow cursor for movement
        _MOUSESHOW "DEFAULT" can be used after a mouse cursor statement above was previously used.

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: How to change the mouse cursor inside a program
« Reply #4 on: December 25, 2020, 03:42:47 pm »
This snippet is crude but seems to work.

Press LMB to change sights.

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(640, 480, 32)
  2.  
  3.  
  4. red = _RGB(255, 0, 0)
  5.  
  6.     CLS
  7.  
  8.     DO WHILE _MOUSEINPUT: mX = _MOUSEX: mY = _MOUSEY: mB = _MOUSEBUTTON(1): LOOP
  9.  
  10.     CIRCLE (mX, mY), 20, red
  11.     IF mB = 0 THEN
  12.         CIRCLE (mX, mY), 2, red
  13.     ELSE
  14.         LINE (mX, mY - 5)-STEP(0, 10), red
  15.         LINE (mX - 5, mY)-STEP(10, 0), red
  16.     END IF
  17.  
  18.     _DISPLAY
  19.     _LIMIT 60
  20.  

I am sure that anyone here can produce a far more superior sample of this code.
Logic is the beginning of wisdom.

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: How to change the mouse cursor inside a program
« Reply #5 on: December 25, 2020, 06:46:14 pm »
Utilizing mostly Steve's quality tooling; since the wheel has already been invented, I present a target reticle.

If you try to go full auto your barrel will seize. ;)

Code: QB64: [Select]
  1. TYPE v2
  2.     x AS INTEGER
  3.     y AS INTEGER
  4.  
  5. DIM hole(10000) AS v2
  6.  
  7.  
  8. SCREEN _NEWIMAGE(600, 600, 32)
  9.  
  10. 'define reticle image
  11. ret& = _NEWIMAGE(50, 50, 32)
  12. _DEST ret&
  13. CIRCLE (24, 24), 20, &HFFFF0000
  14. LINE (0, 24)-(49, 24), &HFFFF0000
  15. LINE (24, 0)-(24, 49), &HFFFF0000
  16.  
  17. shoot = 0
  18.     ms = MBS
  19.     IF ms AND 1 THEN
  20.         IF ms AND 64 THEN _CONTINUE
  21.         hole(shoot).x = _MOUSEX
  22.         hole(shoot).y = _MOUSEY
  23.         shoot = shoot + 1
  24.     END IF
  25.     CLS
  26.     FOR x = 0 TO shoot
  27.         FCirc hole(x).x, hole(x).y, 3, &HFFFF0000
  28.     NEXT x
  29.     _PUTIMAGE (_MOUSEX - 24, _MOUSEY - 24), ret&
  30.     _DISPLAY
  31.     _LIMIT 50
  32.  
  33.  
  34. FUNCTION MBS% 'Mouse Button Status  by Steve McNeill
  35.     STATIC StartTimer AS _FLOAT
  36.     STATIC ButtonDown AS INTEGER
  37.     'STATIC ClickCount AS INTEGER
  38.     CONST ClickLimit## = .2 'Less than 1/4 of a second to down, up a key to count as a CLICK.
  39.     '                          Down longer counts as a HOLD event.
  40.     SHARED Mouse_StartX, Mouse_StartY, Mouse_EndX, Mouse_EndY
  41.     WHILE _MOUSEINPUT 'Remark out this block, if mouse main input/clear is going to be handled manually in main program.
  42.         SELECT CASE SGN(_MOUSEWHEEL)
  43.             CASE 1: MBS = MBS OR 512
  44.             CASE -1: MBS = MBS OR 1024
  45.         END SELECT
  46.     WEND
  47.  
  48.     IF _MOUSEBUTTON(1) THEN MBS = MBS OR 1
  49.     IF _MOUSEBUTTON(2) THEN MBS = MBS OR 2
  50.     IF _MOUSEBUTTON(3) THEN MBS = MBS OR 4
  51.  
  52.     IF StartTimer = 0 THEN
  53.         IF _MOUSEBUTTON(1) THEN 'If a button is pressed, start the timer to see what it does (click or hold)
  54.             ButtonDown = 1: StartTimer = TIMER(0.01)
  55.             Mouse_StartX = _MOUSEX: Mouse_StartY = _MOUSEY
  56.         ELSEIF _MOUSEBUTTON(2) THEN
  57.             ButtonDown = 2: StartTimer = TIMER(0.01)
  58.             Mouse_StartX = _MOUSEX: Mouse_StartY = _MOUSEY
  59.         ELSEIF _MOUSEBUTTON(3) THEN
  60.             ButtonDown = 3: StartTimer = TIMER(0.01)
  61.             Mouse_StartX = _MOUSEX: Mouse_StartY = _MOUSEY
  62.         END IF
  63.     ELSE
  64.         BD = ButtonDown MOD 3
  65.         IF BD = 0 THEN BD = 3
  66.         IF TIMER(0.01) - StartTimer <= ClickLimit THEN 'Button was down, then up, within time limit.  It's a click
  67.             IF _MOUSEBUTTON(BD) = 0 THEN MBS = 4 * 2 ^ ButtonDown: ButtonDown = 0: StartTimer = 0
  68.         ELSE
  69.             IF _MOUSEBUTTON(BD) = 0 THEN 'hold event has now ended
  70.                 MBS = 0: ButtonDown = 0: StartTimer = 0
  71.                 Mouse_EndX = _MOUSEX: Mouse_EndY = _MOUSEY
  72.             ELSE 'We've now started the hold event
  73.                 MBS = MBS OR 32 * 2 ^ ButtonDown
  74.             END IF
  75.         END IF
  76.     END IF
  77.  
  78. SUB FCirc (CX AS INTEGER, CY AS INTEGER, RR AS INTEGER, C AS _UNSIGNED LONG)
  79.  
  80.     'Steve's circle draw
  81.     DIM R AS INTEGER, RError AS INTEGER
  82.     DIM X AS INTEGER, Y AS INTEGER
  83.     R = ABS(RR)
  84.     RError = -R
  85.     X = R
  86.     Y = 0
  87.     IF R = 0 THEN PSET (CX, CY), C: EXIT SUB
  88.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  89.     WHILE X > Y
  90.         RError = RError + Y * 2 + 1
  91.         IF RError >= 0 THEN
  92.             IF X <> Y + 1 THEN
  93.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  94.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  95.             END IF
  96.             X = X - 1
  97.             RError = RError - X * 2
  98.         END IF
  99.         Y = Y + 1
  100.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  101.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  102.     WEND
  103.  
  104. END SUB 'FCirc
  105.  
  106.  

Offline random1

  • Newbie
  • Posts: 86
    • View Profile
Re: How to change the mouse cursor inside a program
« Reply #6 on: December 26, 2020, 11:24:11 pm »
Hi all

Thanks for the replies but what I would really like to do is change my default cursor.  I attached a pic
of the game  that shows the stages of aiming and shooting a bug.  The _MOUSESHOW "CROSSHAIR"  comes close to what I want but kind of falls short graphic wise.  I thought there might be a simple way
to change the default cursor inside a program which would make things very simple.  My graphic does
not show up until the fire button is pressed.  What I want to achieve is the effect of looking through
a scope to zero in on the bugs.  Anyway, maybe the attached pic will help.

R1       




Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: How to change the mouse cursor inside a program
« Reply #7 on: December 27, 2020, 03:54:06 am »
I don't know if this helps... But I use an ancient game "Delta Force: Land Warrior". The weapons that use a "scope" can activate the scope using the Right Mouse Button then fire with the Left Mouse Button. Pressing the RMB again hides the scope.

Perhaps something similar. When you want to shoot, press the RMB to change your mouse pointer into a mouse pointer with sights. Shoot with LMB. Press RMB to restore to a normal mouse pointer.

Just a thought.  Is that closer to what you need?. If so, then its just a simple task, of producing a 'sited pointer' sprite.
Logic is the beginning of wisdom.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: How to change the mouse cursor inside a program
« Reply #8 on: December 27, 2020, 04:17:35 am »
Hi. You say that the cursor does not change until you press the fire button. This means that the error is in the logic of the mouse display (in your program). I'm adding a sample like to do this because I don't have a sprite image of a beetle, a rectangle is used instead. The rectangle (representing the beetle) measures 50 x 50 pixels. Its position is determined by the upper left corner:

Example 1 - using MOUSESHOW
Code: QB64: [Select]
  1. 'example 1 using _MOUSESHOW
  2. bug = _NEWIMAGE(50, 50, 32)
  3. _DEST bug
  4. LINE -(49, 49), _RGB32(127, 200, 99), BF
  5. SCREEN _NEWIMAGE(800, 600, 32)
  6.  
  7.     _MOUSESHOW "Default"
  8.     WEND
  9.     MX = _MOUSEX
  10.     MY = _MOUSEY
  11.     LB = _MOUSEBUTTON(1)
  12.  
  13.     'placing bug middle to screen
  14.     _PUTIMAGE (400 - 25, 300 - 25), bug
  15.  
  16.     IF MX > 400 - 25 AND MX < 400 + 25 THEN '     if mouseX is on bug X location
  17.         IF MY > 300 - 25 AND MY < 300 + 25 THEN ' if mouseY is on bug Y location
  18.             _MOUSESHOW "crosshair"
  19.         END IF
  20.     END IF
  21.  
  22.  

Example 2 - use image as mouse cursor:

Code: QB64: [Select]
  1. 'example 2 using image
  2.  
  3. CurrentScreen = _DEST
  4.  
  5. bug = _NEWIMAGE(50, 50, 32) '                create virtual image contains "bug" - quad
  6. _DEST bug
  7. LINE -(49, 49), _RGB32(127, 200, 99), BF
  8.  
  9.  
  10.  
  11. Cursor = _NEWIMAGE(50, 50, 32) '            create virtual image contains your cursor
  12. _DEST Cursor
  13. CIRCLE (25, 25), 22, _RGB32(255, 255, 255)
  14. LINE (25, 0)-(25, 50), _RGB32(255, 255, 255)
  15. LINE (0, 25)-(50, 25), _RGB32(255, 255, 255)
  16.  
  17. _DEST CurrentScreen
  18. SCREEN _NEWIMAGE(800, 600, 32)
  19. 'placing bug middle to screen
  20. _PUTIMAGE (400 - 25, 300 - 25), bug
  21.  
  22. 'save current screen content
  23. Content = _COPYIMAGE(0)
  24.  
  25.  
  26.  
  27.  
  28.     _PUTIMAGE , Content
  29.  
  30.     WEND
  31.     MX = _MOUSEX
  32.     MY = _MOUSEY
  33.     LB = _MOUSEBUTTON(1)
  34.     ShowCursor = 1
  35.     IF MX > 400 AND MX < 400 + 25 THEN '     if mouseX is on bug X location
  36.         IF MY > 300 AND MY < 300 + 25 THEN ' if mouseY is on bug Y location
  37.             _PUTIMAGE (MX - 25, MY - 25), Cursor
  38.             ShowCursor = 0 '                 comment this and show who real mouse cursor is
  39.         END IF
  40.     END IF
  41.     IF ShowCursor THEN _MOUSESHOW "Default" ELSE _MOUSEHIDE
  42.     _DISPLAY
  43.     _LIMIT 30
  44.  
  45.  

Offline random1

  • Newbie
  • Posts: 86
    • View Profile
Re: How to change the mouse cursor inside a program
« Reply #9 on: December 27, 2020, 05:16:47 am »
Petr

My mistake, when the LMB is pressed the sight graphic is drawn centered at the tip of the mouse pointer.
A custom cursor would make it as simple as pie.   I have used Pcopy in a loop to move an object or
graphic around which is maybe what I will do as a quick fix. 

_MOUSESHOW "CROSSHAIR" is very close to what I need, if only there was a _MOUSESHOW "Gunscope" option. 

Thanks to everyone.

R1

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: How to change the mouse cursor inside a program
« Reply #10 on: December 27, 2020, 07:13:20 pm »
Here's something that updates the reticle idea with some scope magnification. I'll leave any gory animations to more capable hands than mine.

Note: game.png is the picture that random1 posted earlier, or substitute one of your own.

Edit: With a few tweaks I added a mousewheel scope power zoom.

Code: QB64: [Select]
  1. TYPE v2
  2.     x AS INTEGER
  3.     y AS INTEGER
  4.  
  5. DIM hole(10000) AS v2
  6. DIM SHARED msk&
  7. DIM SHARED magfac
  8.  
  9. game& = _LOADIMAGE("game.png", 32)
  10. SCREEN _NEWIMAGE(_WIDTH(game&), _HEIGHT(game&), 32)
  11.  
  12. ret& = _NEWIMAGE(150, 150, 32)
  13. _DEST ret&
  14. CIRCLE (74, 74), 74, &HFFFF0000
  15. CIRCLE (74, 74), 73, &HFFFF0000
  16. CIRCLE (74, 74), 72, &HFFFF0000
  17. LINE (0, 74)-(149, 74), &HFFFF0000
  18. LINE (55, 75)-(95, 75), &HFFFF0000
  19. LINE (75, 55)-(75, 95), &HFFFF0000
  20. LINE (74, 0)-(74, 149), &HFFFF0000
  21.  
  22. msk& = _NEWIMAGE(150, 150, 32)
  23. _DEST msk&
  24. COLOR , _RGB32(255, 0, 255)
  25. FCirc 74, 74, 74, _RGB32(0, 0, 0)
  26. _PUTIMAGE , ret&
  27.  
  28. shoot = 0
  29. magfac = 3
  30.     ms = MBS
  31.     IF ms AND 1 THEN
  32.         IF ms AND 64 THEN _CONTINUE
  33.         hole(shoot).x = _MOUSEX
  34.         hole(shoot).y = _MOUSEY
  35.         shoot = shoot + 1
  36.     END IF
  37.     IF ms AND 512 THEN magfac = magfac - 1 - (magfac = 1)
  38.     IF ms AND 1024 THEN magfac = magfac + 1
  39.  
  40.     gamec& = _COPYIMAGE(game&)
  41.     _PUTIMAGE , gamec&
  42.     _FREEIMAGE gamec&
  43.     FOR x = 0 TO shoot
  44.         FCirc hole(x).x, hole(x).y, 3, &HFFFF0000
  45.     NEXT x
  46.     Magnify
  47.     _DISPLAY
  48.     _LIMIT 50
  49.  
  50.  
  51. SUB Magnify
  52.  
  53.     cpy& = _COPYIMAGE(game&, 32)
  54.     mag& = _NEWIMAGE(150, 150, 32)
  55.     _PUTIMAGE (0, 0)-(149, 149), cpy&, mag&, (_MOUSEX - (75 / magfac), _MOUSEY - (75 / magfac))-(_MOUSEX + (75 / magfac), _MOUSEY + (75 / magfac)), _SMOOTH
  56.     _DEST mag&
  57.     _CLEARCOLOR _RGB32(0, 0, 0), msk&
  58.     _PUTIMAGE , msk&, mag&
  59.     _CLEARCOLOR _RGB32(255, 0, 255), mag&
  60.     _PUTIMAGE (_MOUSEX - 74, _MOUSEY - 74), mag&, 0
  61.     _FREEIMAGE cpy&
  62.     _FREEIMAGE mag&
  63.  
  64. END SUB 'Magnify
  65.  
  66.  
  67. FUNCTION MBS% 'Mouse Button Status  by Steve McNeill
  68.     STATIC StartTimer AS _FLOAT
  69.     STATIC ButtonDown AS INTEGER
  70.     'STATIC ClickCount AS INTEGER
  71.     CONST ClickLimit## = .2 'Less than 1/4 of a second to down, up a key to count as a CLICK.
  72.     '                          Down longer counts as a HOLD event.
  73.     SHARED Mouse_StartX, Mouse_StartY, Mouse_EndX, Mouse_EndY
  74.     WHILE _MOUSEINPUT 'Remark out this block, if mouse main input/clear is going to be handled manually in main program.
  75.         SELECT CASE SGN(_MOUSEWHEEL)
  76.             CASE 1: MBS = MBS OR 512
  77.             CASE -1: MBS = MBS OR 1024
  78.         END SELECT
  79.     WEND
  80.  
  81.     IF _MOUSEBUTTON(1) THEN MBS = MBS OR 1
  82.     IF _MOUSEBUTTON(2) THEN MBS = MBS OR 2
  83.     IF _MOUSEBUTTON(3) THEN MBS = MBS OR 4
  84.  
  85.     IF StartTimer = 0 THEN
  86.         IF _MOUSEBUTTON(1) THEN 'If a button is pressed, start the timer to see what it does (click or hold)
  87.             ButtonDown = 1: StartTimer = TIMER(0.01)
  88.             Mouse_StartX = _MOUSEX: Mouse_StartY = _MOUSEY
  89.         ELSEIF _MOUSEBUTTON(2) THEN
  90.             ButtonDown = 2: StartTimer = TIMER(0.01)
  91.             Mouse_StartX = _MOUSEX: Mouse_StartY = _MOUSEY
  92.         ELSEIF _MOUSEBUTTON(3) THEN
  93.             ButtonDown = 3: StartTimer = TIMER(0.01)
  94.             Mouse_StartX = _MOUSEX: Mouse_StartY = _MOUSEY
  95.         END IF
  96.     ELSE
  97.         BD = ButtonDown MOD 3
  98.         IF BD = 0 THEN BD = 3
  99.         IF TIMER(0.01) - StartTimer <= ClickLimit THEN 'Button was down, then up, within time limit.  It's a click
  100.             IF _MOUSEBUTTON(BD) = 0 THEN MBS = 4 * 2 ^ ButtonDown: ButtonDown = 0: StartTimer = 0
  101.         ELSE
  102.             IF _MOUSEBUTTON(BD) = 0 THEN 'hold event has now ended
  103.                 MBS = 0: ButtonDown = 0: StartTimer = 0
  104.                 Mouse_EndX = _MOUSEX: Mouse_EndY = _MOUSEY
  105.             ELSE 'We've now started the hold event
  106.                 MBS = MBS OR 32 * 2 ^ ButtonDown
  107.             END IF
  108.         END IF
  109.     END IF
  110.  
  111. SUB FCirc (CX AS INTEGER, CY AS INTEGER, RR AS INTEGER, C AS _UNSIGNED LONG)
  112.  
  113.     'Steve's circle draw
  114.     DIM R AS INTEGER, RError AS INTEGER
  115.     DIM X AS INTEGER, Y AS INTEGER
  116.     R = ABS(RR)
  117.     RError = -R
  118.     X = R
  119.     Y = 0
  120.     IF R = 0 THEN PSET (CX, CY), C: EXIT SUB
  121.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  122.     WHILE X > Y
  123.         RError = RError + Y * 2 + 1
  124.         IF RError >= 0 THEN
  125.             IF X <> Y + 1 THEN
  126.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  127.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  128.             END IF
  129.             X = X - 1
  130.             RError = RError - X * 2
  131.         END IF
  132.         Y = Y + 1
  133.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  134.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  135.     WEND
  136.  
  137. END SUB 'FCirc
  138.  
« Last Edit: December 27, 2020, 07:42:27 pm by OldMoses »

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
Re: How to change the mouse cursor inside a program
« Reply #11 on: December 27, 2020, 08:39:10 pm »
you may be able to use a custom cursor using Windows API, perhaps  SpriggsySpriggs could help
here's example code in Pete's favorite language https://www.freebasic.net/forum/viewtopic.php?p=189138#p189138
perhaps someone could adapt that to QB64