@FireGirl
Here is working code for the resizing problem. I was on the wrong track with the left and top border dragging function! All the resizing of borders works like it should. Try it now.
This requires the "+Resize" option on the gui to work rather than handling the dragging ourselves. I went back to the "WM_SIZING" message. If you have any questions, give a holler.
Code:
;Thread that I got "InsertIntegerAtAddress" and "WM_SIZING_Edge" from: http://www.autohotkey.com/forum/viewtopic.php?t=2441
Gui, -border +Resize +LastFound
gui1ID := WinExist()
Gui, Color, 0xFF80C0
Gui, Show, w300 h300, MinMax & AutoRatio
setGuiSize(gui1ID, "100%", "", "", "400", True) ;guiID or guiNum | minwidth | minheight | maxwidth | maxheight | aspect
Return
GuiClose:
ExitApp
Return
WM_SIZING(wParam, lParam, msg)
{
Critical
static guiID, debounce, rightX, bottomY
static rect_left=0, rect_top=4, rect_right=8, rect_bottom=12 ;some rect constants
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
WinGetPos, CurrX, CurrY, CurrW, CurrH, ahk_id %guiID% ;Get beginning rightX and bottomY coords
rightX := CurrX+CurrW
bottomY := CurrY+CurrH
}
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, _minWidth, _minHeight, _maxWidth, _maxHeight, _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
{ newWcoord := mX < CurrX + _minWidth ? CurrX + _minWidth : mX ;make sure width isn't smaller than min
newWcoord := newWcoord > CurrX + _maxWidth ? CurrX + _maxWidth : newWcoord ;make sure width isn't larger than max
InsertIntegerAtAddress(newWcoord, lParam, rect_right) ;set x coord of right side of gui
If(_aspect)
{ newHcoord := CurrY + Round(CurrW * (1/_Ratio)) ;get the new height
InsertIntegerAtAddress(newHcoord, lParam, rect_bottom) ;set y coord of bottom side of gui
}
}
Else If WM_SIZING_Edge in 6 ;bottom border drag
{ newHcoord := mY < CurrY + _minHeight ? CurrY + _minHeight : mY ;make sure height isn't smaller than min
newHcoord := newHcoord > CurrY + _maxHeight ? CurrY + _maxHeight : newHcoord ;make sure height isn't larger than max
InsertIntegerAtAddress(newHcoord, lParam, rect_bottom) ;set y coord of bottom side of gui
If(_aspect)
{ newWcoord := CurrX + Round(CurrH * _Ratio) ;get the new width
InsertIntegerAtAddress(newWcoord, lParam, rect_right) ;set x coord of right side of gui
}
}
Else If WM_SIZING_Edge in 3,5 ;top and top-right border drag
{ newYcoord := mY > bottomY-_minHeight ? bottomY-_minHeight : mY ;make sure height isn't smaller than min
newYcoord := newYcoord < bottomY-_maxHeight ? bottomY-_maxHeight : newYcoord ;make sure height isn't larger than max
InsertIntegerAtAddress(newYcoord, lParam, rect_top) ;set y coord of top side of gui
InsertIntegerAtAddress(bottomY, lParam, rect_bottom) ;set y coord of bottom side of gui
If(_aspect)
{ newWcoord := CurrX + (CurrH * _Ratio) ;get the new width
InsertIntegerAtAddress(newWcoord, lParam, rect_right) ;set x coord of right side of gui
}
}
Else If WM_SIZING_Edge in 1,7 ;left and bottom-left border drag
{ newXcoord := mX > rightX-_minWidth ? rightX-_minWidth : mX ;make sure width isn't smaller than min
newXcoord := newXcoord < rightX-_maxWidth ? rightX-_maxWidth : newXcoord ;make sure width isn't larger than max
InsertIntegerAtAddress(newXcoord, lParam, rect_left) ;set x coord of left side of gui
InsertIntegerAtAddress(rightX, lParam, rect_right) ;set x coord of right side of gui
If(_aspect)
{ newHcoord := CurrY + Round(CurrW * (1/_Ratio)) ;get the new height
InsertIntegerAtAddress(newHcoord, lParam, rect_bottom) ;set y coord of bottom side of gui
}
}
Else If WM_SIZING_Edge in 4 ;top-left border drag
{ newYcoord := mY > bottomY-_minHeight ? bottomY-_minHeight : mY ;make sure height isn't smaller than min
newYcoord := newYcoord < bottomY-_maxHeight ? bottomY-_maxHeight : newYcoord ;make sure height isn't larger than max
scaleMX := rightX - ((bottomY-newYcoord)*_Ratio) ;scale x to y
newXcoord := scaleMX > rightX-_minWidth ? rightX-_minWidth : scaleMX ;make sure width isn't smaller than min
newXcoord := newXcoord < rightX-_maxWidth ? rightX-_maxWidth : newXcoord ;make sure width isn't larger than max
InsertIntegerAtAddress(newYcoord, lParam, rect_top) ;set y coord of top side of gui
InsertIntegerAtAddress(rightX, lParam, rect_right) ;set x coord of right side of gui
InsertIntegerAtAddress(bottomY, lParam, rect_bottom) ;set y coord of bottom side of gui
InsertIntegerAtAddress(newXcoord, lParam, rect_left) ;set x coord of left side of gui
}
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
local tmp1
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
*/
;DEFINE_FUNCTION setGuiSize(ID, Min Width, Min Height, Max Width, Max Height, Aspect)
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.
}
}
Thanks for prodding me to finish this! I probably wouldn't have gotten around to it for a while.