AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

LetUserSelectRect - select a portion of the screen

 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Lexikos



Joined: 17 Oct 2006
Posts: 4726
Location: Australia

PostPosted: Fri Oct 09, 2009 12:40 pm    Post subject: LetUserSelectRect - select a portion of the screen Reply with quote

LetUserSelectRect(ByRef aX1, ByRef aY1, ByRef aX2, ByRef aY2)

Allows the user to select a rectangular region of the screen by clicking and dragging the mouse. The selected region is indicated by a red outline in real-time. Outputs the top-left (aX1, aY1) and bottom-right (aX2, aY2) co-ordinates of the rectangle.

It is based on an older script; functionized at vik.vega's request.

Code:
#NoEnv
CoordMode, Mouse ; Required: change coord mode to screen vs relative.
 
LetUserSelectRect(x1, y1, x2, y2)
MsgBox %x1%,%y1%  %x2%,%y2%

ExitApp
 
LetUserSelectRect(ByRef X1, ByRef Y1, ByRef X2, ByRef Y2)
{
    static r := 3
    ; Create the "selection rectangle" GUIs (one for each edge).
    Loop 4 {
        Gui, %A_Index%: -Caption +ToolWindow +AlwaysOnTop
        Gui, %A_Index%: Color, Red
    }
    ; Disable LButton.
    Hotkey, *LButton, lusr_return, On
    ; Wait for user to press LButton.
    KeyWait, LButton, D
    ; Get initial coordinates.
    MouseGetPos, xorigin, yorigin
    ; Set timer for updating the selection rectangle.
    SetTimer, lusr_update, 10
    ; Wait for user to release LButton.
    KeyWait, LButton
    ; Re-enable LButton.
    Hotkey, *LButton, Off
    ; Disable timer.
    SetTimer, lusr_update, Off
    ; Destroy "selection rectangle" GUIs.
    Loop 4
        Gui, %A_Index%: Destroy
    return
 
    lusr_update:
        MouseGetPos, x, y
        if (x = xlast && y = ylast)
            ; Mouse hasn't moved so there's nothing to do.
            return
        if (x < xorigin)
             x1 := x, x2 := xorigin
        else x2 := x, x1 := xorigin
        if (y < yorigin)
             y1 := y, y2 := yorigin
        else y2 := y, y1 := yorigin
        ; Update the "selection rectangle".
        Gui, 1:Show, % "NA X" x1 " Y" y1 " W" x2-x1 " H" r
        Gui, 2:Show, % "NA X" x1 " Y" y2-r " W" x2-x1 " H" r
        Gui, 3:Show, % "NA X" x1 " Y" y1 " W" r " H" y2-y1
        Gui, 4:Show, % "NA X" x2-r " Y" y1 " W" r " H" y2-y1
    lusr_return:
    return
}

Obsolete version:
Code:
#NoEnv
CoordMode, Mouse ; Required: change coord mode to screen vs relative.

LetUserSelectRect(x1, y1, x2, y2)
MsgBox %x1%,%y1%  %x2%,%y2%

