AutoHotkey Community

It is currently May 27th, 2012, 12:08 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: October 9th, 2009, 12:40 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
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 October 9th, 2009, 3:31 pm, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 9th, 2009, 2:59 pm 
Nice! It flickers like crazy though while dragging on XPSP3 and only works on the desktop :?


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 9th, 2009, 3:34 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
I've added an improved version using a simpler method (and added +AlwaysOnTop). See how that goes. :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 9th, 2009, 3:48 pm 
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


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 9th, 2009, 3:49 pm 
Oh sorry, yes, and it does draw on top of all windows now. :)


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 9th, 2009, 4:05 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
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...)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 9th, 2009, 4:32 pm 
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


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 10th, 2009, 2:21 am 
Offline

Joined: June 7th, 2008, 6:00 am
Posts: 389
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. ;).

Another very nicely written script! Two thumbs up.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Apollo, Rajat and 56 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group