flat assembler
Message board for the users of flat assembler.

Index > Windows > move two windows alongside each other

Author
Thread Post new topic Reply to topic
DergMoney



Joined: 29 Apr 2015
Posts: 34
DergMoney 26 May 2015, 17:10
OK, so I got the problem in the previous thread sorted so here's another.

I have added the ability to move my small black window (SBW) by pressing and holding the right mouse button whilst moving. Works fine. Another thing I want to have happen is that when the target window (windows calculator in this instance) is being moved, I want my SBW to move with it, so it remains in the same position relative to the target. When I move the target window, mine does not move until it receives some other event msg such as tabbing to give it focus or moving the mouse over it, then it jumps to the correct position.

I've tried placing the code for this in different places in different procs. Where it is placed now, between the two ;************** is the only place it nearly does what I want.

I can't think of any windows messages I can intercept to make this work.

I've tried using SetWindowsHookEx with WH_CALLWNDPROCRET to capture the target's messages but my program crashes.

Any way I can do this without hooking?

Thanks for your time and sorry for the long read Sad

Code:
format PE GUI 4.0
entry start

include "%fasminc%\win32a.inc"

section '.code' code readable executable

    start:
        invoke  GetModuleHandle, 0
        mov         [wc.hInstance], eax
        mov     [wcHUD.hInstance], eax
        invoke  LoadIcon, 0, IDI_APPLICATION
        mov         [wc.hIcon], eax
        mov         [wcHUD.hIcon], eax
        invoke  LoadCursor, 0, IDC_ARROW
        mov         [wc.hCursor], eax
        mov         [wcHUD.hCursor], eax
        invoke  RegisterClass, wc
        invoke  RegisterClass, wcHUD
        or          eax,eax
        jz          error
        invoke  CreateWindowEx, NULL, ClassMain, AppName, WS_OVERLAPPEDWINDOW or WS_VISIBLE, 100, 100, 600, 200, NULL, NULL, [wc.hInstance], NULL
        test    eax,eax
        jz          error
        mov     [hWndMain], eax
        invoke  EnumWindows, EnumWindowsProc, 0
        cmp     [hWndPS], -1
        je      msgLoop
        invoke  GetWindowRect, [hWndPS], psRectOld

    msgLoop:
        invoke  GetMessage, msg, NULL, 0, 0
        or          eax, eax
        jz          endLoop
        invoke  TranslateMessage, msg
        invoke  DispatchMessage, msg
        ; was target window found
        cmp     [hWndPS], -1
        ; if not, back to msgLoop
        je      msgLoop
;******************
        ; get position of target window
        invoke  GetWindowRect, [hWndPS], psRectNew
        push    edi esi
        mov     ecx, 4
        mov     edi, psRectNew
        mov     esi, psRectOld
        ; has it changed?
        rep     cmpsd
        ; if not, back to msgLoop
        je      msgLoop

        ; get new position of my window (since it may have been moved with right mouse button from psRectOld)
        invoke  GetWindowRect, [hWndHUD], rect
        mov     eax, [psRectNew.left]
        sub     eax, [psRectOld.left]
        add     [rect.left], eax
        mov     eax, [psRectNew.top]
        sub     eax, [psRectOld.top]
        add     [rect.top], eax
        mov     eax, [psRectNew.right]
        sub     eax, [psRectOld.right]
        add     eax, [rect.right]
        sub     eax, [rect.left]
        mov     [rect.right], eax
        mov     eax, [psRectNew.bottom]
        sub     eax, [psRectOld.bottom]
        add     eax, [rect.bottom]
        sub     eax, [rect.top]
        mov     [rect.bottom], eax
        ; move my window
        invoke  MoveWindow, [hWndHUD], [rect.left], [rect.top], [rect.right], [rect.bottom], TRUE
        ; save current position
        push    [psRectNew.left]
        pop     [psRectOld.left]
        push    [psRectNew.top]
        pop     [psRectOld.top]
        push    [psRectNew.right]
        pop     [psRectOld.right]
        push    [psRectNew.bottom]
        pop     [psRectOld.bottom]
;******************
        jmp         msgLoop
    error:
        invoke  MessageBox, NULL, errorStr, NULL, MB_ICONERROR + MB_OK
    endLoop:
        invoke  ExitProcess, [msg.wParam]

proc WndProc hwnd, wmsg, wparam, lparam
        push    ebx esi edi
        cmp     [wmsg], WM_DESTROY
        je      .wmDestroy
    .defWndProc:
        invoke  DefWindowProc, [hwnd], [wmsg], [wparam], [lparam]
        jmp     .finish
    .wmDestroy:
        invoke  DestroyWindow, [hWndHUD]
        invoke  PostQuitMessage, 0
        xor         eax, eax
    .finish:
        pop     edi esi ebx
        ret
