Jump to content
Sign in to follow this  
spudw2k

MouseRegion

Recommended Posts

spudw2k

Some simple code I made to implement into ludocus' Webcam Security Guard script to allow the select of a region instead of a hardcoded one. Suggestions encouraged.

While 1
    $region = _GetMouseRegion() ;Captures Region as Array ([0][0-1]=Start X&Y  [1][0-1]=End X&Y  [2][0-1]=Distance Between
    $box = _RegionToBox($region) ;Converts Region Array into Top,Left,Width,Height
    $gui = GuiCreate($box[1][0] & " X " & $box[1][1],$box[1][0],$box[1][1],$box[0][0],$box[0][1],0)
    $exitbtn = GUICtrlCreateButton("Exit",0,0,$box[1][0]-6,$box[1][1]-32)
    GUISetState()

    While 1
        $msg = GUIGetMsg()
        If $msg = -3 Or $msg = $exitbtn Then Exit
    WEnd
    GuiDelete()
Wend

Func _StartDrag($dll)
    Do
        sleep(10)
    Until _IsPressed(1,$dll)
    Return MouseGetPos()
EndFunc

Func _FinishDrag($dll,$start,$flags=3)
    While _IsPressed(1,$dll)
        $current = MouseGetPos()
        If BitOR($flags,1) = $flags Then _ShowRegionStats($start,$current)
        If BitOR($flags,2) = $flags Then _ShowRegionHighlight($start,$current)
    WEnd
    ToolTip("")
    Return MouseGetPos()
EndFunc

Func _GetMouseRegion()
    $dll = DllOpen("user32.dll")
    $start = _StartDrag($dll)
    $finish = _FinishDrag($dll,$start)
    DllClose($dll)
    Dim $box[3][2]
    For $i = 0 to 2
        For $x = 0 to 1
            If $i = 0 Then
                $box[$i][$x] = $start[$x]
            ElseIf $i = 1 Then
                $box[$i][$x] = $finish[$x]
            Else
                $box[$i][$x] = $finish[$x] - $start[$x]
            EndIf
        Next
    Next
    Return $box
EndFunc

Func _RegionToBox($region)
    If Not IsArray($region) Then Return 0
    Dim $box[2][2]
    If $region[2][0] < 0 Then
        $box[0][0] = $region[1][0]
    Else
        $box[0][0] = $region[0][0]
    EndIf
    If $region[2][1] < 0 Then
        $box[0][1] = $region[1][1]
    Else
        $box[0][1] = $region[0][1]
    EndIf
    $box[1][0] = Abs($region[2][0])
    $box[1][1] = Abs($region[2][1])
    Return $box
EndFunc

Func _ShowRegionStats($start,$current)
    If $start[0] > $current[0] And $start[1] <> $current[1] Then
        ToolTip("X:" & $start[0] & @TAB & "X:" & $current[0] & @CRLF & "Y:" & $start[1] & @TAB & "Y:" & $current[1] & @CRLF & @CRLF & "Width = " & Abs($current[0]-$start[0]) & @CRLF & "Height = " & Abs($current[1]-$start[1]),$current[0]-74,$current[1]-70)
    ElseIf $start[0] < $current[0] And $start[1] <> $current[1] Then
        ToolTip("X:" & $start[0] & @TAB & "X:" & $current[0] & @CRLF & "Y:" & $start[1] & @TAB & "Y:" & $current[1] & @CRLF & @CRLF & "Width = " & Abs($current[0]-$start[0]) & @CRLF & "Height = " & Abs($current[1]-$start[1]),$current[0],$current[1])
    EndIf
EndFunc

Func _ShowRegionHighlight($start,$current)
    $hd = DllCall("user32.dll", "int", "GetDC", "hwnd", 0)
    $pen = DllCall("gdi32.dll", "int", "CreatePen", "int", 0, "int", 1, "int", 0x0000ff)
    DllCall("gdi32.dll", "int", "SelectObject", "int", $hd[0], "int", $pen[0])
    
    DllCall("GDI32.dll", "int", "MoveToEx", "hwnd", $hd[0], "int",$start[0], "int", $start[1], "int", 0)
    DllCall("GDI32.dll", "int", "LineTo", "hwnd", $hd[0], "int", $start[0], "int", $current[1])
    ;DllCall("GDI32.dll", "int", "LineTo", "hwnd", $hd[0], "int", $current[0], "int", $start[1])
    
    DllCall("GDI32.dll", "int", "MoveToEx", "hwnd", $hd[0], "int",$current[0], "int", $start[1], "int", 0)
    DllCall("GDI32.dll", "int", "LineTo", "hwnd", $hd[0], "int", $current[0], "int", $current[1])
    ;DllCall("GDI32.dll", "int", "LineTo", "hwnd", $hd[0], "int", $start[0], "int", $start[1])
    
    DllCall("GDI32.dll", "int", "MoveToEx", "hwnd", $hd[0], "int",$current[0], "int", $current[1], "int", 0)
    DllCall("GDI32.dll", "int", "LineTo", "hwnd", $hd[0], "int", $start[0], "int", $current[1])
    
    DllCall("GDI32.dll", "int", "MoveToEx", "hwnd", $hd[0], "int",$start[0], "int", $start[1], "int", 0)
    DllCall("GDI32.dll", "int", "LineTo", "hwnd", $hd[0], "int", $current[0], "int", $start[1])

    DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "int", $hd[0])

    sleep(50)
EndFunc

Func _IsPressed($sHexKey, $vDLL = 'user32.dll')
    Local $a_R = DllCall($vDLL, "int", "GetAsyncKeyState", "int", '0x' & $sHexKey)
    If Not @error And BitAND($a_R[0], 0x8000) = 0x8000 Then Return 1
    Return 0
EndFunc

edit: Updated code. Removed includes and added region to box method and test routine which loops unless exit button is pressed.

I'm not very good with the GDI stuff, but I'll try to implement some feature that will draw the region as it is being selected. I'll use a bit flag in the _ShowRegionStats func to support both the GDI and tooltip featues.

edit: added GDI+ to draw box where region is being selected. Sorry it's messy. Not sure how to cleanup the GDI lines.

Edited by spudw2k

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×