Does anyone know of a simple method that will prevent a GUI from setting the Y position to 0 when is moved and released?
I know that I can use OnMessage( 0x3 ) to detect when the window is moving
and then watch for a LButton Up event to set the gui in the position I want. Is that the best I can do or does someone have a better way to do this.
The goal is simple. When I move the window, have it stay where it is moved (even with a negative value for the y axis ).
Example:
Before the question comes up. There is a reason for what is seen, and having what is shown above in the placement it is in is required for other elements that come later. So no I can't just place it at the top of the gui.
HB.
Disable a gui from resetting the the Y position to 0 when released Topic is solved
-
- Posts: 4330
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Disable a gui from resetting the the Y position to 0 when released
Consider this way:
Code: Select all
global EVENT_SYSTEM_MOVESIZESTART := 0xA
, EVENT_SYSTEM_MOVESIZEEND := 0xB
Gui, New, +hwndhGui
Gui, Show, w300 h300
Hook := new WinEventHook(EVENT_SYSTEM_MOVESIZESTART, EVENT_SYSTEM_MOVESIZEEND, "HookProc", hGui)
Return
GuiClose:
ExitApp
HookProc(hHook, event, hwnd) {
static start := {}
if (hwnd != A_EventInfo)
Return
if (event = EVENT_SYSTEM_MOVESIZESTART) {
WinGetPos, X, Y,,, ahk_id %hwnd%
start.x := X, start.y := Y
}
if (event = EVENT_SYSTEM_MOVESIZEEND) {
WinGetPos,, Y,,, ahk_id %hwnd%
if (Y <= 0)
WinMove, ahk_id %hwnd%,, start.x, start.y
}
}
class WinEventHook
{
; Event Constants: https://is.gd/tRT5Wr
__New(eventMin, eventMax, hookProc, eventInfo := 0, idProcess := 0, idThread := 0, dwFlags := 0) {
this.pCallback := RegisterCallback(hookProc, "F",, eventInfo)
this.hHook := DllCall("SetWinEventHook", "UInt", eventMin, "UInt", eventMax, "Ptr", 0, "Ptr", this.pCallback
, "UInt", idProcess, "UInt", idThread, "UInt", dwFlags, "Ptr")
}
__Delete() {
DllCall("UnhookWinEvent", "Ptr", this.hHook)
DllCall("GlobalFree", "Ptr", this.pCallback, "Ptr")
}
}
-
- Posts: 343
- Joined: 08 Jun 2019, 17:36
Re: Disable a gui from resetting the the Y position to 0 when released
wineventhook is good for this or you could use a simple drag from anywhere script.
https://www.autohotkey.com/boards/viewtopic.php?t=80352
https://www.autohotkey.com/boards/viewtopic.php?t=80352
Re: Disable a gui from resetting the the Y position to 0 when released
@teadrinker
Thank you for the reply.
I think that my example may have given the wrong impression about what is happening and what I'm looking for (sorry about that).
Here is a little demo that shows more or less what can't be seen.
As you will see with that demo if you were to try to move the "Move Window" text control up to the top of a monitor that doesn't have another monitor above it, it will snap the guis y position to be the top of the monitor rather than just staying where it is when you release it (which is what I want to do). I want to disable that "Snapping to Top" feature.
Thank you for the reply.
I think that my example may have given the wrong impression about what is happening and what I'm looking for (sorry about that).
Here is a little demo that shows more or less what can't be seen.
Code: Select all
#SingleInstance, Force
Gui, 1:+AlwaysOnTop -Caption -DPIScale
Gui, 1:Color, 22262A
Gui, 1:Add, Text,cWhite x0 y335 w100 h70 Border Center gMoveWindow, Move `n Window
Gui, 1:Show, x200 y100 w2000 h700
return
GuiContextMenu:
*ESC::ExitApp
MoveWindow:
PostMessage, 0xA1, 2
return
Re: Disable a gui from resetting the the Y position to 0 when released
Thank you for the link Dave, but it looks like that is about another issue. I have just posted something that hopefully fills any gaps that I may have missed in my first post.doubledave22 wrote: ↑21 Jun 2021, 15:45wineventhook is good for this or you could use a simple drag from anywhere script.
https://www.autohotkey.com/boards/viewtopic.php?t=80352
-
- Posts: 343
- Joined: 08 Jun 2019, 17:36
Re: Disable a gui from resetting the the Y position to 0 when released
Tried your example... its certainly acting strangely. That said... have you tried teadrinkers or a drag+drop script to move the window instead of PostMessage, 0xA1, 2?
In your example the window itself is actually getting chopped down. I tried dragging it above the monitor and back into view and the GUI seems to cut itself down. I'm guessing it gets redraw and the "move window" box resets its coordinates based on the new window height. Maybe winmove wont do this (both our options used winmove instead)
-
- Posts: 4330
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Disable a gui from resetting the the Y position to 0 when released
Got it. In this case you can realise an algorythm like @doubledave22 provided.
My try:
Code: Select all
#SingleInstance, Force
SetBatchLines, -1
SetWinDelay, 0
Gui, 1:+AlwaysOnTop -Caption -DPIScale +hwndhGui
obj := {hwnd: hGui}
pObj := Object(obj)
Gui, 1:Color, 22262A
Gui, 1:Add, Text,cWhite x0 y335 w100 h70 Border Center gMoveWindow, Move `n Window
Gui, 1:Show, x200 y100 w2000 h700
return
GuiContextMenu:
*ESC::ExitApp
MoveWindow:
CoordMode, Mouse
MouseGetPos, X_Mouse, Y_Mouse
WinGetPos, X_Gui, Y_Gui,,, % "ahk_id " . obj.hwnd
obj.dX := X_Gui - X_Mouse, obj.dY := Y_Gui - Y_Mouse
Hook := new WindowsHook(WH_MOUSE_LL := 14, "LowLevelMouseProc", pObj)
KeyWait, LButton
Hook := ""
return
LowLevelMouseProc(nCode, wParam, lParam) {
static WM_MOUSEMOVE := 0x200, obj
(!obj && obj := Object(A_EventInfo))
msg := wParam
if (msg = WM_MOUSEMOVE) {
mouse_x := NumGet(lParam + 0, "Int")
mouse_y := NumGet(lParam + 4, "Int")
timer := Func("EventHandler").Bind(obj, mouse_x, mouse_y)
SetTimer, % timer, -10
}
Return DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "UInt", wParam, "Ptr", lParam)
}
EventHandler(obj, x, y) {
WinMove, % "ahk_id" . obj.hwnd,, x + obj.dX, y + obj.dY
}
class WindowsHook {
__New(type, callback, eventInfo := "", isGlobal := true) {
this.pCallback := RegisterCallback(callback, "Fast", 3, eventInfo)
this.hHook := DllCall("SetWindowsHookEx", "Int", type, "Ptr", this.pCallback
, "Ptr", !isGlobal ? 0 : DllCall("GetModuleHandle", "UInt", 0, "Ptr")
, "UInt", isGlobal ? 0 : DllCall("GetCurrentThreadId"), "Ptr")
}
__Delete() {
DllCall("UnhookWindowsHookEx", "Ptr", this.hHook)
DllCall("GlobalFree", "Ptr", this.pCallback, "Ptr")
}
}
Re: Disable a gui from resetting the the Y position to 0 when released
@doubledave22
This approximates the effect that I'm going for.
Either way that sounds like it is only a graphical thing. (kind of like how you can set windows to only draw a border when moving a window)
This approximates the effect that I'm going for.
Code: Select all
#SingleInstance, Force
Gui, 1:+AlwaysOnTop -Caption -DPIScale
Gui, 1:Color, 22262A
Gui, 1:Add, Text,cWhite x0 y335 w100 h70 Border Center gMoveWindow, Move `n Window
Gui, 1:Show, x200 y100 w2000 h700
return
GuiContextMenu:
*ESC::ExitApp
MoveWindow:
CoordMode, Mouse, Screen
PostMessage, 0xA1, 2
While(GetKeyState("LButton"))
sleep, 10
MouseGetPos,,Y
Gui, Show, % "y" Y - 335
return
I'm not sure if I'm reading that correct, but it sounds like a windows setting or version thing. I'm on windows 8.1doubledave22 wrote: ↑21 Jun 2021, 16:25In your example the window itself is actually getting chopped down. I tried dragging it above the monitor and back into view and the GUI seems to cut itself down.
Either way that sounds like it is only a graphical thing. (kind of like how you can set windows to only draw a border when moving a window)
-
- Posts: 343
- Joined: 08 Jun 2019, 17:36
Re: Disable a gui from resetting the the Y position to 0 when released
haha i just wrote up a near similar example:
but make sure to comment out postmessage
Code: Select all
#SingleInstance, Force
Gui, 1:+AlwaysOnTop -Caption -DPIScale +HWNDTest123
Gui, 1:Color, 22262A
Gui, 1:Add, Text,cWhite x0 y335 w100 h70 Border Center gMoveWindow, Move `n Window
Gui, 1:Show, x200 y100 w2000 h700
return
GuiContextMenu:
*ESC::ExitApp
MoveWindow:
;~ PostMessage, 0xA1, 2,,, A
while (GetKeystate("LButton","P"))
{
coordmode, mouse, screen
mousegetpos, mX, mY
winmove, % "ahk_id " Test123, ,mX, mY-400
}
return
Re: Disable a gui from resetting the the Y position to 0 when released
@teadrinker
That works quiet well. I think that I can adapt that to suit my needs.
That works quiet well. I think that I can adapt that to suit my needs.
-
- Posts: 343
- Joined: 08 Jun 2019, 17:36
Re: Disable a gui from resetting the the Y position to 0 when released
I'm on windows 10. yes use teadrinkers solution. It seems that winmove doesn't have the same issue you are having
-
- Posts: 4330
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Disable a gui from resetting the the Y position to 0 when released
@doubledave22
It works more smoothly with a mouse hook.
It works more smoothly with a mouse hook.
-
- Posts: 343
- Joined: 08 Jun 2019, 17:36
Re: Disable a gui from resetting the the Y position to 0 when released
yeah I should switch my stuff over... thanks!
Re: Disable a gui from resetting the the Y position to 0 when released
Thank you @teadrinker and @doubledave22
I had hoped for something like this.
But I knew it was a long shot at best. That window hooking should prove useful.
I had hoped for something like this.
Code: Select all
Gui, New, -E0x0FF0F ;Disable "Snap-To-Top"
-
- Posts: 4330
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Disable a gui from resetting the the Y position to 0 when released
No lol. I have no idea if 0x0FF0F does anything at all, I just made that up as an example of what I was really hoping for. Something super simple that takes up 0 lines of code. (0 lines because Gui, New, +AlwaysOnTop ... etc)teadrinker wrote: ↑21 Jun 2021, 17:01I now on Windows 7, for me this doesn't work. Do you know, what the ExStyle is 0x0FF0F? I haven't found.
Like I said, I knew it was a long shot that something like it exists but it kind of feels like there should be something that interrupts the process of checking if a window is outside the top of the screen and resets the position.
-
- Posts: 4330
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Disable a gui from resetting the the Y position to 0 when released
Hm, just tried on Windows 10:
Doesn't work either.
Code: Select all
#SingleInstance, Force
Gui, 1: +AlwaysOnTop -Caption -DPIScale -E0x0FF0F
Gui, 1:Color, 22262A
Gui, 1:Add, Text,cWhite x0 y335 w100 h70 Border Center gMoveWindow, Move `n Window
Gui, 1:Show, x200 y100 w2000 h700
return
GuiContextMenu:
*ESC::ExitApp
MoveWindow:
PostMessage, 0xA1, 2
return
Re: Disable a gui from resetting the the Y position to 0 when released
@teadrinker
Yeah, I just made that number up
When I started out I had a sense that there must be some process that once a window has been moved and released a bit of code checks to see if the window is in the bounds of all monitors and if it is outside the bounds it sets the position to be the top of the best fit monitor. I was hoping that there was something that would tell it to not do that check and just leave the window where it was moved to. (Disable snap-to-top kind of thing)
Yeah, I just made that number up
When I started out I had a sense that there must be some process that once a window has been moved and released a bit of code checks to see if the window is in the bounds of all monitors and if it is outside the bounds it sets the position to be the top of the best fit monitor. I was hoping that there was something that would tell it to not do that check and just leave the window where it was moved to. (Disable snap-to-top kind of thing)
Re: Disable a gui from resetting the the Y position to 0 when released Topic is solved
http://web.archive.org/web/20131112230756/http://stackoverflow.com/questions/6645085/move-a-window-partially-off-the-top-of-the-screen
Code: Select all
#SingleInstance, Force
global hwndGui
Gui, 1:+AlwaysOnTop -Caption -DPIScale +HwndhwndGui
Gui, 1:Color, 22262A
global hwndButton
Gui, 1:Add, Text,cWhite x0 y335 w100 h70 Border Center gMoveWindow HwndhwndButton, Move `n Window
Gui, 1:Show, x200 y100 w200 h700
global in_movesize_loop := false
global inhibit_movesize_loop := false
OnMessage(0x0231, "WM_ENTERSIZEMOVE")
WM_ENTERSIZEMOVE(wParam, lParam, msg, hwnd) {
if (hwnd = hwndGui)
{
in_movesize_loop := true
inhibit_movesize_loop := false
return 0
}
}
OnMessage(0x0232, "WM_EXITSIZEMOVE")
WM_EXITSIZEMOVE(wParam, lParam, msg, hwnd) {
if (hwnd = hwndGui)
{
in_movesize_loop := false
inhibit_movesize_loop := false
return 0
}
}
OnMessage(0x0215, "WM_CAPTURECHANGED")
WM_CAPTURECHANGED(wParam, lParam, msg, hwnd) {
if (hwnd = hwndGui)
{
inhibit_movesize_loop := in_movesize_loop
return 0
}
}
OnMessage(0x0046, "WM_WINDOWPOSCHANGING")
WM_WINDOWPOSCHANGING(wParam, lParam, msg, hwnd) {
if (hwnd = hwndGui)
{
if inhibit_movesize_loop
{
flags := NumGet(lParam + 32, "UInt")
NumPut(flags | 0x0002, lParam + 32, "UInt") ; |= SWP_NOMOVE
return 0
}
}
}
GuiContextMenu:
*ESC::ExitApp
MoveWindow:
PostMessage, 0xA1, 2
return
-
- Posts: 4330
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Disable a gui from resetting the the Y position to 0 when released
@swagfag
Thanks, interesting. Looks like the code can be simplified like this:
Thanks, interesting. Looks like the code can be simplified like this:
Code: Select all
global hwndGui, WM_CAPTURECHANGED := 0x0215, WM_WINDOWPOSCHANGING := 0x0046
Gui, 1:+AlwaysOnTop -Caption -DPIScale +HwndhwndGui
Gui, 1:Color, 22262A
Gui, 1:Add, Text,cWhite x0 y335 w100 h70 Border Center gMoveWindow, Move `n Window
Gui, 1:Show, x200 y100 w200 h700
OnMessage(WM_CAPTURECHANGED, "MessageHandler")
OnMessage(WM_WINDOWPOSCHANGING, "MessageHandler")
Return
MessageHandler(wParam, lParam, msg, hwnd) {
static inhibit_movesize_loop := true
if (hwnd = hwndGui) {
Switch msg {
Case WM_CAPTURECHANGED: inhibit_movesize_loop := !inhibit_movesize_loop
Case WM_WINDOWPOSCHANGING:
if inhibit_movesize_loop {
flags := NumGet(lParam + A_PtrSize*2 + 16, "UInt")
NumPut(flags | 0x0002, lParam + A_PtrSize*2 + 16, "UInt") ; |= SWP_NOMOVE
}
}
}
}
GuiContextMenu:
*ESC::ExitApp
MoveWindow:
PostMessage, 0xA1, 2
return
Who is online
Users browsing this forum: OrangeCat and 288 guests