 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Plastic Guest
|
Posted: Sun Mar 09, 2008 8:35 pm Post subject: |
|
|
As per SKAN suggestion I am posting my working iteration of this. I have the computations (I think) down... however, even though the data is clean as you can see by the results, the GUI is locked frozen and does not re-compute based on XX.. anyone see why and can fix or make this work? I am not sure I understand the advanced hooks or stuff (like WM_WINDOWPOSCHANGING), but maybe someone can see a path to success from this.
here it is,
| Code: |
INPUT_WIDTH=425
INPUT_HEIGHT=496
FixedMinProportion=300
Gosub, Calculate
MsgBox, This 425x496 Input Would Scale Properly To %FixedMinProportion%x%OutPutHeightSize%
; CONTINUE TO GUI
;
;; :)
Gui +Resize +MinSize300x351 +MaxSize425x496
Gui, Show, w300 h351
Return
GuiSize:
INPUT_WIDTH=%A_GuiWidth%
INPUT_HEIGHT=%A_GuiHeight%
FixedMinProportion=300
Gosub, Calculate
ToolTip, INPUT: %INPUT_WIDTH% x %INPUT_HEIGHT% | OUTPUT: %FixedMinProportion% x %OutPutHeightSize%
Gui, Show,,RESIZER V1.0
Return
Calculate:
; CALCULATE PROPORTIONS
if (FixedMinProportion="") {
if (OutPutHeightSize)
FixedMinProportion:=ceil(OutPutHeightSize*INPUT_WIDTH/INPUT_HEIGHT)
else FixedMinProportion:=INPUT_WIDTH
}
if (OutPutHeightSize="") {
if (FixedMinProportion)
OutPutHeightSize:=ceil(FixedMinProportion*INPUT_HEIGHT/INPUT_WIDTH)
else OutPutHeightSize:=INPUT_HEIGHT
}
Return
GuiClose:
ExitApp
|
|
|
| Back to top |
|
 |
Plastic Guest
|
Posted: Wed Mar 12, 2008 6:13 am Post subject: |
|
|
(bump)
Could someone who is knowledgeable with these system calls please help me? |
|
| Back to top |
|
 |
PE0N Guest
|
Posted: Fri Mar 21, 2008 3:23 pm Post subject: |
|
|
Can somebody try to take a crack at this? ...  |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 388
|
Posted: Wed Apr 02, 2008 10:28 am Post subject: |
|
|
I went in a little bit of a different direction. This seems to work reasonably well. It will keep the original aspect ratio of the gui.
For this to work, the gui can't be sizable.
| Code: | SetBatchLines, -1
SetWinDelay,10
fudgeFactor = 3 ;makes the border area larger for easier dragging, seems to be needed on the bottom border
GuiMinSize=300x351
GuiMaxSize=425x496
IDC_SIZEWE = 32644
IDC_SIZENS = 32645
SysGet, SM_CXFIXEDFRAME, 7
SysGet, SM_CYFIXEDFRAME, 8
leftBorder := SM_CXFIXEDFRAME + fudgeFactor
topBorder := SM_CYFIXEDFRAME + fudgeFactor
WM_MOUSEMOVE = 0x200
WM_LBUTTONDOWN = 0x201
Gui -Resize +MaximizeBox +LastFound
guiID := WinExist()
Gui, Show, w300 h351
WinGetPos,,,winW, winH
hProp := winH / winW ;multiply the current width by hProp to get the new height
wProp := winW / winH ;multiply the current height by wProp to get the new width
WEcursor := DllCall("LoadCursor", "Uint", 0, "Int", IDC_SIZEWE) ;load west-east cursor
NScursor := DllCall("LoadCursor", "Uint", 0, "Int", IDC_SIZENS) ;load north-south cursor
StringSplit, guiMin, GuiMinSize, x ;guiMin1 is width ;guiMin2 is height
StringSplit, guiMax, GuiMaxSize, x ;guiMax1 is width ;guiMax2 is height
OnMessage(WM_MOUSEMOVE, "CheckDrag")
OnMessage(WM_LBUTTONDOWN, "CheckDrag")
Return
;need to make left and top border work.
;for left, have to make x smaller while making w larger.
CheckDrag(wparam, lparam, msg, hwnd)
{
global
MouseGetPos, mX, mY
WinGetPos, oX, oY, oW, oH, ahk_id %guiID%
rightBorder := oW - SM_CXFIXEDFRAME - fudgeFactor
bottomBorder := oH - SM_CYFIXEDFRAME - fudgeFactor
If(mX < leftBorder)
{ DllCall("SetCursor", "uint", WEcursor) ;set west-east cursor
direction = W
SetTimer, sizer, 0
}
Else If(mX >= rightBorder)
{ DllCall("SetCursor", "uint", WEcursor) ;set west-east cursor
direction = E
SetTimer, sizer, 0
}
Else If(mX < topBorder)
{ DllCall("SetCursor", "uint", NScursor) ;set north-south cursor
direction = N
SetTimer, sizer, 0
}
Else If(mY > bottomBorder)
{ DllCall("SetCursor", "uint", NScursor) ;set north-south cursor
direction = S
SetTimer, sizer, 0
}
}
sizer:
Critical
If GetKeyState("LButton","P")
{ CoordMode, MOUSE, SCREEN
MouseGetPos, moveX, moveY
If(direction = "W") ;dragging left border ******DOES NOT WORK*****
{ DllCall("SetCursor", "uint", WEcursor) ;set west-east cursor
newW := oX - moveX
newH := newW * hProp
}
Else If(direction = "E") ;dragging right border
{ DllCall("SetCursor", "uint", WEcursor) ;set west-east cursor
newW := moveX - oX
newW := newW < guiMin1 ? guiMin1 : newW ;make sure its not smaller than minimum
newW := newW > guiMax1 ? guiMax1 : newW ;make sure its not bigger than maximum
newH := newW * hProp
moveX := moveX > oX + guiMax1 ? oX + guiMax1 : moveX ;keep mouse within max
moveX := moveX < oX + guiMin1 ? oX + guiMin1 : moveX ;keep mouse within min
}
Else If(direction = "N") ;dragging top border ******DOES NOT WORK*****
{ DllCall("SetCursor", "uint", NScursor) ;set north-south cursor
newH := oY - moveY
newH := newH < guiMin2 ? guiMin2 : newH ;make sure its not smaller than minimum
newH := newH > guiMax2 ? guiMax2 : newH ;make sure its not bigger than maximum
newW := newH * wProp
}
Else If(direction = "S") ;dragging bottom border
{ DllCall("SetCursor", "uint", NScursor) ;set north-south cursor
newH := moveY - oY
newH := newH < guiMin2 ? guiMin2 : newH ;make sure its not smaller than minimum
newH := newH > guiMax2 ? guiMax2 : newH ;make sure its not bigger than maximum
newW := newH * wProp
moveY := moveY > oY + guiMax2 ? oY + guiMax2 : moveY ;keep mouse within max
moveY := moveY < oY + guiMin2 ? oY + guiMin2 : moveY ;keep mouse within min
}
MouseMove, moveX, moveY
WinMove, ahk_id %guiID%,,,, %newW%, %newH%
}
Else
{ SetTimer, sizer, Off
}
Return
guiClose:
ExitApp
Return | At this point, the left and top border drag don't work.
HTH _________________

Last edited by Micahs on Wed Apr 02, 2008 11:46 pm; edited 1 time in total |
|
| Back to top |
|
 |
LST103 Guest
|
Posted: Wed Apr 02, 2008 5:48 pm Post subject: |
|
|
Hey - that is pretty neat. Just curious, I played with it a little and noticed it was a tiny bit choppy --- can that be made any smoother on-size, or is this a factor of Windows or maybe my pc machine?  |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 388
|
Posted: Wed Apr 02, 2008 11:20 pm Post subject: |
|
|
I just added "SetWinDelay,10" and it works quite a bit smoother. I tried to add "Critical" to the "sizer" routine, but it didn't seem to make much difference. There might be some other optimizations also.
And now the mouse is constrained to the min and max gui sizes. _________________
 |
|
| Back to top |
|
 |
