News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Mouse Cursor difficulties

Started by zemtex, February 03, 2011, 09:53:22 AM

Previous topic - Next topic

zemtex

I use ShowCursor(FALSE) to hide it and the reference count decreases respectively. It works very well, but I have an odd problem.

If I run my application by other means than double clicking the executable with my mouse, the cursor hides. But if I launch my program by double clicking it with my mouse the cursor never hides. There is nothing wrong with my mice, its a brand new mice in fact.

Why is that, could it be that the window loses focus in between the double click? I am catching and responding to both WM_SETCURSOR and WM_MOUSEMOVE but it doesnt solve the problem when I launch the app by double clicking the program icon.

If I select the program icon and press ENTER to launch it, the mouse cursor hides properly.  :(
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

qWord

code says more than thousand words  :wink:
Quoteinclude masm32rt.inc
.data?
    hInstance   HINSTANCE ?
.code
WndProc proto hWnd:HWND,uMgs:UINT,wParam:WPARAM,lParam:LPARAM

main proc
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
    mov hInstance,rv(GetModuleHandle,0)
    mov wc.hInstance,eax
    mov wc.cbSize,SIZEOF wc
    mov wc.style,CS_HREDRAW or CS_VREDRAW or CS_SAVEBITS
    mov wc.lpfnWndProc,OFFSET WndProc
    mov wc.cbClsExtra,0
    mov wc.cbWndExtra,0
    mov wc.hIcon,rv(LoadIcon,0,IDI_APPLICATION)
    mov wc.hIconSm,eax
   
    ;/* no cursor */
    mov wc.hCursor,0
   
    mov wc.lpszMenuName,0
    mov wc.hbrBackground,rv(GetStockObject,WHITE_BRUSH);
    mov wc.lpszClassName,chr$("Win32Wnd")
    invoke RegisterClassEx,ADDR wc
    mov esi,rv(CreateWindowEx,0,wc.lpszClassName,"Win32Wnd",WS_VISIBLE or WS_SYSMENU or WS_MAXIMIZEBOX or WS_MINIMIZEBOX or WS_SIZEBOX,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,0,0,hInstance,0)
    invoke UpdateWindow,esi
   
    .while 1
        invoke GetMessage,ADDR msg,0,0,0
        .break .if !eax || eax == -1
        invoke TranslateMessage,ADDR msg
        invoke DispatchMessage,ADDR msg     
    .endw

    invoke ExitProcess,0
main endp

WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    .if uMsg == WM_CLOSE
        invoke PostQuitMessage,0
    .elseif uMsg == WM_SETCURSOR
        invoke SetCursor,0
        mov eax,TRUE
        ret
    .else
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .endif
    xor eax,eax
    ret
WndProc endp
end main
FPU in a trice: SmplMath
It's that simple!

zemtex

Odd, I already have it like that. I have set wc.HCursor to null and i'm setting cursor in WM_SETCURSOR and returning TRUE as instructed by microsoft. I have also tried combining it with ShowCursor(FALSE)

Dont get me wrong, the thing works already, but it doesnt work if I launch my app using my mouse. Its an odd problem. If I run my app using my keyboard the cursor hides.  :dazzled:

Could this have anything to do with my other threaded message dummy window?
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

jj2007

You can solve your problem with a SetTimer call, but that doesn't solve the mystery...

donkey

Double-click is weird to begin with. You would assume that Windows simply logs the time and position of the first click then if another click occurs within a certain distance and time it treats it as a double click. In some cases this seems to be true but in others it isn't. I have tried to grasp the sequence of events that lead to a double click and have come up with very little. In my opinion, though I have no evidence to back it up, Windows captures the mouse after the first click and creates a waitable timer object, if the object expires there was no double click, if the button is pushed before expiration there was a double click. By capturing the mouse, Windows no long needs to worry about which window the mouse is over when the second click is received, simply that it is within the bounds specified in the system parameters. This could lead to some bizarre behavior if you're waiting for a mouse message between the two clicks, you will never get it because the mouse is captured by the system. Probably not much to do with your problem but one of my thought experiments, your problem has given me more data to refine my assumptions though, I'll let it bounce around in my head for a bit and maybe come up with an explanation.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

zemtex

I tried using a timer too, didnt work. It worked 30% of the time and failed the remaining 70%. I don't know why.

Ive set my window cursor to null before creating the window also. Some times when i run the program it shows a wait mouse icon, when the app shows a waiticon I know it will be hidden, it always hides when I see that, but when it shows a normal arrow icon, I know it will fail, it always does when it shows one.

I dont get it. The code is clean as toilet paper, I even feed the OS with hamburgers.

Anyways, it works more often when adding a timer, but it does not work all the times. In fact, this cant be the right way to go. There must be another more reliable way to do it. The question is what way to go when the ms docs says nothing about that.

I think the problem might be when switching from window to fullscreen mode. While this is happening it is possible the window loses focus because of the recent mouse click when I launched the application. I think this is the problem because when i press Enter to run it it works fine. It must be losing focus when i mouse click the program.

And so naturally I tried applying the focus back to the window by using SetForegroundWindow, no luck in doing that either.

My theory is that after it loses focus, ShowCursor(False) will fail because other apps or the desktop has the focus.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

jj2007

Why don't you send your source code? You can strip it to the essentials if you don't want to release your secrets ;-)

