How to change cursor on WM_KEYDOWN and WM_LBUTTONDOWN ?

Started by CoR, March 22, 2007, 01:53:04 PM

Previous topic - Next topic

CoR

I want to change cursor to hand when ctrl is pressed. And to change that cursor to fist if left mouse is pressed.
CTRL = hand
CTRL + LMouseDown = grabbing hand

I have this code but Ctrl pars doesn't not work flawlessly  :(


@@:
cmp uMsg,WM_KEYDOWN
jne @F
   
    cmp wParam,VK_CONTROL
        jne NotPressedCtrlIF

invoke SetClassLong, hWnd,GCL_HCURSOR,hcurGrab
invoke SetCursor, hcurGrab
mov eax,TRUE
ret

NotPressedCtrlIF:
xor eax,eax
ret



@@:
cmp uMsg,WM_LBUTTONDOWN
jne @F



@@:
cmp uMsg,WM_KEYUP
jne @F
;jmp t2
;ClocC db "press",0
;ClotC db "Cursor ctrl",0
;t2:
;  push MB_YESNO
;  push OFFSET ClocC ; caption
;  push OFFSET ClotC ;txt
;  push hWnd
;call MessageBox


      cmp wParam,VK_CONTROL
      jne NotDePressedCtrlIF
       mov CtrlIF,0
 
  invoke SetClassLong, hWnd,GCL_HCURSOR,IDC_ARROW
  invoke LoadCursor,0,IDC_ARROW
invoke SetCursor, eax
  mov eax,1
  ret
NotDePressedCtrlIF:
xor eax,eax
ret


@@:
cmp uMsg,WM_SETCURSOR
jne @F

;     cmp wParam,VK_CONTROL can not test for ctrl in wm sercursor!
;     jne NotPressedCtrl
;     invoke SetCursor, hcurGrab
  ;    mov eax,1
   ;    ret
;NotPressedCtrl:

mov eax,TRUE
ret

This code changes cursor on ctrl down and crtl up, but when mouse is over window for the first time it's hourglass. Not normal arrow! And if cursor changes to 'resize arrows' it stays like that. It does not change on arrow.

Second question:
How to check for two or more events like CtrlDown + LmouseDown (+key "M" down) + mouse move?

TNick

This is from win32.hlp, WNDCLASS topic:

QuotehCursor

Identifies the class cursor. This member must be a handle of a cursor resource. If this member is NULL, an application must explicitly set the cursor shape whenever the mouse moves into the application's window.

So, the solution may be:
- register your class with null there
- in your WM_MOUSEMOVE
. IF CursorType==CT_Standard
INVOKE SetCursor, hCStd
.ELSEIF CursorType==CT_Grabing
  INVOKE SetCursor, hCStd
.ELSEIF ...

- when a event that needs a cursor  change arrives:
mov CursorType, CT_...
INVOKE SetCursor, hCS...

Where CT_ are user defined constants and hCS.. cursor handles.

Nick

PBrennick

CoR,


      invoke  GetAsyncKeyState, VK_CONTROL
      rol     eax, 16
      cmp     ax, 1111111111111111b


The above code will give you flawless results in terms of the CTRL key. If the result of the compare is TRUE, then the CTRL key was (is) pressed. Once you know that test for the mouse action and you will have it.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

Tedd

Quote from: PBrennick on March 22, 2007, 08:26:39 PM

      invoke  GetAsyncKeyState, VK_CONTROL
      rol     eax, 16
      cmp     ax, 1111111111111111b


That should really be..

      invoke  GetAsyncKeyState, VK_CONTROL
      test eax,80000000h

      ;(..then jz if pressed, or jnz if not - depending on preference)

Officially it's only the top bit that's set (in reality the whole top row are set as this function was carried over from 16-bit - where the 'top' bit was bit 15 - so it seems they jsut set the whole lot to get aorund it.)
No snowflake in an avalanche feels responsible.

CoR

