I'm coding a smal utility that is intended to get the number of pixels of the selected area... For that I wanted something like this: You click your mouse button at a certain point, then a line is created at that point, as you drag your mouse the line goes following your cursor, once you release your mouse button the line size is calculated and showed to the user. I didn't manage to find any similar code on google... Drawing a static line isn't a problem, nor is geting the click and realease, I just can't figure how I would do this "dinamicaly".

By the way I'm using hooks to get the mouse input: mouse click, mouse release and mouse move, all of them has it's unique message (WM_MCLICK, WM_MUP, WM_MMOVE).
Posted on 2005-11-11 20:04:28 by Lenin
I'd say WM_LBUTTONDOWN, SetCapture until WM_LBUTTONUP where ReleaseCapture occurs.
On WM_MOUSEMOVE (If Capture is ON) count the difference
Posted on 2005-11-11 20:56:38 by JimmyClif
I had already thought of that method, but I don't see how it would work if the distance to be measured wan't horizontal or vertical. I wanted to use gdi because it would let user see the distance and I beleive that there might some way to get it's size. I really don't know if there's a formula I could use or something like that.
Posted on 2005-11-11 21:12:30 by Lenin
With GDI it will be the same thing - except you will be drawing a line starting from the point when WM_LBUTTONDOWN occured until the current position in WM_MOUSEMOVE.
Posted on 2005-11-12 05:16:31 by JimmyClif
Pythagora? (x2-x1)^2+(y2-y1)^2=length^2
imagine the line as a diagonal of a rectangle
Posted on 2005-11-12 09:15:14 by drizz
Seems to be a nice idea... But I don't know how to implement that... My code so far:

    pStart POINT <?>
    MCdown dd 0
    MCup dd 0
(...)
    .elseif uMsg==WM_MCDOWN
        cmp MCdown, 0
        jz @F
            mov MCdown, FALSE
            mov MCup, TRUE
            push wParam
            pop pStart.x
            push lParam
            pop pStart.y
        @@:
    .elseif uMsg==WM_MCUP
        cmp MCup, 0
        jz @F
            mov MCup, FALSE
            ; So now I would use that formula here, but how? I have the WM_MCDOWN cordinates (pStart.x, pStart.y)
            ; And the MC_UP ones (wParam, lParam)...
            invoke SetDlgItemText, hWnd, IDC_GETSIZE, CTXT("Get size")
        @@:
    .elseif uMsg==WM_COMMAND
mov eax, wParam
cmp ax, IDC_GETSIZE
jnz @F
    mov MCdown, TRUE
    invoke SetDlgItemText, hWnd, IDC_GETSIZE, CTXT("Click and drag your mouse")
@@:
(...)
Posted on 2005-11-12 14:08:05 by Lenin
Holy crap - You're right. Sorry... took me to this moment to realize for good why you mentionned horizontal & vertical.

Drizz, I'm off probably by far... (and out of school for a damn long time) but shouldn't it be a triangle and a^2+b^2=c^2 ?

If you know the starting position (x1,x2), and the ending position (x3,x4) -  oh I see.... (grin)

Pseudo-Code:

.IF x1 > x2
  sub x1, x2
  mov a, x1
.ELSE
  sub x2,x1
  mov a, x2
.ENDIF

.IF x3 > x4
  sub x3, x4
  mov b, x3
.ELSE
  sub x4,x3
  mov b, x4
.ENDIF

mul a * a
mul b * b
add a, b
mov c, a
sqrt(c) ; lenght of line.
Posted on 2005-11-12 17:09:59 by JimmyClif
there's no need to find out which one is bigger (or maybe my brain is sleeping).

mov eax, x2
sub eax, x1
mul eax  ;  a^2
mov ecx, eax
mov eax, y2
sub eax, y1
mul eax  ;  b^2
add eax, ecx  ; a^2 + b^2  ( c^2 )

sqrt(eax) :P
Posted on 2005-11-12 18:47:37 by ti_mo_n
My code is yelding pretty weird results... The weirdest thing is that there's no relation between the real number of pixels and the outputed one like:

