News:

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

WM_MOUSEMOVE message in static control?

Started by RHL, April 17, 2012, 01:14:55 AM

Previous topic - Next topic

dedndave

ok
you are not getting WM_CREATE messages, then
that's because the window isn't subclassed yet when that message is sent   :P

maybe put it in the parent window WndProc WM_CREATE
be sure to use hStatic instead of hWnd

dedndave

            invoke  CreateWindowEx,NULL,addr myclass,addr sname,
                    WS_VISIBLE or WS_CHILD,0h,0h,50h,50h,hWnd,NULL,hInstance,NULL
            mov     hstatic,eax ; save handle static control
            mov     LEAVEAREA.cbSize,sizeof(TRACKMOUSEEVENT)
            mov     LEAVEAREA.dwFlags,TME_HOVER or TME_LEAVE
            mov     LEAVEAREA.dwHoverTime,1000
            mov     LEAVEAREA.hwndTrack,eax
            invoke  TrackMouseEvent,addr LEAVEAREA

RHL

continues without re-showing the static control :|
also, if created, the static control without  SS_NOTIFY, do not even control hides
my code:


myWNDPROC proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
;LOCAL LEAVEAREA:TRACKMOUSEEVENT

        .if uMsg==WM_MOUSEMOVE
            invoke  ShowWindow,hWnd,SW_HIDE

        .elseif uMsg==WM_MOUSELEAVE
            invoke  ShowWindow,hWnd,SW_SHOW

        .endif
        invoke  CallWindowProc,mysubclass,hWnd,uMsg,wParam,lParam
        ret
myWNDPROC endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL LEAVEAREA:TRACKMOUSEEVENT

.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
invoke SetWindowLong,mysubclass,GWL_WNDPROC,myWNDPROC
.ELSEIF uMsg==WM_CREATE
invoke CreateWindowEx,NULL,addr myclass,addr sname,WS_VISIBLE or WS_CHILD or SS_NOTIFY, \
0h,0h,50h,50h,hWnd,NULL,hInstance,NULL

mov hstatic,eax
mov     LEAVEAREA.cbSize,sizeof(TRACKMOUSEEVENT)
mov     LEAVEAREA.dwFlags,TME_HOVER or TME_LEAVE
mov     LEAVEAREA.dwHoverTime,1000
mov     LEAVEAREA.hwndTrack,eax
invoke  TrackMouseEvent,addr LEAVEAREA

invoke SetWindowLong,hstatic,GWL_WNDPROC,myWNDPROC
mov mysubclass,eax


.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF

xor eax,eax
ret
WndProc endp


end start

dedndave

QuoteWM_MOUSELEAVE
The mouse left the client area of the window specified in a prior call to TrackMouseEvent.
All tracking requested by TrackMouseEvent is canceled when this message is generated.
The application must call TrackMouseEvent when the mouse reenters its window if it requires
further tracking of mouse hover behavior.

:P

RHL

Quote from: dedndave on April 17, 2012, 06:24:41 AM
QuoteWM_MOUSELEAVE
The mouse left the client area of the window specified in a prior call to TrackMouseEvent.
All tracking requested by TrackMouseEvent is canceled when this message is generated.
The application must call TrackMouseEvent when the mouse reenters its window if it requires
further tracking of mouse hover behavior.

:P

oh yeah!, then is required call the function in WM_MOUSEMOVE :P thanks dave, now, I will do it with controls multiples and i will post

RHL

Hello :P
I try do it with multiple controls but I couldn't do it... well - yes, I do it,but incorrectly, apparently...
bcz the cpu is rise 50%-60% when I move the cursor in the control area... :|

I think bcz sometime a return wrong in EAX : P

Dave, ur code also do the cpu rise to 50-60% : P
I read the comments in your code, apparently there is a error in EAX, right?

.386
.model flat,stdcall
option casemap:none

include    \masm32\include\masm32rt.inc

myWNDPROC proto :HWND,:UINT,:WPARAM,:LPARAM
WndProc proto :HWND,:UINT,:WPARAM,:LPARAM
WinMain proto :DWORD,:DWORD

.data
    ClassName db "mypaint",0
    AppName  db "paint program",0

myclass db "Static",0
sname db "statictohide",0
sname2 db "statictohide2",0

hstatic dd 0
hstatic2 dd 0

mysubclass dd 0
returnclass dd 0
.data?
    hInstance HINSTANCE ?

.code

start:
invoke GetModuleHandle, NULL
mov    hInstance,eax

invoke WinMain, hInstance,NULL
invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND

mov   wc.cbSize,SIZEOF WNDCLASSEX
mov   wc.style, CS_HREDRAW or CS_VREDRAW
mov   wc.lpfnWndProc, OFFSET WndProc
mov   wc.cbClsExtra,NULL
mov   wc.cbWndExtra,NULL
push  hInstance
pop   wc.hInstance
mov   wc.hbrBackground,COLOR_BTNFACE+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,eax

invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
           hInst,NULL
mov   hwnd,eax

invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd

.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW

mov     eax,msg.wParam
ret
WinMain endp

myWNDPROC proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL LEAVEAREA:TRACKMOUSEEVENT

.if uMsg==WM_MOUSEMOVE
invoke ShowWindow,hWnd,SW_HIDE

mov edx,hWnd
mov LEAVEAREA.cbSize,sizeof(TRACKMOUSEEVENT)
mov LEAVEAREA.dwFlags,TME_HOVER or TME_LEAVE
mov LEAVEAREA.dwHoverTime,1000
mov LEAVEAREA.hwndTrack,edx
invoke TrackMouseEvent,addr LEAVEAREA

.elseif uMsg==WM_MOUSELEAVE
invoke ShowWindow,hWnd,SW_SHOW
.else
invoke CallWindowProc,mysubclass,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
myWNDPROC endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL LEAVEAREA:TRACKMOUSEEVENT

.IF uMsg==WM_DESTROY
invoke SetWindowLong,mysubclass,GWL_WNDPROC,myWNDPROC
invoke PostQuitMessage,NULL

.ELSEIF uMsg==WM_CREATE

invoke CreateWindowEx,NULL,addr myclass,addr sname,WS_VISIBLE or WS_CHILD or SS_NOTIFY, \
0h,0h,50h,50h,hWnd,NULL,hInstance,NULL

mov hstatic,eax ; save hanlde static control

invoke CreateWindowEx,NULL,addr myclass,addr sname2,WS_VISIBLE or WS_CHILD or SS_NOTIFY, \
60h,0h,50h,50h,hWnd,NULL,hInstance,NULL

mov hstatic2,eax

invoke SetWindowLong,hstatic,GWL_WNDPROC,myWNDPROC
invoke SetWindowLong,hstatic2,GWL_WNDPROC,myWNDPROC
mov mysubclass,eax


.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF

xor eax,eax
ret
WndProc endp
end start



all is ok - but the CPU increases to 50% ( only when move the cursor in the static control area )
-
-
-

I tried do it to several ways, but none worked it
for example, return eax = 1, eax = 0
return with callwindowProc....

and, sometimes the program would crashed...


MichaelW

Now that I have had time to test it, my "subclass" solution did not work as expected, but it did provide some useful information. For a static control the WM_MOUSEMOVE message is sent to the parent window only, and the cursor coordinates are relative to the client area of the parent window, even when the cursor is over the control. If I change the static control to a button, for example, then the subclass procedure receives WM_MOUSEMOVE messages and the cursor coordinates are relative to the client area of the button. So it looks like the problem here is specific to static controls.

In the WM_MOUSEMOVE handler for the parent you can determine if the cursor is in the static control by comparing the cursor coordinates to the control coordinates. This test app includes the subclass code, now commented out. Build as a console app:

;==============================================================================
    include \masm32\include\masm32rt.inc
;==============================================================================
IDC_STC equ 1001
;==============================================================================
    .data
      hInstance         HANDLE  0
      hwndStatic        HWND    0
      wpOrigStaticProc  WNDPROC 0
      pt                POINT   <>
      rc                RECT    <>
    .code
;==============================================================================


SubclassProc proc hwnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

    SWITCH uMsg

        CASE WM_MOUSEMOVE

            printf("S\t%d\t%d\n",wParam,lParam)

    ENDSW

    invoke CallWindowProc, wpOrigStaticProc, hwnd, uMsg, wParam, lParam

    ret

SubclassProc endp

;==============================================================================