endp

proc EnumWindowsProc hwnd, lparam
        push    ebx esi edi
        invoke  GetWindowText, [hwnd], strBuff, 1000
        or      eax, eax
        jz      .retTrue
        invoke  lstrlen, strBuff
        mov     ecx, eax
        mov     al, "C"
        mov     edi, strBuff
        repne   scasb
        jne     .retTrue
        mov     esi, searchStr + 1
        invoke  lstrlen, searchStr
        dec     eax
        mov     ecx, eax
        rep     cmpsb
        jne     .retTrue
        invoke  GetClassName, [hwnd], strBuff, 1000
        invoke  lstrlen, psClass
        mov     ecx, eax
        mov     esi, psClass
        mov     edi, strBuff
        rep     cmpsb
        jne     .retTrue
        ; have found the calculator window
        push    [hwnd]
        pop     [hWndPS]
        invoke  CreateWindowEx, WS_EX_LAYERED, ClassHUD, NULL, WS_POPUP or WS_VISIBLE, 800, 100, 50, 25, [hWndPS], NULL, [wcHUD.hInstance], NULL
        test    eax,eax
        jz          error
        mov     [hWndHUD], eax
        invoke  SetLayeredWindowAttributes, [hWndHUD], 0, 255, LWA_ALPHA
        invoke  SetFocus, [hWndPS]
    .retFalse:
        mov     eax, FALSE
        jmp     .finish
    .retTrue:
        mov     eax, TRUE
    .finish:
        pop     edi esi ebx
        ret
endp        

proc WndProcHUD hwnd, wmsg, wparam, lparam
        push    ebx esi edi
        cmp     [rbd], TRUE
        jne     @f
        cmp     [wmsg], WM_MOUSEMOVE
        je      .wmMouseMove
    @@:
        cmp     [wmsg], WM_RBUTTONDOWN
        je      .wmRButtonDown
        cmp     [wmsg], WM_RBUTTONUP
        je      .wmRButtonUp
    .defWndProc:
        invoke  DefWindowProc, [hwnd], [wmsg], [wparam], [lparam]
        jmp     .finish
    .wmRButtonDown:
        mov     [rbd], TRUE             ; set flag to show right button is pressed
        mov     eax, [lparam]
        and     eax, 0x0000FFFF
        mov     [mousePosOld.x], eax
        mov     eax, [lparam]
        shr     eax, 16
        mov     [mousePosOld.y], eax
        xor     eax, eax
        jmp     .finish
    .wmRButtonUp:
        mov     [rbd], FALSE
        xor     eax, eax
        jmp     .finish
    .wmMouseMove:
        mov     eax, [lparam]
        and     eax, 0x0000FFFF
        mov     [mousePos.x], eax
        mov     eax, [lparam]
        shr     eax, 16
        mov     [mousePos.y], eax
        invoke  GetWindowRect, [hwnd], rect
        mov     ebx, [mousePos.x]
        sub     ebx, [mousePosOld.x]
        add     ebx, [rect.left]                ; ebx = new xPos of window
        mov     esi, [mousePos.y]
        sub     esi, [mousePosOld.y]
        add     esi, [rect.top]                 ; esi = new yPos of window
        mov     eax, [rect.left]
        sub     [rect.right], eax               ; rect.right = width of window
        mov     eax, [rect.top]
        sub     [rect.bottom], eax              ; rect.bottom = height of window
        invoke  MoveWindow, [hwnd], ebx, esi, [rect.right], [rect.bottom], TRUE
        xor     eax, eax
        jmp     .finish
    .finish:
        pop     edi esi ebx
        ret
endp


showError: 
        pushad 
        invoke  GetLastError 
        invoke  FormatMessage, FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, eax, LANG_NEUTRAL, errStrBuff, 0, NULL
        invoke  MessageBox, HWND_DESKTOP, [errStrBuff], NULL, MB_ICONERROR or MB_OK 
        popad 
        ret 

section '.data' data readable writeable
    ClassMain   db "WinClass", 00
    ClassHUD    db "hud", 00
    hWndHUD     dd ?
    AppName     db "My App", 00
    errorStr    db "oops!", 00
    hWndMain    dd ?
    hWndPS      dd -1
    psWndProcHnd dd ?
    titlePS     db 1002 dup ?
    strBuff     db 1002 dup ?
    wordBuff    db 40 dup ?
    space       db " ", 00
    errStrBuff  dd ?
    wc          WNDCLASS CS_HREDRAW or CS_VREDRAW, WndProc, 0, 0, NULL, NULL, NULL, COLOR_BTNFACE + 1, NULL, ClassMain
    msg         MSG
    searchStr   db "Calculator", 00
    rect        RECT
    numStr      db "%i", 00
    psClass     db "CalcFrame", 00
    psRectOld   RECT
    psRectNew   RECT
    wcHUD       WNDCLASS CS_HREDRAW or CS_VREDRAW, WndProcHUD, 0, 0, NULL, NULL, NULL, COLOR_BTNFACE + 4, NULL, ClassHUD
    rbd         dd FALSE
    mousePos    POINT       ; new position for mouse input
    mousePosOld POINT       ; old position for mouse input