Huh, that's what  I didn't understand...
QuoteIf this member is NULL, an application must explicitly set the cursor shape whenever the mouse moves into the application's window.
But the member is not a NULL  :( Or I am doing something horribly wrong! I filled hCursor with preloaded cursor handle. I even tried to load cursor before passing it with SetClassLong but it didn't work. It looks much easier to let window handle cursor management instead me handling WM_MOUSEMOVE.
There's no easy way out for me  :bg Thanks Nick.

So if I want to check more WM_messages at once... I can not do it!
But there is way around it! I wanted to check for WM_KEYDOWN (ctrl), VK_LBUTTON, WM_MOUSEMOVE at once. And that will result in moving window or moving window background (like grabbing hand that moves big pdf file)
The 'real way' to do it is:
case WM_MOUSEMOVE
if. wParam=MK_CONTROL AND wParam=MK_LBUTTON
GetAsyncKeyState, VK_my_designated_key
code to move window bckgrnd,
SetCursor, etc...
Thanks PBrennick.


I have gained knowledge in Asm and WinApi just enough to be dangerous to myself and people around me  :bdg

CoR

Ok, mystery continues  :bg Here is code that WORKS exactly what I had in mind  :bdg

@@:
cmp uMsg,WM_KEYDOWN
jne @F
   
    cmp wParam,VK_CONTROL
        jne NotPressedCtrlIF
invoke SetClassLong, hWnd,GCL_HCURSOR,hcurGrab ; hcurGrab is preloaded cursor handle
invoke SetCursor, hcurGrab
xor eax,eax
ret
NotPressedCtrlIF:
xor eax,eax
ret
@@:
cmp uMsg,WM_KEYUP
jne @F
      cmp wParam,VK_CONTROL
      jne NotDePressedCtrlIF
       mov CtrlIF,0

invoke SetClassLong, hWnd,GCL_HCURSOR,hcurArrow
invoke SetCursor, hcurArrow
xor eax,eax
ret
NotDePressedCtrlIF:
xor eax,eax
ret

;@@:
;cmp uMsg,WM_SETCURSOR
; jne @F
;mov eax,TRUE
;ret

Basically I REMOVED WM_SETCORCOR checking and everything works flawlessly!!!!!
No more hourglass or resize arrows! No more flickering cursor over window (thought it flickers over other windows in my multiwindow app, but it will be taken care of) It responds correctly if CTRL key is depressed...

Life is beautiful! Thanks guys!   :dance:

CoR

And here's final version if it can help anyone or if someone wants to improve the code.

@@:;____________;return 0
cmp uMsg,WM_KEYDOWN
jne @F
   
    cmp wParam,VK_CONTROL
        jne NotPressedCtrlIF

;test for repeated key strokes
    and lParam,1073741824 ;40000000h ;30th bit ;1000000000000000000000000000000
    jnz NotPressedCtrlIF
invoke SetClassLong, hWnd,GCL_HCURSOR,hcurGrab
invoke SetCursor, hcurGrab
xor eax,eax
ret

NotPressedCtrlIF:
xor eax,eax
ret
;-----end wm_keydown-----



@@:;______________;return 0
cmp uMsg,WM_KEYUP
jne @F

      cmp wParam,VK_CONTROL
      jne NotDePressedCtrlIF
     
  invoke SetClassLong, hWnd,GCL_HCURSOR,hcurArrow
  invoke SetCursor, hcurArrow
  xor eax,eax
  ret
NotDePressedCtrlIF:
xor eax,eax
ret
;-----end wm_keyup-----



@@:;__________________no return value!!!!!
cmp uMsg,WM_MOUSEMOVE
jne @f

test wParam,MK_CONTROL
jz NotCtr
test wParam,MK_LBUTTON
jz EndMouseMove

;code to move window somehow using lParam and MoveWindow or SetWindowPos
;is it possible without global variables?

jmp EndMouseMove
NotCtr:
invoke SetClassLong, hWnd,GCL_HCURSOR,hcurArrow
invoke SetCursor, hcurArrow

EndMouseMove:

;-----end wm_mousemove-----



@@:;______________________return 0
cmp uMsg,WM_LBUTTONDOWN
jne @F

  test wParam,MK_CONTROL
  jz NotCtrlP
invoke SetClassLong, hWnd,GCL_HCURSOR,hcurGrabbed
invoke SetCursor, hcurGrabbed
        xor eax,eax
        ret
NotCtrlP:
xor eax,eax
ret
;--------end wm_lbutondown-------------------



@@:;__________________return 0
cmp uMsg,WM_LBUTTONUP
jne @F
test wParam,MK_CONTROL  ;8h = 1000b
jz NotCtrl
invoke SetClassLong, hWnd,GCL_HCURSOR,hcurGrab
invoke SetCursor, hcurGrab
        xor eax,eax
        ret
NotCtrl:
invoke SetClassLong, hWnd,GCL_HCURSOR,hcurArrow
invoke SetCursor, hcurArrow
        xor eax,eax
        ret
;---------end wm_lbuttonup---------------

I would be nice if anyone could tell me why this code does not work if I check for WM_SETCURSOR and return either  0 or 1 or unchanged eax? Is there better way for doing this?