DlgProc proc hwndDlg:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

    SWITCH uMsg

        CASE WM_INITDIALOG

            invoke GetDlgItem, hwndDlg, IDC_STC
            mov hwndStatic, eax

            ;invoke SetWindowLong, hwndStatic, GWL_WNDPROC, SubclassProc
            ;mov wpOrigStaticProc, eax

        CASE WM_MOUSEMOVE

            ;-------------------------------------------------------
            ; Load the cursor coordinates into the POINT structure.
            ;-------------------------------------------------------

            mov eax, lParam
            movzx ecx, ax
            shr eax, 16
            movzx edx, ax
            mov pt.x, ecx
            mov pt.y, edx

            ;----------------------------------------------------------
            ; Convert the client coordinates in the POINT structure to
            ; screen coordinates.
            ;-----------------------------------------------------------

            invoke ClientToScreen, hwndDlg, ADDR pt

            ;--------------------------------------------------------------
            ; Get the screen coordinates for the static control rectangle.
            ;--------------------------------------------------------------

            invoke GetWindowRect, hwndStatic, ADDR rc

            ;------------------------------------------------------------
            ; Determine if the cursor is within the bounds of the static
            ; control.
            ;
            ; Because the MASM32 PtInRect proto specifies three DWORD
            ; args instead of one DWORD and one POINT arg, the POINT
            ; arg must be split into its DWORD components.
            ;------------------------------------------------------------

            invoke PtInRect, ADDR rc, pt.x, pt.y
            .IF eax
                printf("X")
            .ELSE
                printf("0")
            .ENDIF

        CASE WM_COMMAND

            SWITCH wParam

                CASE IDCANCEL

                    invoke EndDialog, hwndDlg, NULL

            ENDSW

        CASE WM_CLOSE

            invoke EndDialog, hwndDlg, NULL

    ENDSW

    return 0

DlgProc endp

;==============================================================================
start:
;==============================================================================

    invoke GetModuleHandle, NULL
    mov   hInstance, eax

    Dialog "Test", \
           "MS Sans Serif",10, \
           WS_VISIBLE or WS_OVERLAPPED or WS_SYSMENU or DS_CENTER, \
           1,0,0,100,100,1024

    DlgStatic 0,WS_BORDER or SS_BITMAP,10,10,78,70,IDC_STC
    ;DlgButton "X",0,10,10,78,70,IDC_STC

    CallModalDialog hInstance,0,DlgProc,NULL

    exit
;==============================================================================
end start

eschew obfuscation

dedndave

you may get hundreds of WM_MOUSEMOVE messages
what we need is a flag that we can test to see if the code has been executed

there are a few things we can do to speed things up
1) put the TRACKMOUSEEVENT in the initialized .DATA section
initialize everything except the hwndTrack member
2) when you execute the WM_MOUSEMOVE code, test the hwndTrack member to see if it matches the current hWnd
if it does, you have already hidden the window and set up tracking, so exit
if it does not, hide the window and set up tracking
3) when you receive the WM_MOUSELEAVE message, set the hwndTrack member to 0 (or some non-hWnd value)

dedndave

very strange
i continually get WM_MOUSELEAVE messages while hovering over the static control
i guess i'll have to add code that tests the cursor position inside the bounds of the static rectangle   ::)

EDIT: that won't help, as the tracking event is supposedly canceled each time the message is sent   :(

i must be doing something wrong

dedndave

ok - once again, we have to force windows to behave the way it should - lol
observe processor usage while hovering over the static controls....

i should probably add a test to see if the parent is the top window
it keeps working when the static control is partially obscured by another window - lol

dedndave

#25
ok - now it only works if the dialog is the foreground window   :P
back to the other project...

jj2007

All that looks like an overkill to me... why not simple use a region matching the control??

QuoteCASE WM_MOUSEMOVE
      if 0   ; in WM_SIZE:
         invoke DeleteObject, hRgn
         lea eax, [esi+ButtonWidth]
         mov hRgn, rv(CreateRectRgn, esi, 11+ButtonHeight*(1+UseButton2), eax, 11+ButtonHeight*(2+UseButton2))
      endif
      movsx eax, word ptr lParam
      movsx edx, word ptr lParam+2
      invoke PtInRegion, hRgn, eax, edx
      .if eax
         .if !rgnHit
            SetWin$ hStatic="Get outta here"
            or rgnHit, -1
         .endif
         .if wParam == MK_SHIFT
            SetWin$ hStatic="SHIFT outta here"
         .endif
      .elseif rgnHit
         and rgnHit, 0
         SetWin$ hStatic="Bye"
      .endif

RHL

dave, amazing! :| but i have a question!
HOW YOU DO IT?
how to you know where is error? ( actually is not error, is a bad program structured )
how to you know what to functions  ?

tell me!, I want learn lol  :red

I will convert it to WNDPROC procedure program : P

@JJ
where i can download the Masmbasic.inc , gives me errors : P


dedndave

Jochen's method might be a good one   :P

the way i fgured out when messages were being sent...
i use lines like this to tell me - sometimes it tells you more than olly
invoke Beep,300,40

i also have this other program i wrote to tell me what messages are sent...
http://www.masm32.com/board/index.php?topic=17163.0