section '.idata' import data readable writeable 
library kernel32,'KERNEL32.DLL',\ 
        user32,  'USER32.DLL',\ 
        gdi32,   'GDI32.DLL',\ 
        comdlg32,'COMDLG32.DLL',\ 
        advapi32,'ADVAPI32.DLL',\ 
        comctl32,'COMCTL32.DLL',\
        msvcrt, 'msvcrt.dll'

include '%fasminc%\api\Kernel32.inc' 
include '%fasminc%\api\User32.inc' 
include '%fasminc%\api\Gdi32.inc' 
include '%fasminc%\api\Comdlg32.inc' 
include '%fasminc%\api\Advapi32.inc' 
include '%fasminc%\api\Comctl32.inc'
import msvcrt,\ 
        sprintf,'sprintf'
    


Description:
Download
Filename: findcalc.zip
Filesize: 1.37 KB
Downloaded: 248 Time(s)

Post 26 May 2015, 17:10
View user's profile Send private message Reply with quote
El Tangas



Joined: 11 Oct 2003
Posts: 120
Location: Sunset Empire
El Tangas 26 May 2015, 21:22
I'm still interested in your case, also curious if this is possible... Smile

So, with the help of OllyDbg, I have determined that your window receives messages WM_WINDOWPOSCHANGING and WM_WINDOWPOSCHANGED when the calculator window is moved. Probably because the system is telling it to set its Z-order above Calculator. So you can use those events to reposition, I think.

In fact, the lParam of these messages is a pointer to a WINDOWPOS structure that maybe you can change just what you need (x,y position), then send for default processing. Let windows do the work for you.
Post 26 May 2015, 21:22
View user's profile Send private message Reply with quote
DergMoney



Joined: 29 Apr 2015
Posts: 34
DergMoney 26 May 2015, 23:24
Hi again El Tangas,

You are right in the first two things, yes my window does get those messages and it is due to a change in z-order. However, because it is only indicating this change in z-order, the x, y, width and height are NULL in the WINDOWPOS structure. It may be possible that my MoveWindow routine will work here, I'll give it a go tomorrow, 0:22am here. Wink
Post 26 May 2015, 23:24
View user's profile Send private message Reply with quote
El Tangas



Joined: 11 Oct 2003
Posts: 120
Location: Sunset Empire
El Tangas 27 May 2015, 13:25
Well, this doesn't seem to be easy. Maybe you have to set up a timer and regularly check if the target window has moved, say 10 times per second or so. Not elegant at all Sad

Maybe your hook failed because of this:

Quote:
Because hooks run in the context of an application, they must match the "bitness" of the application. If a 32-bit application installs a global hook on 64-bit Windows, the 32-bit hook is injected into each 32-bit process (the usual security boundaries apply). In a 64-bit process, the threads are still marked as "hooked." However, because a 32-bit application must run the hook code, the system executes the hook in the hooking app's context; specifically, on the thread that called SetWindowsHookEx. This means that the hooking application must continue to pump messages or it might block the normal functioning of the 64-bit processes


From what I gather, maybe calc.exe is 64 bit and needs a 64 bit hook code. Maybe the hook procedure should be assembled with use64. Sorry, never used hooks, actually.
Post 27 May 2015, 13:25
View user's profile Send private message Reply with quote
DergMoney



Joined: 29 Apr 2015
Posts: 34
DergMoney 27 May 2015, 15:09
Again, you are indeed right. In Win7 there are actually 2 calc.exe programs, one is in rootdrive:\Windows\System32 and the other is in rootdrive:\Windows\SysWOW64. These are different versions, one being 32-bit and the other 64-bit. I have tried it with both with no success.

This forum is very quiet nowadays so it is hard to get help. I see that Tomasz, the original developer of FASM hasn't even updated the copyright for the site since 2013.

I was a member way back when but lost my login details and changed email address so had to rejoin when I came up against this problem.

I have written a hook DLL for WH_CALLWNDPROC and WH_CALLWNDPROCRET and am fiddling with that at the minute. I'll let you know how it goes.
Post 27 May 2015, 15:09
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 27 May 2015, 17:56
If you want the current size and position, GetWindowRect should be enough.

In addition to focus/zorder things from WM_WINDOWxxxx there are other potentially useful messages like WM_SIZE will tell you new size.
Post 27 May 2015, 17:56
View user's profile Send private message Reply with quote
DergMoney