real: 28px, outputed: 626px, direction: horizontal
real: 50px, outputed:500px, direction: horizontal
real: 45px, outputed:581px, direction: vertical
real: 74px, outputed:308px, direction: vertical
real: 29px, outputed:250px, direction: diagonal


    .elseif uMsg==WM_MCUP
        cmp MCup, 0
        jz @F
            mov MCup, FALSE
            invoke SetDlgItemText, hWnd, IDC_GETSIZE, CTXT("Get size")
           
            mov ecx, pStart.x
            .if ecx > pStart.y
                mov eax, pStart.x
                sub eax, pStart.y
            .else
                mov eax, pStart.y
                sub eax, pStart.x
            .endif
            mul eax ; a^2
            mov result, eax
           
            mov ecx, wParam
            .if ecx > lParam
                mov eax, wParam
                sub eax, lParam
            .else
                mov eax, lParam
                sub eax, wParam
            .endif
            mul eax ; b^2
            add result, eax ; c^2
            fild result
            fsqrt
            fist result
            fwait

            invoke wsprintf, addr buffer, addr template, result
            invoke MessageBox, hWnd, addr buffer, 0, MB_OK
        @@:


Of course that it could be a problem with my method to catch the cordinates, if needed I'll post the whole code.
Posted on 2005-11-12 19:59:11 by Lenin
Well, I don't know your code but regarding the lParam & the wParam's: Under WM_MOUSEMOVE & LBUTTONDOWN/UP the coordinates for x/y are located in lParamHi & lParamLo respectively. Maybe that's your error.

ti_mo_n: You're probably right - but shouldn't we use the abs(x) for each of the substractions to prevent negative numbers?
Posted on 2005-11-12 22:39:44 by JimmyClif
When you square any real numbers, they become positive.
Posted on 2005-11-12 23:04:41 by roticv

Well, I don't know your code but regarding the lParam & the wParam's: Under WM_MOUSEMOVE & LBUTTONDOWN/UP the coordinates for x/y are located in lParamHi & lParamLo respectively. Maybe that's your error.


I coded my DLL to pass me the x and y cordinates in wParam and lParam:

MouseProc proc nCode:DWORD,wParam:DWORD,lParam:DWORD
invoke CallNextHookEx,hHook,nCode,wParam,lParam
mov edx,lParam
assume edx:PTR MOUSEHOOKSTRUCT
.if wParam == WM_LBUTTONDOWN
    invoke PostMessage,hWnd,WM_MCDOWN,.pt.x,.pt.y
.elseif wParam == WM_LBUTTONUP
    invoke PostMessage,hWnd,WM_MCUP,.pt.x,.pt.y
.else
    invoke PostMessage,hWnd,WM_MOUSEMV,.pt.x,.pt.y
.endif
assume edx:nothing
xor eax,eax
ret
MouseProc endp
Posted on 2005-11-13 10:42:23 by Lenin
This appears to give me correct lenghts:


.data?
Startx dd ?
Starty dd ?
Endx dd ?
Endy dd ?
dummy dd ?
Capture dd ?
.code
WndProc proc uses ebx hwnd:DWORD,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
LOCAL rect:RECT
LOCAL ps:PAINTSTRUCT

    .IF uMsg==WM_CREATE
m2m hWnd, hwnd
;invoke OnCreate
.ELSEIF uMsg==WM_LBUTTONDOWN
invoke SetCapture,hWnd
mov Capture, TRUE
movzx eax, lParamL ; lParamL == WORD PTR
mov Startx, eax      ; lParamH == WORD PTR
movzx eax, lParamH
mov Starty, eax
.ELSEIF uMsg==WM_LBUTTONUP
invoke ReleaseCapture
mov Capture, FALSE
;Get line lenght

mov eax, Startx
mov edx, Endx
sub eax, edx
imul eax, eax
push eax

mov eax, Starty
mov edx, Endy
sub eax, edx
imul eax, eax

pop edx

add eax, edx

mov dummy, eax
finit
fild dummy
fsqrt
fistp dummy

PrintDec dummy

.ELSEIF uMsg==WM_MOUSEMOVE
.IF Capture == TRUE
movzx eax, lParamL
mov Endx, eax
movzx eax, lParamH
mov Endy, eax
invoke InvalidateRect,hWnd,0,TRUE
.ENDIF
.ELSEIF uMsg==WM_PAINT
.IF Capture == TRUE
invoke BeginPaint,hWnd,a$ ps
invoke GetStockObject,BLACK_PEN
push eax
invoke SelectObject,ps.hdc,eax
invoke MoveToEx,ps.hdc,Startx,Starty,NULL
invoke LineTo,ps.hdc,Endx,Endy
invoke EndPaint,hWnd,a$ ps
call DeleteObject
.ENDIF
    .ELSEIF uMsg==WM_DESTROY
invoke PostQuitMessage,0

    .ELSE
invoke DefWindowProc,hwnd,uMsg,wParam,lParam
ret
    .ENDIF
    xor eax,eax
    ret
