MsgBox and WinMove

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
AmDeG 11
Posts: 388
Joined: 28 Nov 2013, 11:42

Re: MsgBox and WinMove

22 Jan 2018, 12:32

sorry I don't see the difference "WinClas vs"

please advise
teadrinker
Posts: 4358
Joined: 29 Mar 2015, 09:41
Contact:

Re: MsgBox and WinMove

22 Jan 2018, 12:42

Should be DllCall("GetClassName", Ptr, hwnd := wp, Str, WinClass, Int, 256)
AmDeG 11
Posts: 388
Joined: 28 Nov 2013, 11:42

Re: MsgBox and WinMove

22 Jan 2018, 12:47

great! now it works! thanks!
llinfeng
Posts: 86
Joined: 08 Dec 2016, 21:54
Contact:

Re: MsgBox and WinMove

27 Feb 2022, 09:12

Thanks to teadrinker's CBTProc function, here is a quick demo to summon a message box roughly at the center of the active window. (The Round function is needed, in short.)

Code: Select all

;  Assign to 1 for testing.
1::
    WinGetPos, X, Y, Width, Height, A  ; "A" to get the active window's pos.
        x_center := Round(X + Width/5*2)
        y_center := Round(Y + Height/2)
    msgbox,, Centered-Msg|x%x_center% y%y_center%, This msgbox is centered corresponding to the previous active window.
return



; And, the dependency part.
; Source: https://www.autohotkey.com/boards/viewtopic.php?t=37355
; From user: teadrinker
CBTProc(nCode, wp, lp)  {
   static WH_CBT := 5, HCBT_CREATEWND := 3
        , dummy := OnExit( Func("CBTProc").Bind("OnExit") )
        , hHook := DllCall("SetWindowsHookEx", Int, WH_CBT
                                             , Ptr, RegisterCallback("CBTProc", "Fast")
                                             , Ptr, 0
                                             , UInt, DllCall("GetCurrentThreadId") , Ptr)
   if (nCode = "OnExit")  {
      DllCall("UnhookWindowsHookEx", Ptr, hHook)
      return
   }
   if (nCode = HCBT_CREATEWND)  {
      VarSetCapacity(WinClass, 256)
      DllCall("GetClassName", Ptr, hwnd := wp, Str, WinClass, Int, 256)
      if (WinClass = "#32770")  {
         pCREATESTRUCT := NumGet(lp+0)
         sTitle := StrGet( pTitle := NumGet(pCREATESTRUCT + A_PtrSize * 5 + 4 * 4), "UTF-16" )
         RegExMatch(sTitle, "^(.*)\|(?:x(\d+)\s?)?(?:y(\d+))?$", match)
         ( !(match2 = "" && match3 = "") && StrPut(match1, pTitle, "UTF-16") )
         ( match2 != "" && NumPut(match2, pCREATESTRUCT + A_PtrSize * 4 + 4 * 3, "Int") )
         ( match3 != "" && NumPut(match3, pCREATESTRUCT + A_PtrSize * 4 + 4 * 2, "Int") )
      }
   }
   Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wp, Ptr, lp)
}

scatrmind
Posts: 8
Joined: 22 Mar 2021, 11:51

Re: MsgBox and WinMove

12 Apr 2023, 15:30

@teadrinker How do I get your code to work with negative coordinates such as when your primary monitor is on the right and your secondary monitor is on the left (meaning all x-coordinates on the secondary monitor are negative). When I try to get message boxes to appear on my secondary monitor, the message boxes appear on my primary monitor and the message box title includes the coordinates I specified. For example, if I use...

Code: Select all

MsgBox,, OH NO!|x-1160 y420, I don't know what I'm doing!
...the message box title is "OH NO!|x-1160 y420". However, if I make the coordinates positive in this example, the message box appears in the location specified and the message box title is "OH NO!" as expected.
User avatar
FanaticGuru
Posts: 1907
Joined: 30 Sep 2013, 22:25

Re: MsgBox and WinMove

12 Apr 2023, 16:55

scatrmind wrote:
12 Apr 2023, 15:30
@teadrinker How do I get your code to work with negative coordinates such as when your primary monitor is on the right and your secondary monitor is on the left (meaning all x-coordinates on the secondary monitor are negative). When I try to get message boxes to appear on my secondary monitor, the message boxes appear on my primary monitor and the message box title includes the coordinates I specified. For example, if I use...

Code: Select all

MsgBox,, OH NO!|x-1160 y420, I don't know what I'm doing!
...the message box title is "OH NO!|x-1160 y420". However, if I make the coordinates positive in this example, the message box appears in the location specified and the message box title is "OH NO!" as expected.

The RegExMatch is not designed to handle negative numbers:
RegExMatch(sTitle, "^(.*)\|(?:x(\d+)\s?)?(?:y(\d+))?$", match)

You could try changing to this:
RegExMatch(sTitle, "^(.*)\|(?:x(-?\d+)\s?)?(?:y(-?\d+))?$", match)