Joined: 29 Apr 2015
Posts: 34
DergMoney 27 May 2015, 19:16
Hi cod3b453,

Thanks for the reply. I have used GetWindowRect but my window update until the other has stopped. I want mine to be dragged with one that is moving.
Post 27 May 2015, 19:16
View user's profile Send private message Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 27 May 2015, 19:37
Embarassed Forgot to finish my list with "and WM_MOVE will tell you the new position" in my previous; the combination of those two should allow to you handle moving and sizing.
Post 27 May 2015, 19:37
View user's profile Send private message Reply with quote
DergMoney



Joined: 29 Apr 2015
Posts: 34
DergMoney 27 May 2015, 20:15
Thanks again, but as I say, I have no problem getting size and co-ordinates of the target window and using WM_MOVE etc for my window, but while the target has the focus mine will not update, i.e. move.
Post 27 May 2015, 20:15
View user's profile Send private message Reply with quote
El Tangas



Joined: 11 Oct 2003
Posts: 120
Location: Sunset Empire
El Tangas 27 May 2015, 20:33
Meanwhile, I was working on this problem using the timer method, since you are trying the hook method. I have a working prototype, check it out.
Made a few changes to your original code to simplify it. For example, I just search for the class name, since the window name changes with language, and removed your main window, there is only the HUD window (we can close it with ALT-F4).
Used CreateTimerQueueTimer and DeleteTimerQueueTimer functions that were not even included in fasm's kernel32.inc, guess nobody here has used them before Shocked so I include source, binary and the updated kernel32.inc
(Code may have some leftovers Confused )

Code:
format PE GUI 4.0

include 'win32ax.inc'

struc LENSTRING [string]
{
        common
                align 4
                . db string
                .len = $ - .
                db 0
}

.code

    start:
        invoke  GetModuleHandle, 0
        mov     [wcHUD.hInstance], eax
        invoke  LoadIcon, 0, IDI_APPLICATION
        mov     [wcHUD.hIcon], eax
        invoke  LoadCursor, 0, IDC_ARROW
        mov     [wcHUD.hCursor], eax
        invoke  RegisterClass, wcHUD
        or      eax,eax
        jz      error
        invoke  EnumWindows, EnumWindowsProc, 0

    msgLoop:
        invoke  GetMessage, msg, NULL, 0, 0
        or      eax, eax
        jz      endLoop
        invoke  TranslateMessage, msg
        invoke  DispatchMessage, msg
        jmp     msgLoop
    error:
        invoke  MessageBox, NULL, errorStr, NULL, MB_ICONERROR + MB_OK
    endLoop:
        invoke  DeleteTimerQueueTimer, 0, [hTimer], 0

        invoke  ExitProcess, [msg.wParam]

proc EnumWindowsProc hwnd, lparam
        push    ebx esi edi
        ;invoke  GetWindowText, [hwnd], strBuff, 1000
        ;or      eax, eax
        ;jz      .retTrue

        ;mov     ecx, eax
        ;mov     eax, dword [searchStr]
        ;mov     edi, strBuff
        ;shl     ecx,2
        ;repne   scasd
        ;jne     .retTrue
        ;mov     esi, searchStr + 4

        ;mov     ecx, searchStr.len - 4
        ;rep     cmpsb
        ;jne     .retTrue

        invoke  GetClassName, [hwnd], strBuff, 1000

        mov     ecx, psClass.len
        mov     esi, psClass
        mov     edi, strBuff
        rep     cmpsb
        jne     .retTrue

        ; have found the calculator window
;        int3
        push    [hwnd]
        pop     [hWndPS]
        invoke  CreateWindowEx, WS_EX_LAYERED, ClassHUD, NULL, WS_POPUP or WS_VISIBLE, 0, 0, 100, 100, [hWndPS], NULL, [wcHUD.hInstance], NULL
        test    eax,eax
        jz      error
        mov     [hWndHUD], eax
        invoke  SetLayeredWindowAttributes, [hWndHUD], 0, 255, LWA_ALPHA
        invoke  SetFocus, [hWndPS]

        ;setup timer
        invoke CreateTimerQueueTimer, hTimer, 0, TimeUp, 0, 100, 100, 0

    .retFalse:
        mov     eax, FALSE
        jmp     .finish
    .retTrue:
        mov     eax, TRUE
    .finish:
        pop     edi esi ebx
        ret
endp        

proc TimeUp lpParameter, TimerOrWaitFired
        push    ebx edi esi
        invoke  GetWindowRect, [hWndPS], TgtPos
        invoke  GetWindowRect, [hWndHUD], HUDPos
        mov     eax,[TgtPos.left]
        cmp     eax,[HUDPos.left]
        jne     .repositionHUD
        mov     eax,[TgtPos.top]
        cmp     eax,[HUDPos.top]
        jne     .repositionHUD
    .finish:
        pop     esi edi ebx
        ret
    .repositionHUD:
        invoke  SetWindowPos, [hWndHUD],0,[TgtPos.left],[TgtPos.top],0,0,SWP_SHOWWINDOW or SWP_NOSIZE or SWP_NOZORDER
        jmp     .finish