WndProc endp
Posted on 2005-11-13 13:14:43 by JimmyClif
Thanks a lot :) For some weird reason after adapting my code (copy and pasting yours) my window became unresponsible... I'm pretty sure that it's because I'm handling WM_PAINT but I don't know how to fix it... Here's the code:

.386
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive

include windows.inc
include kernel32.inc
include user32.inc
include gdi32.inc
include \masm32\macros\macros.asm

includelib AutoClickDll.lib
includelib kernel32.lib
includelib user32.lib
includelib gdi32.lib

DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
InstallHook proto :DWORD
UninstallHook proto
MouseProc proto :DWORD,:DWORD,:DWORD

.const
    IDC_HOOK equ 12
    IDC_XPOINT equ 10
    IDC_YPOINT equ 11
    IDC_COLORBOX equ 12
    IDC_GETSIZE equ 13
    WM_MOUSEMV equ WM_USER+6
    WM_MCUP equ WM_USER+7
    WM_MCDOWN equ WM_USER+8
.data?
    rect RECT <?>
    ps PAINTSTRUCT <?>
    pStart POINT <?>
    pEnd POINT <?>
    result dd ?
    buffer db 50 dup(?)
.data
    template db "There are %lu pixels",0
    MCdown dd 0
    Capture dd 0
.code
start:
invoke GetModuleHandle, NULL
invoke DialogBoxParam, eax, 1, NULL, addr DlgProc, NULL
invoke ExitProcess, 0

DlgProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    .if uMsg==WM_PAINT
        .if Capture
            invoke BeginPaint,hWnd,addr ps
            invoke GetStockObject, BLACK_PEN
            push eax
            invoke SelectObject,ps.hdc,eax
            invoke MoveToEx,ps.hdc,pStart.x,pStart.y,NULL
            invoke LineTo,ps.hdc,pEnd.x,pEnd.y
            invoke EndPaint,hWnd,addr ps
            call DeleteObject
        .endif
    .elseif uMsg==WM_MOUSEMV
        invoke SetDlgItemInt, hWnd, IDC_XPOINT, wParam, FALSE
        invoke SetDlgItemInt, hWnd, IDC_YPOINT, lParam, FALSE
        .if Capture
            m2m pEnd.x, wParam
            m2m pEnd.y, lParam
            invoke InvalidateRect,hWnd,0,TRUE
        .endif
    .elseif uMsg==WM_MCUP
        mov Capture, FALSE
       
        mov eax, pStart.x
        mov edx, pEnd.x
        sub eax, edx
        imul eax, eax
       
        push eax
       
        mov eax, pStart.y
        mov edx, pEnd.y
        sub eax, edx
        imul eax, eax
       
        pop edx
        add eax, edx
        mov result, eax
       
        finit
        fild result
        fsqrt
        fistp result
       
        invoke wsprintf, addr buffer, addr template, result
        invoke MessageBox, hWnd, addr buffer, 0, MB_OK
    .elseif uMsg==WM_MCDOWN
        .if MCdown
            mov MCdown, FALSE
            mov Capture, TRUE
            m2m pStart.x, wParam
            m2m pStart.y, lParam
        .endif
    .elseif uMsg==WM_COMMAND
        mov eax, wParam
        .if ax==IDC_GETSIZE
            mov MCdown, TRUE
            invoke SetDlgItemText, hWnd, IDC_GETSIZE, CTXT("Click and drag your mouse")
        .endif       
    .elseif uMsg==WM_INITDIALOG
        invoke GetWindowRect,hWnd,addr rect
        invoke SetWindowPos,hWnd,HWND_TOPMOST,rect.left,rect.top,rect.right,rect.bottom,SWP_SHOWWINDOW

        invoke InstallHook, hWnd
    .elseif uMsg==WM_CLOSE
        invoke UninstallHook
        invoke EndDialog,hWnd,0
    .else
        mov eax,FALSE
        ret
.endif
mov eax,TRUE
ret
DlgProc endp

end start


I took away a few features I had implemented to see if they were causing the errors, but they weren't.
Posted on 2005-11-13 20:03:56 by Lenin
Maybe because your forgot the calls to SetCapture & ReleaseCapture. Try that.
Posted on 2005-11-13 20:45:29 by JimmyClif
Oh I'm using hooks... I tested using SetCapture but it only aplies to my window... Like I can't detect the mouse events when it's out of my window.

The main purpose of this project is help me to build resource files, so I can open a program , get it's sizes, controls' sizes etc... I'm also getting it's colors, just removed that of the code posted here. If I can't catch mouse events from others windows then my project is just a big waste of my time :P
Posted on 2005-11-13 20:58:48 by Lenin
How you're coming along there? All good? If you need to get rid of the WM_PAINT part just kick out the whole WM_PAINT handler and the call to InvalidateRect.