zemtex

Here is the relevant of winmain:


;**********************************************************************************************
;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_WINMAIN-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_WINMAIN-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_WINMAIN-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


ALIGN 16
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
LOCAL Color:DWORD
LOCAL ColChoice:DWORD
LOCAL D3D9_Interface:DWORD
LOCAL D3D9_Device:DWORD
LOCAL Quitting:DWORD
LOCAL D3D9_PresParam:D3DPRESENT_PARAMETERS

mov Quitting, 0


;**********************************************************************************************
;-_-_-winmain-_-_-_-_-_-_-_-_-_-_-_-_WINCLASS DATA-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


mov   wc.cbSize, SIZEOF WNDCLASSEX
mov   wc.style, CS_OWNDC
mov   wc.lpfnWndProc, OFFSET MainWndProc
mov   wc.cbClsExtra, NULL
mov   wc.cbWndExtra, NULL
push  hInstance
pop   wc.hInstance
mov   wc.hbrBackground, COLOR_WINDOW+1
mov   wc.lpszMenuName, NULL
mov   wc.lpszClassName, OFFSET ClassName
Invoke LoadIcon,NULL,IDI_APPLICATION
mov   wc.hIcon,eax
mov   wc.hIconSm,eax
;Invoke LoadCursor,NULL,IDC_ARROW
mov   wc.hCursor,NULL


;**********************************************************************************************
;-_-_-winmain-_-_-_-_-_-_-_-_-_-_-_-_REGISTER WINDOW-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


Invoke RegisterClassEx, addr wc


;**********************************************************************************************
;-_-_-winmain-_-_-_-_-_-_-_-_-_-_-_-_CREATE WINDOW-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


Invoke CreateWindowEx,WS_EX_TOPMOST,\
ADDR ClassName,\
ADDR AppName,\
WS_POPUP or WS_VISIBLE,\
CW_USEDEFAULT,\
CW_USEDEFAULT,\
WINDOW_WIDTH,\
WINDOW_HEIGHT,\
NULL,\
NULL,\
hInst,\
NULL
mov   hwnd,eax

IF DEBUG EQ 1
mov DebugHwnd, eax
ENDIF


;**********************************************************************************************
;-_-_-winmain-_-_-_-_-_-_-_-_-_-_-_-_UPDATE WINDOW-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


Invoke UpdateWindow, hwnd


;**********************************************************************************************
;-_-_-winmain-_-_-_-_-_-_-_-_-_-_-_-_CREATE DUMMY THREAD-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