endp


proc WndProcHUD hwnd, wmsg, wparam, lparam
        push    ebx edi esi
        cmp     [wmsg], WM_DESTROY
        je      .wmDestroy
    .defWndProc:
        invoke  DefWindowProc, [hwnd], [wmsg], [wparam], [lparam]
        jmp     .finish
    .wmDestroy:
        invoke  PostQuitMessage, 0
        xor     eax, eax
    .finish:
        pop     esi edi ebx
        ret
endp


showError: 
        pushad 
        invoke  GetLastError 
        invoke  FormatMessage, FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, eax, LANG_NEUTRAL, errStrBuff, 0, NULL
        invoke  MessageBox, HWND_DESKTOP, [errStrBuff], NULL, MB_ICONERROR or MB_OK 
        popad 
        ret 

.data
    ClassHUD    LENSTRING "hud"
    errorStr    LENSTRING "oops!"
    ;searchStr   LENSTRING "Calculator"
    psClass     LENSTRING "CalcFrame"

    align 4
    hTimer      dd ?
    hWndHUD     dd ?
    hWndPS      dd ?
    psWndProcHnd dd ?
    titlePS     db 1004 dup ?
    strBuff     db 1004 dup ?
    wordBuff    db 40 dup ?
    errStrBuff  dd ?
    msg         MSG

    TgtPos      RECT
    HUDPos      RECT
    wcHUD       WNDCLASS CS_HREDRAW or CS_VREDRAW, WndProcHUD, 0, 0, NULL, NULL, NULL, COLOR_BTNFACE + 4, NULL, ClassHUD

virtual at 0
    windowpos WINDOWPOS
end virtual


.end start       


Description:
Download
Filename: findcalc.zip
Filesize: 8.9 KB
Downloaded: 251 Time(s)

Post 27 May 2015, 20:33
View user's profile Send private message Reply with quote
DergMoney



Joined: 29 Apr 2015
Posts: 34
DergMoney 27 May 2015, 20:55
Great work El Tangas, you've got further than me Wink As you say, there are things not included in the kernel, and also questions that have never been asked. i.e. WH_CALLWNDPROC and WH_CALLWNDPROCRET have no results in the forum. There is a FASM equivalent of Iczelion's hook tutorial for WH_MOUSE but not working very well. A google search shows that the 2 hooks I am looking at seem hard to implement.

Thanks for the time you put in, I only tried the *.exe, good stuff. I'll get a look at the code tomorrow Wink

If I manage to get the hook working I'll post it here in case it's of help to anyone else.
Post 27 May 2015, 20:55
View user's profile Send private message Reply with quote
DergMoney



Joined: 29 Apr 2015
Posts: 34
DergMoney 06 Jun 2015, 16:48
Finally got time to look at this again. I came across a function I didn't know existed, SetWinEventHook

https://msdn.microsoft.com/en-us/library/windows/desktop/dd373640%28v=vs.85%29.aspx

I now have my black window doing all I required. It moves in tandem with the calculator window. It can be moved on its own with the righthand mouse button and will keep the same relative position to the calculator window when the calc window is moved again. If the calc window is minimized the black window is hidden and when the calc window is closed the black window is too. This doesn't destroy my main window, so if the calculator is re-opened my black window is created again Wink

Code:

format PE GUI 4.0
entry start

include "%fasminc%\win32a.inc"

section '.code' code readable executable

    start:
        invoke  GetModuleHandle, 0
        mov         [wc.hInstance], eax
        mov         [wcHUD.hInstance], eax
        invoke  LoadIcon, 0, IDI_APPLICATION
        mov         [wc.hIcon], eax
        mov         [wcHUD.hIcon], eax
        invoke  LoadCursor, 0, IDC_ARROW
        mov         [wc.hCursor], eax
        mov         [wcHUD.hCursor], eax
        invoke  RegisterClass, wc
        or          eax,eax
        jz          error
        invoke  RegisterClass, wcHUD
        or          eax,eax
        jz          error
        invoke  CreateWindowEx, NULL, ClassMain, AppName, WS_OVERLAPPEDWINDOW or WS_VISIBLE, 100, 100, 420, 170, NULL, NULL, [wc.hInstance], NULL
        test    eax,eax
        jz          error
        mov     [hWndMain], eax
        mov     [hWndPS], 00
        ; check if the calculator is already opened
        invoke  EnumWindows, EnumWindowsProc, 0

    msgLoop:
        invoke  GetMessage, msg, NULL, 0, 0
        or          eax, eax
        jz          endLoop
        invoke  TranslateMessage, msg
        invoke  DispatchMessage, msg
        jmp         msgLoop
    error:
        invoke  MessageBox, NULL, errorStr, NULL, MB_ICONERROR + MB_OK
    endLoop:
        invoke  ExitProcess, [msg.wParam]