LetUserSelectRect(ByRef aX1, ByRef aY1, ByRef aX2, ByRef aY2)
{
    ; Create red pen.
    redPen := DllCall("CreatePen", "int", 0, "int", 5, "uint", 0xff)
    ; Retrieve stock brush.
    blackBrush := DllCall("GetStockObject", "int", BLACK_BRUSH:=0x4)
    ; Create the "selection rectangle" GUI.
    Gui, -Caption +ToolWindow
    Gui, +LastFound
    WinSet, TransColor, Black
    ; Disable LButton.
    Hotkey, *LButton, lusr_return, On
    ; Wait for user to press LButton.
    KeyWait, LButton, D
    ; Get initial coordinates.
    MouseGetPos, xorigin, yorigin
    ; Set timer for updating the selection rectangle.
    SetTimer, lusr_update, 10
    ; Wait for user to release LButton.
    KeyWait, LButton
    ; Re-enable LButton.
    Hotkey, *LButton, Off
    ; Disable timer.
    SetTimer, lusr_update, Off
    ; Delete red pen.
    DllCall("DeleteObject", "uint", redPen)
    ; Destroy "selection rectangle" GUI.
    Gui, Destroy
    ; Set output parameters.
    if (x2 < xorigin)
         aX1 := x2, aX2 := xorigin
    else aX2 := x2, aX1 := xorigin
    if (y2 < yorigin)
         aY1 := y2, aY2 := yorigin
    else aY2 := y2, aY1 := yorigin
    return
   
    lusr_update:
        MouseGetPos, x2, y2
        if (x1 = x2 && y1 = y2)
            ; Mouse hasn't moved so there's nothing to do.
            return
        x1 := x2, y1 := y2
        ; Update the "selection rectangle" GUI.
        Gui, Show, % "NA X" . (x2<xorigin ? x2 : xorigin) . " Y" . (y2<yorigin ? y2 : yorigin)
                    . " W" . Abs(x2-xorigin) . " H" . Abs(y2-yorigin)
        Gui, +LastFound
        ; Get GDI device context for drawing.
        hdc := DllCall("GetDC", "uint", WinExist())
        ; Select pen and brush.
        oldPen := DllCall("SelectObject", "uint", hdc, "uint", redPen)
        oldBrush := DllCall("SelectObject", "uint", hdc, "uint", blackBrush)
        ; Draw rectangle.
        DllCall("Rectangle", "uint", hdc, "int", 0, "int", 0, "int", Abs(x2-xorigin), "int", Abs(y2-yorigin))
        ; Reselect original pen and brush (required for proper cleanup).
        DllCall("SelectObject", "uint", hdc, "uint", oldPen)
        DllCall("SelectObject", "uint", hdc, "uint", oldBrush)
        ; Clean up.
        DllCall("ReleaseDC", "uint", WinExist(), "uint", hdc)
    lusr_return:
    return
}


Last edited by Lexikos on Fri Oct 09, 2009 3:31 pm; edited 2 times in total
Back to top
View user's profile Send private message Visit poster's website
n-l-i-d
Guest





PostPosted: Fri Oct 09, 2009 2:59 pm    Post subject: Reply with quote

Nice! It flickers like crazy though while dragging on XPSP3 and only works on the desktop Confused
Back to top
Lexikos



Joined: 17 Oct 2006
Posts: 4726
Location: Australia

PostPosted: Fri Oct 09, 2009 3:34 pm    Post subject: Reply with quote

I've added an improved version using a simpler method (and added +AlwaysOnTop). See how that goes. Smile
Back to top
View user's profile Send private message Visit poster's website
n-l-i-d
Guest





PostPosted: Fri Oct 09, 2009 3:48 pm    Post subject: Reply with quote

Much better! No flickering, and still low cpu usage. I do see artifacts from redrawing (lines stick out of the rectangle) along the corners of the rectangle while resizing.

HTH
Back to top
n-l-i-d
Guest





PostPosted: Fri Oct 09, 2009 3:49 pm    Post subject: Reply with quote

Oh sorry, yes, and it does draw on top of all windows now. Smile
Back to top
Lexikos



Joined: 17 Oct 2006
Posts: 4726
Location: Australia

PostPosted: Fri Oct 09, 2009 4:05 pm    Post subject: Reply with quote

n-l-i-d wrote:
I do see artifacts from redrawing
That's typical for Windows before desktop composition (Aero) was introduced. Actually, making the GUIs partially transparent might help (it'd have a similar effect), but would probably slow it down a bit.
Quote:
it does draw
Well, not really. It creates four windows, AutoHotkey paints them red and Windows is responsible for (in)correctly redrawing other windows as the four move around. (You could say it spills the red paint...)
Back to top
View user's profile Send private message Visit poster's website
n-l-i-d
Guest





PostPosted: Fri Oct 09, 2009 4:32 pm    Post subject: Reply with quote

Using SetBatchLines 0 and SetWinDelay 0 helps. I think it could be "solved" if the order of moving/resizing of the guis depended on the directions of the drag. If the most-outer side/gui moves last if contracting and first if expanding (before/after the respective sides), the effect is hardly visible anymore.

HTH
Back to top
Wicked



Joined: 07 Jun 2008
Posts: 223

PostPosted: Sat Oct 10, 2009 2:21 am    Post subject: Reply with quote

You pwned my version of it (Which I'm sure you saw on the other thread in 'Ask For Help'). Every time I write one, you guys out do me. Well, not for long. Muahahahahaha. Wink.

Another very nicely written script! Two thumbs up.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group