Invoke CreateThread, NULL, 0, OFFSET DummyWindowThread, 0, 0, NULL
mov DumTrHandle, eax


;**********************************************************************************************
;-_-_-winmain-_-_-_-_-_-_-_-_-_-_-_-_CREATE DX9 INTERFACE-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


Invoke D3D9_Create_Interface
mov D3D9_Interface, eax


;**********************************************************************************************
;-_-_-winmain-_-_-_-_-_-_-_-_-_-_-_-_SET DX PARAMETERS-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


IF DEBUG EQ 1
Invoke D3D9_Set_Present_Parameters, D3D9_Interface, addr D3D9_PresParam, WINDOW_WIDTH, WINDOW_HEIGHT, hwnd, TRUE
ELSE
Invoke D3D9_Set_Present_Parameters, D3D9_Interface, addr D3D9_PresParam, WINDOW_WIDTH, WINDOW_HEIGHT, hwnd, FALSE
ENDIF


;**********************************************************************************************
;-_-_-winmain-_-_-_-_-_-_-_-_-_-_-_-_CREATE DX9 DEVICE-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


; Create Direct3D9 Device
Invoke D3D9_Create_Device, D3D9_Interface, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,\
   addr D3D9_PresParam, addr D3D9_Device




Here is the window callback procedure:



;**********************************************************************************************
;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_WNDPROC-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_WNDPROC-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_WNDPROC-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


ALIGN 16
MainWndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM


;**********************************************************************************************
;-_-_-winproc-_-_-_-_-_-_-_-_-_-_-_-_WM_CREATE-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


CREATE

Invoke SetTimer, hWnd, 1, 5000, NULL


;**********************************************************************************************
;-_-_-winproc-_-_-_-_-_-_-_-_-_-_-_-_WM_TIMER-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


TIMER

Invoke SetForegroundWindow, hWnd
Invoke KillTimer, hWnd, 1
Invoke ShowCursor, 0


;**********************************************************************************************
;-_-_-winproc-_-_-_-_-_-_-_-_-_-_-_-_WM_CLOSE-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


CLOSE

Invoke DestroyWindow, hWnd


;**********************************************************************************************
;-_-_-winproc-_-_-_-_-_-_-_-_-_-_-_-_WM_MOUSEMOVE-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


MOUSEMOVE

; Trap mouse movement to avvoid windows resetting cursor


;**********************************************************************************************
;-_-_-winproc-_-_-_-_-_-_-_-_-_-_-_-_WM_SETCURSOR-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


SETCURSOR

Invoke SetCursor, NULL
mov eax, TRUE
ret


;**********************************************************************************************
;-_-_-winproc-_-_-_-_-_-_-_-_-_-_-_-_WM_DESTROY-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


DESTROY

Invoke ShowCursor, 1
Invoke PostQuitMessage, NULL



;**********************************************************************************************
;-_-_-winproc-_-_-_-_-_-_-_-_-_-_-_-_DEFAULT WINPROC-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


.ELSE
DEFWNDPROC


;**********************************************************************************************
;-_-_-winproc-_-_-_-_-_-_-_-_-_-_-_-_RET ZERO JUMP HERE-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
;**********************************************************************************************


.ENDIF

RETNULL

MainWndProc endp
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

Tedd

Here's how I usually do it; no timer, no setting a null cursor or other fiddling, and I've never noticed any problems..


WinMain {
  RegisterClass...
  CreateWindow...
  set up D3D, change video mode, render state, etc.
  ShowWindow...
  ShowCursor(false)
  message-loop, exit on quit
  ShowCursor(true)
  clean up...
  return
}
No snowflake in an avalanche feels responsible.

jj2007

qWord's recipe works perfectly for me:
Quote   SWITCH uMsg
   CASE WM_SETCURSOR
      deb 1, "ShowCursor", wParam, lParam   ; MasmBasic macro
      invoke ShowCursor, 0
      return 1