proc WndProc hwnd, wmsg, wparam, lparam
        push    ebx edi esi
        cmp     [wmsg], WM_CREATE
        je      .wmCreate
        cmp     [wmsg], WM_DESTROY
        je      .wmDestroy
    .defWndProc:
        invoke  DefWindowProc, [hwnd], [wmsg], [wparam], [lparam]
        jmp     .finish
    .wmCreate:
        ; create the 3 hooks for capturing calculator events
        invoke  SetWinEventHook, EVENT_OBJECT_DESTROY, EVENT_OBJECT_DESTROY, NULL, winEventProc, 0, 0, WINEVENT_OUTOFCONTEXT
        mov     [hookDestroyHnd], eax
        invoke  SetWinEventHook, EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, NULL, winEventProc, 0, 0, WINEVENT_OUTOFCONTEXT
        mov     [hookLocationHnd], eax
        invoke  SetWinEventHook, EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, NULL, winEventProc, 0, 0, WINEVENT_OUTOFCONTEXT
        mov     [hookCreateHnd], eax
        xor     eax, eax
        jmp     .finish
    .wmDestroy:
        ; kill the 3 hooks
        invoke  UnhookWinEvent, [hookDestroyHnd]
        invoke  UnhookWinEvent, [hookLocationHnd]
        invoke  UnhookWinEvent, [hookCreateHnd]
        invoke  PostQuitMessage, 0
        xor         eax, eax
    .finish:
        pop         esi edi ebx
        ret
endp

proc WndProcHUD hwnd, wmsg, wparam, lparam
        push    ebx esi edi
        mov     eax, [hwnd]
        cmp     eax, [hWndHUD]
        jne     .defWndProc
        cmp     [rbd], TRUE             ; [rbd] is a flag to show if the right mouse button is down, if FALSE then don't process WM_MOUSEMOVE message
        jne     @f
        cmp     [wmsg], WM_MOUSEMOVE
        je      .wmMouseMove
    @@:
        cmp     [wmsg], WM_RBUTTONDOWN
        je      .wmRButtonDown
        cmp     [wmsg], WM_RBUTTONUP
        je      .wmRButtonUp
        cmp     [wmsg], WM_DESTROY
        je      .wmDestroy
    .defWndProc:
        invoke  DefWindowProc, [hwnd], [wmsg], [wparam], [lparam]
        jmp     .finish
    .wmRButtonDown:
        mov     [rbd], TRUE             ; set flag to show right button is pressed
        mov     eax, [lparam]
        and     eax, 0x0000FFFF
        mov     [mousePosOld.x], eax    ; save current mouse co-ordinates
        mov     eax, [lparam]
        shr     eax, 16
        mov     [mousePosOld.y], eax
        xor     eax, eax
        jmp     .finish
    .wmRButtonUp:
        mov     [rbd], FALSE
        xor     eax, eax
        jmp     .finish
    .wmMouseMove:
        mov     eax, [lparam]
        and     eax, 0x0000FFFF
        mov     [mousePos.x], eax
        mov     eax, [lparam]
        shr     eax, 16
        mov     [mousePos.y], eax
        invoke  GetWindowRect, [hwnd], rectHUD
        mov     eax, [rectHUD.left]         ; get width and height
        sub     [rectHUD.right], eax
        mov     eax, [rectHUD.top]
        sub     [rectHUD.bottom], eax
        mov     eax, [mousePos.x]
        sub     eax, [mousePosOld.x]
        add     [rectHUD.left], eax
        mov     eax, [mousePos.y]
        sub     eax, [mousePosOld.y]
        add     [rectHUD.top], eax
        invoke  MoveWindow, [hwnd], [rectHUD.left], [rectHUD.top], [rectHUD.right], [rectHUD.bottom], TRUE
        xor     eax, eax
        jmp     .finish
    .wmDestroy:
        mov     [hWndPS], 00
        xor         eax, eax
        jmp     .finish
    .finish:
        pop         esi edi ebx
        ret
endp