Now I don't know how the DllCall is going to handle the negative number but at least now the RegExMatch will look for it. I don't have two monitors.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
scatrmind
Posts: 8
Joined: 22 Mar 2021, 11:51

Re: MsgBox and WinMove

12 Apr 2023, 17:06

@FanaticGuru - Yes; it works! Thank you!
User avatar
FanaticGuru
Posts: 1907
Joined: 30 Sep 2013, 22:25

Re: MsgBox and WinMove

29 Apr 2024, 12:12

teadrinker wrote:
25 Sep 2017, 23:22
Made some changes to the code:

Code: Select all

MsgBox, This MessageBox will appear in the centre of screen, as usual
MsgBox,, |x50 y70, This MessageBox will appear in coords x = 50 y = 70 without a title.
MsgBox,, Hello!|x500 y0, This MessageBox will appear in coords x = 500 y = 0 with the title "Hello!"
Return

CBTProc(nCode, wp, lp)  {
   static WH_CBT := 5, HCBT_CREATEWND := 3
        , dummy := OnExit( Func("CBTProc").Bind("OnExit") )
        , hHook := DllCall("SetWindowsHookEx", Int, WH_CBT
                                             , Ptr, RegisterCallback("CBTProc", "Fast")
                                             , Ptr, 0
                                             , UInt, DllCall("GetCurrentThreadId") , Ptr)
   if (nCode = "OnExit")  {
      DllCall("UnhookWindowsHookEx", Ptr, hHook)
      return
   }
   if (nCode = HCBT_CREATEWND)  {
      VarSetCapacity(WinClass, 256)
      DllCall("GetClassName", Ptr, hwnd := wp, Str, WinClass, Int, 256)
      if (WinClass = "#32770")  {
         pCREATESTRUCT := NumGet(lp+0)
         sTitle := StrGet( pTitle := NumGet(pCREATESTRUCT + A_PtrSize * 5 + 4 * 4), "UTF-16" )
         RegExMatch(sTitle, "^(.*)\|(?:x(\d+)\s?)?(?:y(\d+))?$", match)
         ( !(match2 = "" && match3 = "") && StrPut(match1, pTitle, "UTF-16") )
         ( match2 != "" && NumPut(match2, pCREATESTRUCT + A_PtrSize * 4 + 4 * 3, "Int") )
         ( match3 != "" && NumPut(match3, pCREATESTRUCT + A_PtrSize * 4 + 4 * 2, "Int") )
      }
   }
   Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wp, Ptr, lp)
}

@teadrinker or someone else that knows magic, can you kindly convert this to v2 code. I tried but can't get it to work. I know the static initializing trick no longer works with v2 but even outside that I could not get it right.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
teadrinker
Posts: 4358
Joined: 29 Mar 2015, 09:41
Contact:

Re: MsgBox and WinMove

29 Apr 2024, 14:16

It will not be possible to translate this code to v2 exactly, because there is no mechanism in the second version that would create self-starting functions. The closest translation would be the following:

Code: Select all

#Requires AutoHotkey v2

inst := MsgBoxWithCoords()
MsgBox 'This MsgBox appears in coords x = 50 y = 70', 'title|x50 y70' ; coords are specified in the title after |

class MsgBoxWithCoords
{
    __New() {
        this.Hook := MsgBoxWithCoords.WindowsHook(WH_CBT := 5, CBTProc, false)

        CBTProc(nCode, wp, lp) {
            static HCBT_CREATEWND := 3
            if (nCode = HCBT_CREATEWND) {
                DetectHiddenWindows(true)
                if WinGetClass(wp) = '#32770' {
                    pCREATESTRUCT := NumGet(lp, 'Ptr')
                    title := StrGet(pTitle := NumGet(pCREATESTRUCT, A_PtrSize * 5 + 16, 'Ptr'))
                    RegExMatch(title, '^(.*)\|(?:x(-?\d+)\s?)?(?:y(-?\d+))?$', &m)
                    (!(m[2] = '' && m[3] = '') && StrPut(m[1], pTitle))
                    (m[2] != '' && NumPut('Int', m[2], pCREATESTRUCT, A_PtrSize * 4 + 12))
                    (m[3] != '' && NumPut('Int', m[3], pCREATESTRUCT, A_PtrSize * 4 +  8))
                }
            }
        }
    }

    __Delete() => this.DeleteProp('Hook')

    class WindowsHook {
        __New(type, callback, isGlobal := true) {
            this.callback := CallbackCreate(callback, 'Fast', 3)
            this.hHook := DllCall('SetWindowsHookEx', 'Int', type, 'Ptr', this.callback
                , 'Ptr', !isGlobal ? 0 : DllCall('GetModuleHandle', 'UInt', 0, 'Ptr')
                , 'UInt', isGlobal ? 0 : DllCall('GetCurrentThreadId'), 'Ptr')
        }

        __Delete() => (DllCall('UnhookWindowsHookEx', 'Ptr', this.hHook), CallbackFree(this.callback))
    }
}
However, for this code to work, you'll have to call inst := MsgBoxWithCoords() before calling MsgBox().

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: JPMuir, MHMD, starkel and 130 guests