Rhys
Joined: 17 Apr 2007 Posts: 758 Location: Florida
|
Posted: Thu Apr 03, 2008 4:02 pm Post subject: |
|
|
Here's my 2c:
Since you're defining a set aspect ratio, you don't need to have a height / width control (since there's really only one variable - size).
Because size is also constrained to a minimum and maximum, why not control it with a slide control in the GUI itself?
Edit: | Code: | ratio:=.66666
w:=300
h:=w * ratio
gui, add, Slider, gSlide vW Range300-600 AltSubmit,300
gui, show, w%w% h%h%
Return
GuiClose:
ExitApp
;Reload
Return
Slide:
;Tooltip, %W% ;For testing
h:=w * ratio
gui, show, w%w% h%h%
Return | Edit2: I started working on a version that allows sizing via the normal controls, but I have to go home and I have tomorrow off, so here's what I've got so far: | Code: | ratio:=1.1666666666666666666666666666667
w:=300
h:=w * ratio
gui, +resize +maxsize425x496
gui, add, Slider, gSlide vW Range300-425 AltSubmit,300
gui, show, w%w% h%h%
Return
GuiClose:
ExitApp
;Reload
Return
Slide:
;Tooltip, %W%
h:=w * ratio
gui, show, w%w% h%h%
Return
GuiSize:
If !(A_EventInfo)
{ If((A_GuiWidth / A_GuiHeight) > Ratio)
}
Return |
_________________ [Join IRC!]
 |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 388
|
Posted: Fri Apr 04, 2008 12:22 am Post subject: |
|
|
As for the slider control:
Plastic might be happy with that. But I don't think that was the original intent. I thought that he wanted the gui to be sized normally, but with a fixed aspect ratio. If Plastic is happy, so am I.
| Rhys wrote: | | you don't need to have a height / width control | I don't technically use a control to do the sizing.
| Rhys wrote: | | allows sizing via the normal controls | What do you mean? The standard window border drag for sizing? If so, you will run into some problems with dragging while resizing the gui manually (that's why I went the route I did.) Also, you have to keep track of which border they are dragging. For instance, the left border - you have to move the gui x position as well as the width. Each border has its own requirements. That's the reason I don't think: | Rhys wrote: | | there's really only one variable - size | There's more to keep track of than just size. _________________
 |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 388
|
Posted: Sat Apr 05, 2008 7:29 am Post subject: |
|
|
This is what I have so far. It offers fixed ratio resizing and min/max. It works very well on my 950Mhz machine using only the "WM_SIZING" message. The only resize borders I have implemented are Right, Bottom, and Bottom-Right. There is a problem that I can't find right now and I am holding off adding the rest of the sides until I fix it.
When you resize (only the Right, Bottom, and Bottom-Right), the minimum constraint seems to work, but the max doesn't work right. If you drag it with the bottom border all the way to the maximum and then try to drag with the right border, it will resize a little more. The max is not consistent between the different sides. Does anyone see what I am missing? I'm tired, so its probably something stupid!
| Code: | ;Thread that I took the original code from: http://www.autohotkey.com/forum/viewtopic.php?t=2441
;Uses Anchor 4.60a by Titan
;~ _minSize = 300x200 ;if this is not specified, the min w,h will be the initial gui size
_maxSize = 500x400
SetBatchLines,150ms
SetWinDelay, 0
Gui +Resize +LastFound
guiID := WinExist()
Gui, Add, Edit, w300 h200 vg1Edit, Hello
Gui, Add, Button, vg1Ok, Ok
Gui, Add, Button, x+ yp vg1Exit, Exit
Gui, Add, Button, x+ yp vg1Close, Close
Gui, Show,, MinMax & AutoRatio
WinGetPos,,,guiW, guiH, ahk_id %guiID% ;get gui w,h and calc the size ratio
_hProp := guiH / guiW ;multiply the current width by _hProp to get the new height
_wProp := guiW / guiH ;multiply the current height by _wProp to get the new width
If(_minSize) ;only do this if minimum specified
{ StringSplit, _min, _minSize, x ;_min1 is width ;_min2 is height
}
Else ;min not given - use gui w,h for minimum
{ _min1 := guiW ;set the minimum width = initial gui width
_min2 := guiH ;set the minimum height = initial gui height
}
StringSplit, _max, _maxSize, x ;_max1 is width ;_max2 is height
OnMessage(0x214,"WM_SIZING")
Return
GuiClose:
ExitApp
Return
GuiSize:
anchor("g1Edit","wh")
anchor("g1Ok","y")
anchor("g1Exit","y")
anchor("g1Close","y")
Return
WM_SIZING(wParam,lParam,msg)
{
global guiID, _wProp, _hProp, _min1, _min2, _max1, _max2
WM_SIZING_Edge:=wParam
WinGetPos,CurrX,CurrY,CurrW,CurrH,ahk_id %guiID% ;Get current W/H
CoordMode, MOUSE, SCREEN
MouseGetPos, mX, mY
If WM_SIZING_Edge in 2,8 ;right and bottom-right border drag - keep within min and max, keep aspect ratio
{ newWcoord := mX < CurrX + _min1 ? CurrX + _min1 : mX ;make sure width isn't smaller than min
newWcoord := newWcoord > CurrX + _max1 ? CurrX + _max1 : newWcoord ;make sure width isn't larger than max
InsertIntegerAtAddress(newWcoord,lParam,8,4) ;set x coord of right side of gui
newHcoord := CurrY + (CurrW * _hProp) ;get the new height
InsertIntegerAtAddress(newHcoord,lParam,12,4) ;set y coord of bottom side of gui
}
If(WM_SIZING_Edge = 6) ;bottom border drag - keep within min and max, keep aspect ratio
{ newHcoord := mY < CurrY + _min2 ? CurrY + _min2 : mY ;make sure height isn't smaller than min
newHcoord := newHcoord > CurrY + _max2 ? CurrY + _max2 : newHcoord ;make sure height isn't larger than max
InsertIntegerAtAddress(newHcoord,lParam,12,4) ;set y coord of bottom side of gui
newWcoord := CurrX + (CurrH * _wProp) ;get the new width
InsertIntegerAtAddress(newWcoord,lParam,8,4) ;set x coord of right side of gui
}
;TODO - Top, Top-Right, Top-Left, Left, Left-Bottom - these will require modifing the x,y coords too.
return true
/*
From MSDN (with edits):
lParam - RECT Structure containing window coords
typedef struct _RECT {
LONG left; (0) offset in structure
LONG top; (4)
LONG right; (8)
LONG bottom; (12)
} RECT, *PRECT;
wParam - Specifies which edge of the window is being sized. This
parameter can be one of the following values.
WMSZ_LEFT (1) Left edge
WMSZ_RIGHT (2) Right edge
WMSZ_TOP (3) Top edge
WMSZ_TOPLEFT (4) Top-left corner
WMSZ_TOPRIGHT (5) Top-right corner
WMSZ_BOTTOM (6) Bottom edge
WMSZ_BOTTOMLEFT (7) Bottom-left corner
WMSZ_BOTTOMRIGHT (8) Bottom-right corner
*/
}
InsertIntegerAtAddress(pInteger, pAddress, pOffset = 0, pSize = 4) ;update this to putnum
{
mask := 0xFF ; This serves to isolate each byte, one by one.
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
{
DllCall("RtlFillMemory", UInt, pAddress + pOffset + A_Index - 1, UInt, 1
, UChar, (pInteger & mask) >> 8 * (A_Index - 1))
mask := mask << 8 ; Set it up for isolation of the next byte.
}
}
/*
Function: Anchor
Defines how controls should be automatically positioned relative to the new dimensions of a window when resized.
Parameters:
cl - a control HWND, associated variable name or ClassNN to operate on
a - (optional) one or more of the anchors: 'x', 'y', 'w' (width) and 'h' (height),
optionally followed by a relative factor, e.g. "x h0.5"
r - (optional) true to redraw controls, recommended for GroupBox and Button types
Examples:
> "xy" ; bounds a control to the bottom-left edge of the window
> "w0.5" ; any change in the width of the window will resize the width of the control on a 2:1 ratio
> "h" ; similar to above but directrly proportional to height
Remarks:
To assume the current window size for the new bounds of a control (i.e. resetting) simply omit the second and third parameters.
However if the control had been created with DllCall() and has its own parent window,
the container AutoHotkey created GUI must be made default with the +LastFound option prior to the call.
For a complete example see anchor-example.ahk.
License:
- Version 4.60a by Titan <http://www.autohotkey.net/~Titan/#anchor>
- GNU General Public License 3.0 or higher <http://www.gnu.org/licenses/gpl-3.0.txt>
*/
Anchor(i, a = "", r = false) {
static c, cs = 12, cx = 255, cl = 0, g, gs = 8, gl = 0, gpi, gw, gh, z = 0, k = 0xffff
If z = 0
VarSetCapacity(g, gs * 99, 0), VarSetCapacity(c, cs * cx, 0), z := true
If (!WinExist("ahk_id" . i)) {
GuiControlGet, t, Hwnd, %i%
If ErrorLevel = 0
i := t
Else ControlGet, i, Hwnd, , %i%
}
VarSetCapacity(gi, 68, 0), DllCall("GetWindowInfo", "UInt", gp := DllCall("GetParent", "UInt", i), "UInt", &gi)
, giw := NumGet(gi, 28, "Int") - NumGet(gi, 20, "Int"), gih := NumGet(gi, 32, "Int") - NumGet(gi, 24, "Int")
If (gp != gpi) {
gpi := gp
Loop, %gl%
If (NumGet(g, cb := gs * (A_Index - 1)) == gp) {
gw := NumGet(g, cb + 4, "Short"), gh := NumGet(g, cb + 6, "Short"), gf := 1
Break
}
If (!gf)
NumPut(gp, g, gl), NumPut(gw := giw, g, gl + 4, "Short"), NumPut(gh := gih, g, gl + 6, "Short"), gl += gs
}
ControlGetPos, dx, dy, dw, dh, , ahk_id %i%
Loop, %cl%
If (NumGet(c, cb := cs * (A_Index - 1)) == i) {
If a =
{
cf = 1
Break
}
giw -= gw, gih -= gh, as := 1, dx := NumGet(c, cb + 4, "Short"), dy := NumGet(c, cb + 6, "Short")
, cw := dw, dw := NumGet(c, cb + 8, "Short"), ch := dh, dh := NumGet(c, cb + 10, "Short")
Loop, Parse, a, xywh
If A_Index > 1
av := SubStr(a, as, 1), as += 1 + StrLen(A_LoopField)
, d%av% += (InStr("yh", av) ? gih : giw) * (A_LoopField + 0 ? A_LoopField : 1)
DllCall("SetWindowPos", "UInt", i, "Int", 0, "Int", dx, "Int", dy
, "Int", InStr(a, "w") ? dw : cw, "Int", InStr(a, "h") ? dh : ch, "Int", 4)
If r != 0
DllCall("RedrawWindow", "UInt", i, "UInt", 0, "UInt", 0, "UInt", 0x0101) ; RDW_UPDATENOW | RDW_INVALIDATE
Return
}
If cf != 1
cb := cl, cl += cs
bx := NumGet(gi, 48), by := NumGet(gi, 16, "Int") - NumGet(gi, 8, "Int") - gih - NumGet(gi, 52)
If cf = 1
dw -= giw - gw, dh -= gih - gh
NumPut(i, c, cb), NumPut(dx - bx, c, cb + 4, "Short"), NumPut(dy - by, c, cb + 6, "Short")
, NumPut(dw, c, cb + 8, "Short"), NumPut(dh, c, cb + 10, "Short")
Return, true
}
|
_________________
 |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 388
|
Posted: Sat Apr 05, 2008 8:51 am Post subject: |
|
|
All right, I got it! The fixed ratio and min/max all work correctly now.
| Code: | ;Thread that I got "InsertIntegerAtAddress" and "WM_SIZING" info from: http://www.autohotkey.com/forum/viewtopic.php?t=2441
;Uses Anchor 4.60a by Titan
_minWidth = 200 ;specify either minWidth, minHeight, or none. If none, initial gui w,h is used. - minWidth overrides minHeight
_minHeight =
_maxWidth = 500 ;specify either maxWidth, maxHeight, or none - maxWidth overrides maxHeight
_maxHeight =
SetBatchLines,150ms
SetWinDelay, 0
SysGet, SM_CXMAXTRACK, 59 ;get largest window size
SysGet, SM_CYMAXTRACK, 60
Gui +Resize +LastFound
guiID := WinExist()
Gui, Add, Edit, w300 h200 vg1Edit, Hello
Gui, Add, Button, vg1Ok, Ok
Gui, Add, Button, x+ yp vg1Exit, Exit
Gui, Add, Button, x+ yp vg1Close, Close
Gui, Show,, MinMax & AutoRatio
WinGetPos,,,guiW, guiH, ahk_id %guiID% ;get gui w,h and calc the size ratio
_hProp := guiH / guiW ;multiply the current width by _hProp to get the new height
_wProp := guiW / guiH ;multiply the current height by _wProp to get the new width
If(_minWidth) ;this sets the vars for max w,h to keep aspect ratio
{ _min1 := _minWidth ;this is the width
_min2 := _minWidth * _hProp ;this is the height
}
Else If(_minHeight) ;_minHeight given
{ _min1 := _minHeight * _wProp ;this is the width
_min2 := _minHeight ;this is the height
}
Else ;no min given
{ _min1 := guiW ;set min w,h = initial gui w,h
_min2 := guiH
}
If(_maxWidth) ;this sets the vars for max w,h to keep aspect ratio
{ _max1 := _maxWidth ;this is the width
_max2 := _maxWidth * _hProp ;this is the height
}
Else If(_maxHeight) ;_maxHeight given
{ _max1 := _maxHeight * _wProp ;this is the width
_max2 := _maxHeight ;this is the height
}
Else ;no max given
{ _max1 := SM_CXMAXTRACK ;largest window possible in system
_max2 := SM_CYMAXTRACK
}
OnMessage(0x214,"WM_SIZING")
Return
GuiClose:
ExitApp
Return
GuiSize:
anchor("g1Edit","wh")
anchor("g1Ok","y")
anchor("g1Exit","y")
anchor("g1Close","y")
Return
WM_SIZING(wParam, lParam, msg)
{
global guiID, _wProp, _hProp, _min1, _min2, _max1, _max2
WM_SIZING_Edge := wParam
WinGetPos, CurrX, CurrY, CurrW, CurrH, ahk_id %guiID% ;Get current W/H
CoordMode, MOUSE, SCREEN
MouseGetPos, mX, mY
If WM_SIZING_Edge in 2,8 ;right and bottom-right border drag - keep within min and max, keep aspect ratio
{ newWcoord := mX < CurrX + _min1 ? CurrX + _min1 : mX ;make sure width isn't smaller than min
newWcoord := newWcoord > CurrX + _max1 ? CurrX + _max1 : newWcoord ;make sure width isn't larger than max
InsertIntegerAtAddress(newWcoord, lParam, 8, 4) ;set x coord of right side of gui
newHcoord := CurrY + (CurrW * _hProp) ;get the new height
InsertIntegerAtAddress(newHcoord, lParam, 12, 4) ;set y coord of bottom side of gui
}
If(WM_SIZING_Edge = 6) ;bottom border drag - keep within min and max, keep aspect ratio
{ newHcoord := mY < CurrY + _min2 ? CurrY + _min2 : mY ;make sure height isn't smaller than min
newHcoord := newHcoord > CurrY + _max2 ? CurrY + _max2 : newHcoord ;make sure height isn't larger than max
InsertIntegerAtAddress(newHcoord, lParam, 12, 4) ;set y coord of bottom side of gui
newWcoord := CurrX + (CurrH * _wProp) ;get the new width
InsertIntegerAtAddress(newWcoord, lParam, 8, 4) ;set x coord of right side of gui
}
;TODO - Top, Top-Right, Top-Left, Left, Left-Bottom - these will require modifing the x,y coords too.
return true
/*
From MSDN (with edits):
lParam - RECT Structure containing window coords
typedef struct _RECT {
LONG left; (0) offset in structure
LONG top; (4)
LONG right; (8)
LONG bottom; (12)
} RECT, *PRECT;
wParam - Specifies which edge of the window is being sized. This
parameter can be one of the following values.
WMSZ_LEFT (1) Left edge
WMSZ_RIGHT (2) Right edge
WMSZ_TOP (3) Top edge
WMSZ_TOPLEFT (4) Top-left corner
WMSZ_TOPRIGHT (5) Top-right corner
WMSZ_BOTTOM (6) Bottom edge
WMSZ_BOTTOMLEFT (7) Bottom-left corner
WMSZ_BOTTOMRIGHT (8) Bottom-right corner
*/
}
InsertIntegerAtAddress(pInteger, pAddress, pOffset = 0, pSize = 4) ;update this to putnum
{
mask := 0xFF ; This serves to isolate each byte, one by one.
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
{
DllCall("RtlFillMemory", UInt, pAddress + pOffset + A_Index - 1, UInt, 1
, UChar, (pInteger & mask) >> 8 * (A_Index - 1))
mask := mask << 8 ; Set it up for isolation of the next byte.
}
}
/*
Function: Anchor
Defines how controls should be automatically positioned relative to the new dimensions of a window when resized.
Parameters:
cl - a control HWND, associated variable name or ClassNN to operate on
a - (optional) one or more of the anchors: 'x', 'y', 'w' (width) and 'h' (height),
optionally followed by a relative factor, e.g. "x h0.5"
r - (optional) true to redraw controls, recommended for GroupBox and Button types
Examples:
> "xy" ; bounds a control to the bottom-left edge of the window
> "w0.5" ; any change in the width of the window will resize the width of the control on a 2:1 ratio
> "h" ; similar to above but directrly proportional to height
Remarks:
To assume the current window size for the new bounds of a control (i.e. resetting) simply omit the second and third parameters.
However if the control had been created with DllCall() and has its own parent window,
the container AutoHotkey created GUI must be made default with the +LastFound option prior to the call.
For a complete example see anchor-example.ahk.
License:
- Version 4.60a by Titan <http://www.autohotkey.net/~Titan/#anchor>
- GNU General Public License 3.0 or higher <http://www.gnu.org/licenses/gpl-3.0.txt>
*/
Anchor(i, a = "", r = false) {
static c, cs = 12, cx = 255, cl = 0, g, gs = 8, gl = 0, gpi, gw, gh, z = 0, k = 0xffff
If z = 0
VarSetCapacity(g, gs * 99, 0), VarSetCapacity(c, cs * cx, 0), z := true
If (!WinExist("ahk_id" . i)) {
GuiControlGet, t, Hwnd, %i%
If ErrorLevel = 0
i := t
Else ControlGet, i, Hwnd, , %i%
}
VarSetCapacity(gi, 68, 0), DllCall("GetWindowInfo", "UInt", gp := DllCall("GetParent", "UInt", i), "UInt", &gi)
, giw := NumGet(gi, 28, "Int") - NumGet(gi, 20, "Int"), gih := NumGet(gi, 32, "Int") - NumGet(gi, 24, "Int")
If (gp != gpi) {
gpi := gp
Loop, %gl%
If (NumGet(g, cb := gs * (A_Index - 1)) == gp) {
gw := NumGet(g, cb + 4, "Short"), gh := NumGet(g, cb + 6, "Short"), gf := 1
Break
}
If (!gf)
NumPut(gp, g, gl), NumPut(gw := giw, g, gl + 4, "Short"), NumPut(gh := gih, g, gl + 6, "Short"), gl += gs
}
ControlGetPos, dx, dy, dw, dh, , ahk_id %i%
Loop, %cl%
If (NumGet(c, cb := cs * (A_Index - 1)) == i) {
If a =
{
cf = 1
Break
}
giw -= gw, gih -= gh, as := 1, dx := NumGet(c, cb + 4, "Short"), dy := NumGet(c, cb + 6, "Short")
, cw := dw, dw := NumGet(c, cb + 8, "Short"), ch := dh, dh := NumGet(c, cb + 10, "Short")
Loop, Parse, a, xywh
If A_Index > 1
av := SubStr(a, as, 1), as += 1 + StrLen(A_LoopField)
, d%av% += (InStr("yh", av) ? gih : giw) * (A_LoopField + 0 ? A_LoopField : 1)
DllCall("SetWindowPos", "UInt", i, "Int", 0, "Int", dx, "Int", dy
, "Int", InStr(a, "w") ? dw : cw, "Int", InStr(a, "h") ? dh : ch, "Int", 4)
If r != 0
DllCall("RedrawWindow", "UInt", i, "UInt", 0, "UInt", 0, "UInt", 0x0101) ; RDW_UPDATENOW | RDW_INVALIDATE
Return
}
If cf != 1
cb := cl, cl += cs
bx := NumGet(gi, 48), by := NumGet(gi, 16, "Int") - NumGet(gi, 8, "Int") - gih - NumGet(gi, 52)
If cf = 1
dw -= giw - gw, dh -= gih - gh
NumPut(i, c, cb), NumPut(dx - bx, c, cb + 4, "Short"), NumPut(dy - by, c, cb + 6, "Short")
, NumPut(dw, c, cb + 8, "Short"), NumPut(dh, c, cb + 10, "Short")
Return, true
}
|
_________________
 |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 388
|
Posted: Mon Apr 07, 2008 9:46 am Post subject: |
|
|
Now the sizing is contained in functions. To use, call
| Code: | | setGuiSize(gui1ID, "90%", "", "200%", "", True) | or | Code: | | setGuiSize(gui2ID, "300", "", "550", "", False) |
where the first param is the gui id or gui number, then minimum width, minimum height, maximum width, maximum height, and aspect ('True' or 'False'). The widths and heights can be given in pixels or percent of original. For the aspect, 'True' means to preserve the aspect ratio, and 'False' means to allow the width and height to change independently.
The main benefit of using the min/max settings without aspect ratio control is that you can specify the min or max values as a percent of the original instead of just pixels.
| Code: | ;Thread that I got "InsertIntegerAtAddress" and "WM_SIZING_Edge" from: http://www.autohotkey.com/forum/viewtopic.php?t=2441
;Uses Anchor 4.60a by Titan
Gui +Resize +LastFound
gui1ID := WinExist()
Gui, Add, Edit, w350 h250 vg1Edit, Hello
Gui, Add, Button, vg1Ok, Ok
Gui, Add, Button, x+ yp vg1Exit, Exit
Gui, Add, Button, x+ yp vg1Close, Close
Gui, Show,, MinMax & AutoRatio
Gui 2:+Resize +LastFound
gui2ID := WinExist()
Gui, 2:Add, Edit, w300 h200 vg2Edit, Hello
Gui, 2:Add, Button, vg2Ok, Ok
Gui, 2:Add, Button, x+ yp vg2Exit, Exit
Gui, 2:Add, Button, x+ yp vg2Close, Close
Gui, 2:Show,, Gui Number Two
Gui 3:+Resize +LastFound
gui3ID := WinExist()
Gui, 3:Add, Edit, w150 h100 vg3Edit, Hello
Gui, 3:Add, Button, vg3Ok, Ok
Gui, 3:Add, Button, x+ yp vg3Exit, Exit
Gui, 3:Add, Button, x+ yp vg3Close, Close
Gui, 3:Show,, NOT HANDLED
setGuiSize(gui1ID, "90%", "", "200%", "", True)
setGuiSize(gui2ID, "300", "", "550", "", False)
Return
GuiClose:
ExitApp
Return
GuiSize:
anchor("g1Edit","wh")
anchor("g1Ok","y")
anchor("g1Exit","y")
anchor("g1Close","y")
Return
WM_SIZING(wParam, lParam, msg)
{
Critical
static guiID, debounce
tmpBL := A_BatchLines
SetBatchLines,-1
WM_SIZING_Edge := wParam
CoordMode, MOUSE, SCREEN
If GetKeyState("LButton","P") and (!debounce) ;get the gui id the first time only for this resizing
{ debounce=1
MouseGetPos, mX, mY, guiID
}
Else If(debounce) ;not the first time through
{ MouseGetPos, mX, mY
}
If !GetKeyState("LButton","P") ;mouse released - reset
{ debounce=0
}
WinGetPos, CurrX, CurrY, CurrW, CurrH, ahk_id %guiID% ;Get current W/H
getGuiSize(guiID, _ratio, _min1, _min2, _max1, _max2, _aspect) ;get the ratio/min/max info for this gui
IfEqual, _ratio, , Return False ;if not a handled gui, exit func
If WM_SIZING_Edge in 2,8 ;right and bottom-right border drag - keep within min and max, keep aspect ratio
{ newWcoord := mX < CurrX + _min1 ? CurrX + _min1 : mX ;make sure width isn't smaller than min
newWcoord := newWcoord > CurrX + _max1 ? CurrX + _max1 : newWcoord ;make sure width isn't larger than max
InsertIntegerAtAddress(newWcoord, lParam, 8, 4) ;set x coord of right side of gui
If(_aspect)
{ newHcoord := CurrY + Round(CurrW * (1/_Ratio)) ;get the new height
InsertIntegerAtAddress(newHcoord, lParam, 12, 4) ;set y coord of bottom side of gui
}
}
If(WM_SIZING_Edge = 6) ;bottom border drag - keep within min and max, keep aspect ratio
{ newHcoord := mY < CurrY + _min2 ? CurrY + _min2 : mY ;make sure height isn't smaller than min
newHcoord := newHcoord > CurrY + _max2 ? CurrY + _max2 : newHcoord ;make sure height isn't larger than max
InsertIntegerAtAddress(newHcoord, lParam, 12, 4) ;set y coord of bottom side of gui
If(_aspect)
{ newWcoord := CurrX + Round(CurrH * _Ratio) ;get the new width
InsertIntegerAtAddress(newWcoord, lParam, 8, 4) ;set x coord of right side of gui
}
}
If(WM_SIZING_Edge = 3) ;top border drag - keep within min and max, keep aspect ratio
{ newYcoord := mY < CurrY + _min2 ? CurrY + _min2 : mY ;make sure height isn't smaller than min
newYcoord := newHcoord > CurrY + _max2 ? CurrY + _max2 : newHcoord ;make sure height isn't larger than max
InsertIntegerAtAddress(newHcoord, lParam, 4, 4) ;set y coord of bottom side of gui
InsertIntegerAtAddress(newHcoord, lParam, 0, 4) ;set y coord of top side of gui
If(_aspect)
{ newWcoord := CurrX + (CurrH * _Ratio) ;get the new width
InsertIntegerAtAddress(newWcoord, lParam, 8, 4) ;set x coord of right side of gui
}
}
;TODO - Top, Top-Right, Top-Left, Left, Left-Bottom - these will require modifing the x,y coords too.
SetBatchLines, %tmpBL%
return True
/*
From MSDN (with edits):
lParam - RECT Structure containing window coords
typedef struct _RECT {
LONG left; (0) offset in structure
LONG top; (4)
LONG right; (8)
LONG bottom; (12)
} RECT, *PRECT;
wParam - Specifies which edge of the window is being sized. This
parameter can be one of the following values.
WMSZ_LEFT (1) Left edge
WMSZ_RIGHT (2) Right edge
WMSZ_TOP (3) Top edge
WMSZ_TOPLEFT (4) Top-left corner
WMSZ_TOPRIGHT (5) Top-right corner
WMSZ_BOTTOM (6) Bottom edge
WMSZ_BOTTOMLEFT (7) Bottom-left corner
WMSZ_BOTTOMRIGHT (8) Bottom-right corner
*/
}
getGuiSize(_0, ByRef _1="", ByRef _2="", ByRef _3="", ByRef _4="", ByRef _5="", ByRef _6="", ByRef _7="", ByRef _8="", ByRef _9="", ByRef _10="", ByRef _11="", ByRef _12="", ByRef _13="", ByRef _14="") ;get the info for the given gui - vars return blank if no match - allow up to 15 params (maybe the basis of another array handler?)
{
global
IfEqual, _0,, Return Please provide an ID or Gui Number
If _0 Is Digit ;must have passed gui number instead of ID
{ Gui, %_0%:+LastFound
_0 := WinExist()
}
StringSplit, _ggsStuff, %_0%_ggsArray, `,
IfEqual, _ggsStuff0, 0, Return ;if not a match, exit func
Loop, %_ggsStuff0%
{ tmp = _%A_Index%
%tmp% := _ggsStuff%A_Index%
}
}
/*
defaults:
_ID = gui1 id
_minwidth = guiID.width
_minheight = guiID.height
_maxWidth = system window max width
_maxHeight = system window max height
*/
setGuiSize(_ID=1, _minWidth="", _minHeight="", _maxWidth="", _maxHeight="", _aspect=True) ;set the ratio/min/max info for the given gui
{
SysGet, SM_CXMAXTRACK, 59 ;get largest window size
SysGet, SM_CYMAXTRACK, 60
If _ID Is Digit ;must have passed gui number instead of window ID
{ Gui, %_ID%:+LastFound
_ID := WinExist()
}
WinGetPos,,,guiW, guiH, ahk_id %_ID% ;get gui w,h and calc the size ratio
_Ratio := guiW / guiH ;multiply the current width by _Ratio to get the new height, multiply the current height by (1/_Ratio) to get the new width
;this sets the vars for max w,h to keep aspect ratio
If(_minWidth) ;if minimum width is given
{ IfInString, _minWidth, `% ;if a percent is specified
{ StringReplace, _minWidth, _minWidth, `%,,All
_minWidth := _minWidth / 100 ;did it this way because _minWidth/100 produced '0' - an integer
_min1 := Round(guiW * _minWidth) ;this is the width
_min2 := Round(_min1 * (1/_Ratio)) ;this is the height
}
Else ;must be 'px'
{ StringReplace, _minWidth, _minWidth, px,,All ;just in case
_min1 := _minWidth ;this is the width
_min2 := Round(_min1 * (1/_Ratio)) ;this is the height
}
}
Else If(_minHeight) ;_minHeight given
{ IfInString, _minHeight, `% ;if a percent is specified
{ StringReplace, _minHeight, _minHeight, `%,,All
_minHeight := _minHeight / 100 ;did it this way because _minHeight/100 produced '0' - an integer
_min2 := guiH * _minHeight ;this is the height
_min1 := Round(_min2 * _Ratio) ;this is the width
}
Else ;must be 'px'
{ StringReplace, _minHeight, _minHeight, px,,All ;just in case
_min2 := _minHeight ;this is the height
_min1 := Round(_min2 * _Ratio) ;this is the width
}
}
Else ;no min given
{ _min1 := guiW ;set min w,h = initial gui w,h
_min2 := guiH
}
If(_maxWidth) ;if maximum width is given
{ IfInString, _maxWidth, `% ;if a percent is specified
{ StringReplace, _maxWidth, _maxWidth, `%,,All
_maxWidth /= 100
_max1 := guiW * _maxWidth ;this is the width
_max2 := (_max1 * (1/_Ratio)) ;this is the height
}
Else ;must be 'px'
{ StringReplace, _maxWidth, _maxWidth, px,,All ;just in case
_max1 := _maxWidth ;this is the width
_max2 := Round(_max1 * (1/_Ratio)) ;this is the height
}
}
Else If(_maxHeight) ;_maxHeight given
{ IfInString, _maxHeight, `% ;if a percent is specified
{ StringReplace, _maxHeight, _maxHeight, `%,,All
_maxHeight /= 100
_max2 := guiH * _maxHeight ;this is the height
_max1 := (_max2 * _Ratio) ;this is the width
}
Else ;must be 'px'
{ StringReplace, _maxHeight, _maxHeight, px,,All ;just in case
_max2 := _maxHeight ;this is the height
_max1 := Round(_max2 * _Ratio) ;this is the width
}
}
Else ;no max given
{ _max1 := SM_CXMAXTRACK ;largest window possible in system
_max2 := SM_CYMAXTRACK
}
%_ID%_ggsArray := _ratio "," _min1 "," _min2 "," _max1 "," _max2 "," _aspect
globalWrapper(_ID "_ggsArray", %_ID%_ggsArray)
OnMessage(0x214,"WM_SIZING") ;this will happen once for every window set, but that shouldn't cause any problems
}
globalWrapper(victim, content) ;this turns a dynamic local variable into a global variable
{
global
%victim% := content
}
InsertIntegerAtAddress(pInteger, pAddress, pOffset = 0, pSize = 4) ;update this to putnum
{
mask := 0xFF ; This serves to isolate each byte, one by one.
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
{
DllCall("RtlFillMemory", UInt, pAddress + pOffset + A_Index - 1, UInt, 1
, UChar, (pInteger & mask) >> 8 * (A_Index - 1))
mask := mask << 8 ; Set it up for isolation of the next byte.
}
}
/*
Function: Anchor
Defines how controls should be automatically positioned relative to the new dimensions of a window when resized.
Parameters:
cl - a control HWND, associated variable name or ClassNN to operate on
a - (optional) one or more of the anchors: 'x', 'y', 'w' (width) and 'h' (height),
optionally followed by a relative factor, e.g. "x h0.5"
r - (optional) true to redraw controls, recommended for GroupBox and Button types
Examples:
> "xy" ; bounds a control to the bottom-left edge of the window
> "w0.5" ; any change in the width of the window will resize the width of the control on a 2:1 ratio
> "h" ; similar to above but directrly proportional to height
Remarks:
To assume the current window size for the new bounds of a control (i.e. resetting) simply omit the second and third parameters.
However if the control had been created with DllCall() and has its own parent window,
the container AutoHotkey created GUI must be made default with the +LastFound option prior to the call.
For a complete example see anchor-example.ahk.
License:
- Version 4.60a by Titan <http://www.autohotkey.net/~Titan/#anchor>
- GNU General Public License 3.0 or higher <http://www.gnu.org/licenses/gpl-3.0.txt>
*/
Anchor(i, a = "", r = false) {
static c, cs = 12, cx = 255, cl = 0, g, gs = 8, gl = 0, gpi, gw, gh, z = 0, k = 0xffff
If z = 0
VarSetCapacity(g, gs * 99, 0), VarSetCapacity(c, cs * cx, 0), z := true
If (!WinExist("ahk_id" . i)) {
GuiControlGet, t, Hwnd, %i%
If ErrorLevel = 0
i := t
Else ControlGet, i, Hwnd, , %i%
}
VarSetCapacity(gi, 68, 0), DllCall("GetWindowInfo", "UInt", gp := DllCall("GetParent", "UInt", i), "UInt", &gi)
, giw := NumGet(gi, 28, "Int") - NumGet(gi, 20, "Int"), gih := NumGet(gi, 32, "Int") - NumGet(gi, 24, "Int")
If (gp != gpi) {
gpi := gp
Loop, %gl%
If (NumGet(g, cb := gs * (A_Index - 1)) == gp) {
gw := NumGet(g, cb + 4, "Short"), gh := NumGet(g, cb + 6, "Short"), gf := 1
Break
}
If (!gf)
NumPut(gp, g, gl), NumPut(gw := giw, g, gl + 4, "Short"), NumPut(gh := gih, g, gl + 6, "Short"), gl += gs
}
ControlGetPos, dx, dy, dw, dh, , ahk_id %i%
Loop, %cl%
If (NumGet(c, cb := cs * (A_Index - 1)) == i) {
If a =
{
cf = 1
Break
}
giw -= gw, gih -= gh, as := 1, dx := NumGet(c, cb + 4, "Short"), dy := NumGet(c, cb + 6, "Short")
, cw := dw, dw := NumGet(c, cb + 8, "Short"), ch := dh, dh := NumGet(c, cb + 10, "Short")
Loop, Parse, a, xywh
If A_Index > 1
av := SubStr(a, as, 1), as += 1 + StrLen(A_LoopField)
, d%av% += (InStr("yh", av) ? gih : giw) * (A_LoopField + 0 ? A_LoopField : 1)
DllCall("SetWindowPos", "UInt", i, "Int", 0, "Int", dx, "Int", dy
, "Int", InStr(a, "w") ? dw : cw, "Int", InStr(a, "h") ? dh : ch, "Int", 4)
If r != 0
DllCall("RedrawWindow", "UInt", i, "UInt", 0, "UInt", 0, "UInt", 0x0101) ; RDW_UPDATENOW | RDW_INVALIDATE
Return
}
If cf != 1
cb := cl, cl += cs
bx := NumGet(gi, 48), by := NumGet(gi, 16, "Int") - NumGet(gi, 8, "Int") - gih - NumGet(gi, 52)
If cf = 1
dw -= giw - gw, dh -= gih - gh
NumPut(i, c, cb), NumPut(dx - bx, c, cb + 4, "Short"), NumPut(dy - by, c, cb + 6, "Short")
, NumPut(dw, c, cb + 8, "Short"), NumPut(dh, c, cb + 10, "Short")
Return, true
}
|
_________________
 |
|
| Back to top |
|
 |
U90 Guest
|
Posted: Mon Apr 14, 2008 4:51 am Post subject: |
|
|
Micahs, .. big Applause!
I was going to post this on a separate thread, but maybe you can assist. I like the way this function works, but curious if you might know how to hook in a special sub-function which accomplishes this goal:
--Slow down the rate in which the GUI can be opened, in a smooth fashion.... so like, the way it is right now is like 1.0, ... and some setting like 0.5 would slow the rate at which one can grab and expand open the GUI.
It seems like you have the expertise to understand the dynamics of this and maybe can help me on a separate problem I have.... BTW, I love this design. Very cool  |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 388
|
Posted: Tue Apr 15, 2008 6:04 pm Post subject: |
|
|
I had to move some things around. You'll have to find a happy balance between 'IncrementSize' and 'IncrementSpeed' to get the rate/smoothness you desire. What do you think?
| Code: | ;This one has resize speed control!
;Thread that I got "InsertIntegerAtAddress" and "WM_SIZING_Edge" from: http://www.autohotkey.com/forum/viewtopic.php?t=2441
;Uses Anchor 4.60a by Titan
Gui +Resize +LastFound
gui1ID := WinExist()
Gui, Add, Edit, w350 h250 vg1Edit, Hello
Gui, Add, Button, vg1Ok, Ok
Gui, Add, Button, x+ yp vg1Exit, Exit
Gui, Add, Button, x+ yp vg1Close, Close
Gui, Show,, MinMax`, No Aspect
Gui 2:+Resize +LastFound
gui2ID := WinExist()
Gui, 2:Add, Edit, w300 h200 vg2Edit, Hello
Gui, 2:Add, Button, vg2Ok, Ok
Gui, 2:Add, Button, x+ yp vg2Exit, Exit
Gui, 2:Add, Button, x+ yp vg2Close, Close
Gui, 2:Show,, MinMax`, With Aspect
Gui 3:+Resize +LastFound
gui3ID := WinExist()
Gui, 3:Add, Edit, w150 h100 vg3Edit, Hello
Gui, 3:Add, Button, vg3Ok, Ok
Gui, 3:Add, Button, x+ yp vg3Exit, Exit
Gui, 3:Add, Button, x+ yp vg3Close, Close
Gui, 3:Show,, NOT HANDLED
setGuiSize(gui1ID, "90%", "", "200%", "", False)
setGuiSize(gui2ID, "300", "", "550", "", True)
Return
GuiClose:
ExitApp
Return
GuiSize:
anchor("g1Edit","wh")
anchor("g1Ok","y")
anchor("g1Exit","y")
anchor("g1Close","y")
Return
WM_SIZING(wParam, lParam, msg)
{
global
Critical
static guiID, debounce
WM_SIZING_Edge := wParam
guiSizeAddr := lParam
If GetKeyState("LButton","P") and (!debounce) ;for each resizing, only get the gui id and info the first time through
{ debounce=1
CoordMode, MOUSE, SCREEN
MouseGetPos,,, guiID
getGuiSize(guiID, _ratio, _min1, _min2, _max1, _max2, _aspect) ;get the ratio/min/max info for this gui
SetTimer, WinSlowerDowner, %IncrementSpeed%
}
If !GetKeyState("LButton","P") ;mouse released - reset
{ debounce=0
SetTimer, WinSlowerDowner, Off
}
IfEqual, _ratio, , Return False ;if not a handled gui, exit func
WinGetPos, CurrX, CurrY, CurrW, CurrH, ahk_id %guiID% ;Get current x,y,w,h
newCurrW := CurrX + CurrW
newCurrH := CurrY + CurrH
InsertIntegerAtAddress(CurrX, lParam, Rect_left, 4) ;set x coord of left side of gui - these make sure the drag does not happen!
InsertIntegerAtAddress(CurrY, lParam, Rect_top, 4) ;set y coord of top side of gui
InsertIntegerAtAddress(newCurrW, lParam, Rect_right, 4) ;set x coord of right side of gui
InsertIntegerAtAddress(newCurrH, lParam, Rect_bottom, 4) ;set y coord of bottom side of gui
Return True
WinSlowerDowner:
Critical
SetWinDelay, 0
If !GetKeyState("LButton","P")
{ Exit
}
tmpBL := A_BatchLines
SetBatchLines, 20ms
CoordMode, MOUSE, SCREEN
MouseGetPos, tX, tY
WinGetPos, CurrX, CurrY, CurrW, CurrH, ahk_id %guiID% ;Get current x,y,w,h
If WM_SIZING_Edge in 2,8 ;right and bottom-right border drag
{ idealW := Abs(CurrX-tX) ;what the width should be
tmpCurrW := CurrW ;current width
If(tmpCurrW < idealW) ;if current is less than it should be
{ tmpCurrW += IncrementSize
idealW := idealW < _max1 ? idealW : _max1 ;keep ideal width within max
tmpCurrW := tmpCurrW > idealW ? idealW : tmpCurrW ;if greater than ideal width, make equal
tmpCurrH := _aspect ? Round(tmpCurrW * (1/_Ratio)) : CurrH ;preserve aspect ratio or not
WinMove, ahk_id %guiID% ,,,, tmpCurrW, tmpCurrH ;do the deed
}
Else If(tmpCurrW > idealW) ;current is greater than it should be
{ tmpCurrW -= IncrementSize
idealW := idealW > _min1 ? idealW : _min1 ;keep ideal width within min
tmpCurrW := tmpCurrW < idealW ? idealW : tmpCurrW ;if less than ideal width, make equal
tmpCurrH := _aspect ? Round(tmpCurrW * (1/_Ratio)) : CurrH ;preserve aspect ratio or not
WinMove, ahk_id %guiID% ,,,, tmpCurrW, tmpCurrH ;do the deed
}
}
If(WM_SIZING_Edge = 6) ;bottom border drag
{ idealH := Abs(CurrY-tY) ;what the height should be
tmpCurrH := CurrH ;current height
If(tmpCurrH < idealH) ;if current is less than it should be
{ tmpCurrH += IncrementSize
idealH := idealH < _max2 ? idealH : _max2 ;keep ideal height within max
tmpCurrH := tmpCurrH > idealH ? idealH : tmpCurrH ;if greater than ideal height, make equal
tmpCurrW := _aspect ? Round(tmpCurrH * _Ratio) : CurrW ;preserve aspect ratio or not
WinMove, ahk_id %guiID% ,,,, tmpCurrW, tmpCurrH ;do the deed
}
Else If(tmpCurrH > idealH) ;current is greater than it should be
{ tmpCurrH -= IncrementSize
idealH := idealH > _min2 ? idealH : _min2 ;keep ideal height within min
tmpCurrH := tmpCurrH < idealH ? idealH : tmpCurrH ;if less than ideal height, make equal
tmpCurrW := _aspect ? Round(tmpCurrH * _Ratio) : CurrW ;preserve aspect ratio or not
WinMove, ahk_id %guiID% ,,,, tmpCurrW, tmpCurrH ;do the deed
}
}
;~ TODO:
;~ If(WM_SIZING_Edge = 3) ;top border drag
;~ If(WM_SIZING_Edge = 4) ;top-left border
;~ If WM_SIZING_Edge In 1,7 ;left, bottom-left borders
SetBatchLines, %tmpBL%
Return
/*
From MSDN (with edits):
lParam - RECT Structure containing window coords
typedef struct _RECT {
LONG left; (0) offset in structure
LONG top; (4)
LONG right; (8)
LONG bottom; (12)
} RECT, *PRECT;
wParam - Specifies which edge of the window is being sized. This
parameter can be one of the following values.
WMSZ_LEFT (1) Left edge
WMSZ_RIGHT (2) Right edge
WMSZ_TOP (3) Top edge
WMSZ_TOPLEFT (4) Top-left corner
WMSZ_TOPRIGHT (5) Top-right corner
WMSZ_BOTTOM (6) Bottom edge
WMSZ_BOTTOMLEFT (7) Bottom-left corner
WMSZ_BOTTOMRIGHT (8) Bottom-right corner
*/
}
getGuiSize(_0, ByRef _1="", ByRef _2="", ByRef _3="", ByRef _4="", ByRef _5="", ByRef _6="", ByRef _7="", ByRef _8="", ByRef _9="", ByRef _10="", ByRef _11="", ByRef _12="", ByRef _13="", ByRef _14="") ;get the info for the given gui - vars return blank if no match - allow up to 15 params (maybe the basis of another array handler?)
{
global
local tmp1
Rect_left = 0 ;set up some constants for the sizing
Rect_top = 4
Rect_right = 8
Rect_bottom = 12
IncrementSize = 15
IncrementSpeed = 50
IfEqual, _0,, Return Please provide an ID or Gui Number
If _0 Is Digit ;must have passed gui number instead of ID
{ Gui, %_0%:+LastFound
_0 := WinExist()
}
StringSplit, _ggsStuff, %_0%_ggsArray, `,
IfEqual, _ggsStuff0, 0, Return ;if not a match, exit func
Loop, %_ggsStuff0%
{ tmp1 = _%A_Index%
%tmp1% := _ggsStuff%A_Index%
}
}
/*
defaults:
_ID = gui1 id
_minwidth = guiID.width
_minheight = guiID.height
_maxWidth = system window max width
_maxHeight = system window max height
*/
setGuiSize(_ID=1, _minWidth="", _minHeight="", _maxWidth="", _maxHeight="", _aspect=True) ;set the ratio/min/max info for the given gui
{
SysGet, SM_CXMAXTRACK, 59 ;get largest window size
SysGet, SM_CYMAXTRACK, 60
If _ID Is Digit ;must have passed gui number instead of window ID
{ Gui, %_ID%:+LastFound
_ID := WinExist()
}
WinGetPos,,,guiW, guiH, ahk_id %_ID% ;get gui w,h and calc the size ratio
_Ratio := guiW / guiH ;multiply the current width by _Ratio to get the new height, multiply the current height by (1/_Ratio) to get the new width
;this sets the vars for max w,h to keep aspect ratio
If(_minWidth) ;if minimum width is given
{ IfInString, _minWidth, `% ;if a percent is specified
{ StringReplace, _minWidth, _minWidth, `%,,All
_minWidth := _minWidth / 100 ;did it this way because _minWidth/100 produced '0' - an integer
_min1 := Round(guiW * _minWidth) ;this is the width
_min2 := Round(_min1 * (1/_Ratio)) ;this is the height
}
Else ;must be 'px'
{ StringReplace, _minWidth, _minWidth, px,,All ;just in case
_min1 := _minWidth ;this is the width
_min2 := Round(_min1 * (1/_Ratio)) ;this is the height
}
}
Else If(_minHeight) ;_minHeight given
{ IfInString, _minHeight, `% ;if a percent is specified
{ StringReplace, _minHeight, _minHeight, `%,,All
_minHeight := _minHeight / 100 ;did it this way because _minHeight/100 produced '0' - an integer
_min2 := guiH * _minHeight ;this is the height
_min1 := Round(_min2 * _Ratio) ;this is the width
}
Else ;must be 'px'
{ StringReplace, _minHeight, _minHeight, px,,All ;just in case
_min2 := _minHeight ;this is the height
_min1 := Round(_min2 * _Ratio) ;this is the width
}
}
Else ;no min given
{ _min1 := guiW ;set min w,h = initial gui w,h
_min2 := guiH
}
If(_maxWidth) ;if maximum width is given
{ IfInString, _maxWidth, `% ;if a percent is specified
{ StringReplace, _maxWidth, _maxWidth, `%,,All
_maxWidth /= 100
_max1 := guiW * _maxWidth ;this is the width
_max2 := (_max1 * (1/_Ratio)) ;this is the height
}
Else ;must be 'px'
{ StringReplace, _maxWidth, _maxWidth, px,,All ;just in case
_max1 := _maxWidth ;this is the width
_max2 := Round(_max1 * (1/_Ratio)) ;this is the height
}
}
Else If(_maxHeight) ;_maxHeight given
{ IfInString, _maxHeight, `% ;if a percent is specified
{ StringReplace, _maxHeight, _maxHeight, `%,,All
_maxHeight /= 100
_max2 := guiH * _maxHeight ;this is the height
_max1 := (_max2 * _Ratio) ;this is the width
}
Else ;must be 'px'
{ StringReplace, _maxHeight, _maxHeight, px,,All ;just in case
_max2 := _maxHeight ;this is the height
_max1 := Round(_max2 * _Ratio) ;this is the width
}
}
Else ;no max given
{ _max1 := SM_CXMAXTRACK ;largest window possible in system
_max2 := SM_CYMAXTRACK
}
%_ID%_ggsArray := _ratio "," _min1 "," _min2 "," _max1 "," _max2 "," _aspect
globalWrapper(_ID "_ggsArray", %_ID%_ggsArray)
OnMessage(0x214,"WM_SIZING") ;this will happen once for every window set, but that shouldn't cause any problems
}
globalWrapper(victim, content) ;this turns a dynamic local variable into a global variable
{
global
%victim% := content
}
InsertIntegerAtAddress(pInteger, pAddress, pOffset = 0, pSize = 4) ;update this to putnum
{
mask := 0xFF ; This serves to isolate each byte, one by one.
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
{
DllCall("RtlFillMemory", UInt, pAddress + pOffset + A_Index - 1, UInt, 1
, UChar, (pInteger & mask) >> 8 * (A_Index - 1))
mask := mask << 8 ; Set it up for isolation of the next byte.
}
}
/*
Function: Anchor
Defines how controls should be automatically positioned relative to the new dimensions of a window when resized.
Parameters:
cl - a control HWND, associated variable name or ClassNN to operate on
a - (optional) one or more of the anchors: 'x', 'y', 'w' (width) and 'h' (height),
optionally followed by a relative factor, e.g. "x h0.5"
r - (optional) true to redraw controls, recommended for GroupBox and Button types
Examples:
> "xy" ; bounds a control to the bottom-left edge of the window
> "w0.5" ; any change in the width of the window will resize the width of the control on a 2:1 ratio
> "h" ; similar to above but directrly proportional to height
Remarks:
To assume the current window size for the new bounds of a control (i.e. resetting) simply omit the second and third parameters.
However if the control had been created with DllCall() and has its own parent window,
the container AutoHotkey created GUI must be made default with the +LastFound option prior to the call.
For a complete example see anchor-example.ahk.
License:
- Version 4.60a by Titan <http://www.autohotkey.net/~Titan/#anchor>
- GNU General Public License 3.0 or higher <http://www.gnu.org/licenses/gpl-3.0.txt>
*/
Anchor(i, a = "", r = false) {
static c, cs = 12, cx = 255, cl = 0, g, gs = 8, gl = 0, gpi, gw, gh, z = 0, k = 0xffff
If z = 0
VarSetCapacity(g, gs * 99, 0), VarSetCapacity(c, cs * cx, 0), z := true
If (!WinExist("ahk_id" . i)) {
GuiControlGet, t, Hwnd, %i%
If ErrorLevel = 0
i := t
Else ControlGet, i, Hwnd, , %i%
}
VarSetCapacity(gi, 68, 0), DllCall("GetWindowInfo", "UInt", gp := DllCall("GetParent", "UInt", i), "UInt", &gi)
, giw := NumGet(gi, 28, "Int") - NumGet(gi, 20, "Int"), gih := NumGet(gi, 32, "Int") - NumGet(gi, 24, "Int")
If (gp != gpi) {
gpi := gp
Loop, %gl%
If (NumGet(g, cb := gs * (A_Index - 1)) == gp) {
gw := NumGet(g, cb + 4, "Short"), gh := NumGet(g, cb + 6, "Short"), gf := 1
Break
}
If (!gf)
NumPut(gp, g, gl), NumPut(gw := giw, g, gl + 4, "Short"), NumPut(gh := gih, g, gl + 6, "Short"), gl += gs
}
ControlGetPos, dx, dy, dw, dh, , ahk_id %i%
Loop, %cl%
If (NumGet(c, cb := cs * (A_Index - 1)) == i) {
If a =
{
cf = 1
Break
}
giw -= gw, gih -= gh, as := 1, dx := NumGet(c, cb + 4, "Short"), dy := NumGet(c, cb + 6, "Short")
, cw := dw, dw := NumGet(c, cb + 8, "Short"), ch := dh, dh := NumGet(c, cb + 10, "Short")
Loop, Parse, a, xywh
If A_Index > 1
av := SubStr(a, as, 1), as += 1 + StrLen(A_LoopField)
, d%av% += (InStr("yh", av) ? gih : giw) * (A_LoopField + 0 ? A_LoopField : 1)
DllCall("SetWindowPos", "UInt", i, "Int", 0, "Int", dx, "Int", dy
, "Int", InStr(a, "w") ? dw : cw, "Int", InStr(a, "h") ? dh : ch, "Int", 4)
If r != 0
DllCall("RedrawWindow", "UInt", i, "UInt", 0, "UInt", 0, "UInt", 0x0101) ; RDW_UPDATENOW | RDW_INVALIDATE
Return
}
If cf != 1
cb := cl, cl += cs
bx := NumGet(gi, 48), by := NumGet(gi, 16, "Int") - NumGet(gi, 8, "Int") - gih - NumGet(gi, 52)
If cf = 1
dw -= giw - gw, dh -= gih - gh
NumPut(i, c, cb), NumPut(dx - bx, c, cb + 4, "Short"), NumPut(dy - by, c, cb + 6, "Short")
, NumPut(dw, c, cb + 8, "Short"), NumPut(dh, c, cb + 10, "Short")
Return, true
}
|
_________________
 |
|
| Back to top |
|
 |
FireGirl
Joined: 04 May 2007 Posts: 102
|
Posted: Mon Jun 02, 2008 11:56 pm Post subject: |
|
|
Micahs!
I like what you did with this allot I've been working with something quite similar (see below), ... and just curious if you would take a quick looksee, and see if you can blend this into what you have -- or have your own personal take within it.
With this code, the GUI is designed to be open/closed by dragging the inside corridor ... and it would be so awesome if we could get the ratio perspective into this!!!, or yours vice-versa
| Code: |
xsize = 478
ysize = 478
xoffset = 40
yoffset = 40
xoffsethigh := xsize - xoffset
yoffsethigh := ysize - yoffset
Gui 2: -Border -caption +ToolWindow
Gui 2: Color, D3407E
Gui 2: Show, w%xsize% h%ysize%, a %xsize%x%ysize% GUI
WinGet, active_id, ID, A
OnMessage(0x201, "GUI_Expand")
return
GUI_Expand(wParam, lParam)
{
global
MouseGetPos, Xpos, Ypos, OutputvarWin,
if (OutputvarWin = active_ID)
{
WinGetPos, winXpos, winYpos, Xsize, Ysize, ahk_id %active_ID%
if ( (Xpos > xoffsethigh) and (Ypos > yoffset or Ypos < yoffsethigh) )
{
loop
{
GetKeyState, state, LButton
if state = D
{
prevXpos := Xpos
MouseGetPos, Xpos, Ypos,
Xsize := Xsize + Xpos - prevXpos
Gui, Show, w%xsize% h%ysize%, a %xsize%x%ysize% GUI
xoffsethigh := xsize - xoffset
yoffsethigh := ysize - yoffset
}
else
break
}
}
if ( (Ypos > yoffsethigh) and (Xpos > xoffset or Xpos < xoffsethigh) )
{
loop
{
GetKeyState, state, LButton
if state = D
{
prevYpos := Ypos
MouseGetPos, Xpos, Ypos,
Ysize := Ysize + Ypos - prevYpos
Gui, Show, w%xsize% h%ysize%, a %xsize%x%ysize% GUI
xoffsethigh := xsize - xoffset
yoffsethigh := ysize - yoffset
}
else
break
}
}
}
}
|
BTW, thanks allot to Z Gecko, Razlin and some others helping. |
|
| Back to top |
|
 |
Micahs
Joined: 01 Dec 2006 Posts: 388
|
Posted: Tue Jun 03, 2008 4:00 pm Post subject: |
|
|
This is one of the first iterations modified a little. It behaves like the bit that you posted. Note that I still haven't added sizing by dragging the left or top borders. I'll look into it if you want.
| Code: | SetBatchLines, -1
SetWinDelay,10
Gui 2: -Border -caption +ToolWindow +LastFound
Gui 2: Color, D3407E
guiID := WinExist()
Gui, 2:Show, w300 h351
WinGetPos,,,winW, winH
changeArrow=0 ;change the cursor to arrows when over the drag area or not
constrainMouse=0 ;constrain the mouse to the border min/max during drag
fudgeFactor = 3 ;makes the border area larger for easier dragging, seems to be needed on the bottom border
GuiMinSize=300x351
GuiMaxSize=425x496
IDC_SIZEWE = 32644
IDC_SIZENS = 32645
SysGet, SM_CXFIXEDFRAME, 7
SysGet, SM_CYFIXEDFRAME, 8
leftBorder := SM_CXFIXEDFRAME + fudgeFactor
topBorder := SM_CYFIXEDFRAME + fudgeFactor
WM_MOUSEMOVE = 0x200
WM_LBUTTONDOWN = 0x201
hProp := winH / winW ;multiply the current width by hProp to get the new height
wProp := winW / winH ;multiply the current height by wProp to get the new width
WEcursor := DllCall("LoadCursor", "Uint", 0, "Int", IDC_SIZEWE) ;load west-east cursor
NScursor := DllCall("LoadCursor", "Uint", 0, "Int", IDC_SIZENS) ;load north-south cursor
StringSplit, guiMin, GuiMinSize, x ;guiMin1 is width ;guiMin2 is height
StringSplit, guiMax, GuiMaxSize, x ;guiMax1 is width ;guiMax2 is height
OnMessage(WM_MOUSEMOVE, "CheckDrag")
OnMessage(WM_LBUTTONDOWN, "CheckDrag")
Return
;need to make left and top border work.
;for left, have to make x smaller while making w larger.
CheckDrag(wparam, lparam, msg, hwnd)
{
global
MouseGetPos, mX, mY
WinGetPos, oX, oY, oW, oH, ahk_id %guiID%
rightBorder := oW - SM_CXFIXEDFRAME - fudgeFactor
bottomBorder := oH - SM_CYFIXEDFRAME - fudgeFactor
If(mX < leftBorder)
{ If(changeArrow)
{ DllCall("SetCursor", "uint", WEcursor) ;set west-east cursor
}
direction = W
SetTimer, sizer, 0
}
Else If(mX >= rightBorder)
{ If(changeArrow)
{ DllCall("SetCursor", "uint", WEcursor) ;set west-east cursor
}
direction = E
SetTimer, sizer, 0
}
Else If(mX < topBorder)
{ If(changeArrow)
{ DllCall("SetCursor", "uint", NScursor) ;set north-south cursor
}
direction = N
SetTimer, sizer, 0
}
Else If(mY > bottomBorder)
{ If(changeArrow)
{ DllCall("SetCursor", "uint", NScursor) ;set north-south cursor
}
direction = S
SetTimer, sizer, 0
}
}
sizer:
Critical
If GetKeyState("LButton","P")
{ CoordMode, MOUSE, SCREEN
MouseGetPos, moveX, moveY
If(direction = "W") ;dragging left border ******DOES NOT WORK*****
{ If(changeArrow)
{ DllCall("SetCursor", "uint", WEcursor) ;set west-east cursor
}
newW := moveX - oX
newH := newW * hProp
newX := moveX
newY :=
}
Else If(direction = "N") ;dragging top border ******DOES NOT WORK*****
{ If(changeArrow)
{ DllCall("SetCursor", "uint", NScursor) ;set north-south cursor
}
newH := oY - moveY
newH := newH < guiMin2 ? guiMin2 : newH ;make sure its not smaller than minimum
newH := newH > guiMax2 ? guiMax2 : newH ;make sure its not bigger than maximum
newW := newH * wProp
}
Else If(direction = "E") ;dragging right border
{ If(changeArrow)
{ DllCall("SetCursor", "uint", WEcursor) ;set west-east cursor
}
newW := moveX - oX
newW := newW < guiMin1 ? guiMin1 : newW ;make sure its not smaller than minimum
newW := newW > guiMax1 ? guiMax1 : newW ;make sure its not bigger than maximum
newH := newW * hProp
newX=
newY=
If(constrainMouse)
{ moveX := moveX > oX + guiMax1 ? oX + guiMax1 : moveX ;keep mouse within max
moveX := moveX < oX + guiMin1 ? oX + guiMin1 : moveX ;keep mouse within min
}
}
Else If(direction = "S") ;dragging bottom border
{ If(changeArrow)
{ DllCall("SetCursor", "uint", NScursor) ;set north-south cursor
}
newH := moveY - oY
newH := newH < guiMin2 ? guiMin2 : newH ;make sure its not smaller than minimum
newH := newH > guiMax2 ? guiMax2 : newH ;make sure its not bigger than maximum
newW := newH * wProp
newX=
newY=
If(constrainMouse)
{ moveY := moveY > oY + guiMax2 ? oY + guiMax2 : moveY ;keep mouse within max
moveY := moveY < oY + guiMin2 ? oY + guiMin2 : moveY ;keep mouse within min
}
}
MouseMove, moveX, moveY
WinMove, ahk_id %guiID%,, %newX%, %newY%, %newW%, %newH%
}
Else
{ SetTimer, sizer, Off
}
Return
guiClose:
ExitApp
Return |
_________________
 |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|