proc winEventProc hWinEventHook, event, hwnd, idObject, idChild, idEventThread, dwmsEventTime
        cmp     [hWndPS], 00
        jne     @f
        ; calculator isn't running, check if this is a creation event, if it is then process it.
        cmp     [event], EVENT_OBJECT_CREATE
        je      .eventObjectCreate
        jmp     .finish
      @@:
        mov     eax, [hWndPS]
        cmp     eax, [hwnd]
        ; if not the calculator don't do any further processing.
        jne     .finish
        cmp     [event], EVENT_OBJECT_DESTROY
        je      .eventObjectDestroy
        cmp     [event], EVENT_OBJECT_LOCATIONCHANGE
        je      .eventObjectLocationChange
        jmp     .finish
    .eventObjectCreate:
        ; see if the created object is the calculator, black window will be created before return if it is
        stdcall EnumWindowsProc, [hwnd], NULL
        jmp     .finish
    .eventObjectLocationChange:
        ; calculator is being moved, update black window position
        invoke  GetWindowRect, [hwnd], psRectNew
        mov     eax, [psRectNew.left]
        cmp     eax, [psRectOld.left]
        jne     .moved
        mov     eax, [psRectNew.top]
        cmp     eax, [psRectOld.top]
        jne     .moved
        mov     eax, [psRectNew.right]
        cmp     eax, [psRectOld.right]
        jne     .moved
        mov     eax, [psRectNew.bottom]
        cmp     eax, [psRectOld.bottom]
        je      .finish
    .moved:
        invoke  GetWindowRect, [hWndHUD], rectHUD
        mov     eax, [rectHUD.left]
        sub     [rectHUD.right], eax                ; width
        mov     eax, [rectHUD.top]
        sub     [rectHUD.bottom], eax               ; height
        mov     eax, [psRectNew.left]
        sub     eax, [psRectOld.left]
        add     [rectHUD.left], eax                 ; x pos
        mov     eax, [psRectNew.top]
        sub     eax, [psRectOld.top]
        add     [rectHUD.top], eax                  ; y pos
        invoke  MoveWindow, [hWndHUD], [rectHUD.left], [rectHUD.top], [rectHUD.right], [rectHUD.bottom], TRUE
        mov     esi, psRectNew
        mov     edi, psRectOld
        mov     ecx, 4
        rep     movsd
        xor     eax, eax
        jmp     .finish
    .eventObjectDestroy:
        ; calculator is about to be closed, close black window
        invoke  DestroyWindow, [hWndHUD]
        jmp     .finish
    .finish:
        ret
endp

proc EnumWindowsProc hwnd, lparam
        ; checks [hwnd]'s class name to see if it's the calculator
        push    ebx esi edi
        invoke  GetClassName, [hwnd], strBuff, 1000
        invoke  lstrlen, psClass
        mov     ecx, eax
        mov     esi, psClass
        mov     edi, strBuff
        rep     cmpsb
        jne     .retTrue
        ; have found the calculator window
        mov     eax, [hwnd]
        call    createHUD
    .retFalse:
        mov     eax, FALSE
        jmp     .finish
    .retTrue:
        mov     eax, TRUE
    .finish:
        pop     edi esi ebx
        ret
endp        

showError:
        push    ebx edi esi
        invoke  GetLastError 
        invoke  FormatMessage, FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, eax, LANG_NEUTRAL, errStrBuff, 0, NULL
        invoke  MessageBox, HWND_DESKTOP, [errStrBuff], NULL, MB_ICONERROR or MB_OK or MB_SETFOREGROUND
        pop     esi edi ebx
        ret

createHUD:
        ; gets position of calculator to position the black window
        mov     [hWndPS], eax
        invoke  GetWindowRect, [hWndPS], psRectOld
        invoke  CreateWindowEx, WS_EX_LAYERED, ClassHUD, NULL, WS_POPUP or WS_VISIBLE, [psRectOld.left], [psRectOld.top], 100, 50, [hWndPS], NULL, [wcHUD.hInstance], NULL
        or      eax, eax
        jnz     @f
        call    showError
      @@:
        mov     [hWndHUD], eax
        invoke  SetLayeredWindowAttributes, [hWndHUD], 0, 255, LWA_ALPHA
        invoke  GetWindowRect, [hWndHUD], rectHUD
        mov     [rectHUD.right], 100
        mov     [rectHUD.bottom], 50
        ret

section '.data' data readable writeable

    psRectOld       RECT
    psRectNew       RECT
    rectHUD         RECT
    mousePosOld     POINT
    mousePos        POINT
    wc              WNDCLASS CS_HREDRAW or CS_VREDRAW, WndProc, 0, 0, NULL, NULL, NULL, COLOR_BTNFACE + 1, NULL, ClassMain
    wcHUD           WNDCLASS CS_HREDRAW or CS_VREDRAW, WndProcHUD, 0, 0, NULL, NULL, NULL, COLOR_BTNFACE + 4, NULL, ClassHUD
    msg             MSG
    rbd             dd FALSE
    ClassMain       db "Main Class", 00
    ClassHUD        db "HUD Class", 00
    AppName         db "SetWinEventHook Test", 00
    psClass         db "CalcFrame", 00
    errorStr        db "oops!", 00
    strBuff         db 1000 dup ?
    hWndMain        dd ?
    hWndPS          dd ?
    hWndHUD         dd ?
    hookLocationHnd dd ?
    hookDestroyHnd  dd ?
    hookCreateHnd   dd ?
    errStrBuff      dd ?