On another note, If you do what I think you're doing... Why not doing an enumeration of the selected window and list all the controls along with their sizes and colors?
Posted on 2005-11-14 15:39:37 by JimmyClif
I don't know exactly what you think I'm doing :P

I took away the line part as you said and now it's working, not that precise, but it's working. Still I will leave the code here hoping that some kind soul might make the line work :)

Thanks a lot Jimmy, I didn't expect some to build the whole code for me.

.386
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive

include windows.inc
include kernel32.inc
include user32.inc
include gdi32.inc
include \masm32\macros\macros.asm

includelib AutoClickDll.lib
includelib kernel32.lib
includelib user32.lib
includelib gdi32.lib

DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
InstallHook proto :DWORD
UninstallHook proto
MouseProc proto :DWORD,:DWORD,:DWORD

.const
    IDC_HOOK equ 12
    IDC_XPOINT equ 10
    IDC_YPOINT equ 11
    IDC_COLORBOX equ 12
    IDC_GETSIZE equ 13
    WM_MOUSEMV equ WM_USER+6
    WM_MCUP equ WM_USER+7
    WM_MCDOWN equ WM_USER+8
.data?
    BoxColor dd ?
    ColorBoxHwnd dd ?
    rect RECT <?>
    ps PAINTSTRUCT <?>
    pStart POINT <?>
    pEnd POINT <?>
    result dd ?
    buffer db 50 dup(?)
.data
    template db "There are %lu pixels",0
    MCdown dd 0
    Capture dd 0
.code
start:
invoke GetModuleHandle, NULL
invoke DialogBoxParam, eax, 1, NULL, addr DlgProc, NULL
invoke ExitProcess, 0

DlgProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    .if uMsg==WM_MOUSEMV
        invoke SetDlgItemInt, hWnd, IDC_XPOINT, wParam, FALSE
        invoke SetDlgItemInt, hWnd, IDC_YPOINT, lParam, FALSE

comment * ==========================================
        .if Capture
            m2m pEnd.x, wParam
            m2m pEnd.y, lParam
            invoke InvalidateRect,hWnd,0,TRUE
        .endif
    .elseif uMsg==WM_PAINT
        .if Capture
            invoke BeginPaint,hWnd,addr ps
            invoke GetStockObject, BLACK_PEN
            push eax
            invoke SelectObject,ps.hdc,eax
            invoke MoveToEx,ps.hdc,pStart.x,pStart.y,NULL
            invoke LineTo,ps.hdc,pEnd.x,pEnd.y
            invoke EndPaint,hWnd,addr ps
            call DeleteObject
        .endif
comment * ==========================================
    .elseif uMsg==WM_MCUP
        .if Capture
            mov Capture, FALSE
       
            m2m pEnd.x, wParam
            m2m pEnd.y, lParam
       
            mov eax, pStart.x
            mov edx, pEnd.x
            sub eax, edx
            imul eax, eax
       
            push eax
       
            mov eax, pStart.y
            mov edx, pEnd.y
            sub eax, edx
            imul eax, eax
           
            pop edx
            add eax, edx
            mov result, eax
       
            finit
            fild result
            fsqrt
            fistp result
           
            invoke wsprintf, addr buffer, addr template, result
            invoke MessageBox, hWnd, addr buffer, 0, MB_OK
            invoke SetDlgItemText, hWnd, IDC_GETSIZE, CTXT("Get Size")
        .endif
    .elseif uMsg==WM_MCDOWN
        .if MCdown
            mov MCdown, FALSE
            mov Capture, TRUE
            m2m pStart.x, wParam
            m2m pStart.y, lParam
        .endif
    .elseif uMsg==WM_COMMAND
        mov eax, wParam
        .if ax==IDC_GETSIZE
            mov MCdown, TRUE
            invoke SetDlgItemText, hWnd, IDC_GETSIZE, CTXT("Click and drag your mouse")
        .endif       
    .elseif uMsg==WM_INITDIALOG
        invoke GetWindowRect,hWnd,addr rect
        invoke SetWindowPos,hWnd,HWND_TOPMOST,rect.left,rect.top,rect.right,rect.bottom,SWP_SHOWWINDOW

        invoke InstallHook, hWnd
    .elseif uMsg==WM_CLOSE
        invoke UninstallHook
        invoke EndDialog,hWnd,0
    .else
        mov eax,FALSE
        ret
.endif
mov eax,TRUE
ret
DlgProc endp

end start
Posted on 2005-11-15 17:28:41 by Lenin