section '.idata' import data readable writeable 
library kernel32,  'KERNEL32.DLL',\ 
        user32,    'USER32.DLL'

include '%fasminc%\api\Kernel32.inc' 
include '%fasminc%\api\User32.inc' 

    


The equates for use with SetWinEventHook are not in the fasm user32.inc file so here they are...

Code:
; Event codes for SetWinEventHook

EVENT_MIN                       = 00000001h
EVENT_SYSTEM_SOUND              = 00000001h
EVENT_SYSTEM_ALERT              = 00000002h
EVENT_SYSTEM_FOREGROUND         = 00000003h
EVENT_SYSTEM_MENUSTART          = 00000004h
EVENT_SYSTEM_MENUEND            = 00000005h
EVENT_SYSTEM_MENUPOPUPSTART     = 00000006h
EVENT_SYSTEM_MENUPOPUPEND       = 00000007h
EVENT_SYSTEM_CAPTURESTART       = 00000008h
EVENT_SYSTEM_CAPTUREEND         = 00000009h
EVENT_SYSTEM_MOVESIZESTART      = 0000000ah
EVENT_SYSTEM_MOVESIZEEND        = 0000000bh
EVENT_SYSTEM_CONTEXTHELPSTART   = 0000000ch
EVENT_SYSTEM_CONTEXTHELPEND     = 0000000dh
EVENT_SYSTEM_DRAGDROPSTART      = 0000000eh
EVENT_SYSTEM_DRAGDROPEND        = 0000000fh
EVENT_SYSTEM_DIALOGSTART        = 00000010h
EVENT_SYSTEM_DIALOGEND          = 00000011h
EVENT_SYSTEM_SCROLLINGSTART     = 00000012h
EVENT_SYSTEM_SCROLLINGEND       = 00000013h
EVENT_SYSTEM_SWITCHSTART        = 00000014h
EVENT_SYSTEM_SWITCHEND          = 00000015h
EVENT_SYSTEM_MINIMIZESTART      = 00000016h
EVENT_SYSTEM_MINIMIZEEND        = 00000017h
EVENT_OBJECT_CREATE             = 00008000h
EVENT_OBJECT_DESTROY            = 00008001h
EVENT_OBJECT_SHOW               = 00008002h
EVENT_OBJECT_HIDE               = 00008003h
EVENT_OBJECT_REORDER            = 00008004h
EVENT_OBJECT_FOCUS              = 00008005h
EVENT_OBJECT_SELECTION          = 00008006h
EVENT_OBJECT_SELECTIONADD       = 00008007h
EVENT_OBJECT_SELECTIONREMOVE    = 00008008h
EVENT_OBJECT_SELECTIONWITHIN    = 00008009h
EVENT_OBJECT_STATECHANGE        = 0000800ah
EVENT_OBJECT_LOCATIONCHANGE     = 0000800bh
EVENT_OBJECT_NAMECHANGE         = 0000800ch
EVENT_OBJECT_DESCRIPTIONCHANGE  = 0000800dh
EVENT_OBJECT_VALUECHANGE        = 0000800eh
EVENT_OBJECT_PARENTCHANGE       = 0000800fh
EVENT_OBJECT_HELPCHANGE         = 00008010h
EVENT_OBJECT_DEFACTIONCHANGE    = 00008011h
EVENT_OBJECT_ACCELERATORCHANGE  = 00008012h
EVENT_CONSOLE_CARET             = 00004001h
CONSOLE_CARET_SELECTION         = 00000001h
CONSOLE_CARET_VISIBLE           = 00000002h
EVENT_CONSOLE_UPDATE_REGION     = 00004002h
EVENT_CONSOLE_UPDATE_SIMPLE     = 00004003h
EVENT_CONSOLE_UPDATE_SCROLL     = 00004004h
EVENT_CONSOLE_LAYOUT            = 00004005h
EVENT_CONSOLE_START_APPLICATION = 00004006h
CONSOLE_APPLICATION_16BIT       = 00000001h
EVENT_CONSOLE_END_APPLICATION   = 00004007h
EVENT_MAX                       = 7fffffffh

WINEVENT_OUTOFCONTEXT   = 0000
WINEVENT_SKIPOWNTHREAD  = 0001
WINEVENT_SKIPOWNPROCESS = 0002
WINEVENT_INCONTEXT      = 0004
    


Description:
Download
Filename: hookTest.zip
Filesize: 1.43 KB
Downloaded: 241 Time(s)

Post 06 Jun 2015, 16:48
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.