How to catch right click on a gui anywhere including its controls?

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
RUBn
Posts: 51
Joined: 27 Nov 2013, 05:12
Contact:

How to catch right click on a gui anywhere including its controls?

12 Feb 2024, 07:55

I need to destroy a gui (window) whenever the user right clicks anywhere on the window, including on the controls it contains. So far I use g.OnEvent("ContextMenu", Clack, -1) but the right clicks from my edits don't come through, although from pictures it do. In the edit the contextmenu pops up even though I made them readonly.

I found this in the OnEvent: "Note: Since Edit and MonthCal controls have their own context menu, a right-click in one of them will not launch the ContextMenu event."
But I need these edits since text controls don't give an option for good wrapping

Any solution?

Code: Select all

	g := Gui("+AlwaysOnTop -Caption +ToolWindow +LastFound")
	g.OnEvent("ContextMenu", Clack, -1)
	g.AddPicture("x10 y10 w48 h-1 Section Icon +0x100" I,F)	
	g.AddEdit((ico ? "xs+48 ys" : "") " w" W0 " Background" g.BackColor " -VScroll -E0x200 Center vt 0x800", titl)	; Using readonly edit for word-cut-wrapping for fixed width
	g.AddEdit((ico ? " xs+48" : "") " w" W0 " Background" g.BackColor " -VScroll -E0x200 y+5 Center 0x80 0x800", tip)
	
	Clack(g,params*){
		for i,param in params
			  str .= i . param . " "
		MsgBox(str)
		g.Destroy
	}
User avatar
boiler
Posts: 17404
Joined: 21 Dec 2014, 02:44

Re: How to catch right click on a gui anywhere including its controls?

12 Feb 2024, 08:20

You can set a hotkey for the right mouse button that is only active when over the GUI:

Code: Select all

MyGui := Gui()
MyGui.Add('Edit')
MyGui.Add('Button',, 'My Button')
MyGui.Show

#HotIf MouseIsOver(MyGui.Hwnd)
RButton::MyGui.Destroy

MouseIsOver(hwnd) {
    MouseGetPos ,, &targetHwnd
    return hwnd = targetHwnd
}
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: How to catch right click on a gui anywhere including its controls?

12 Feb 2024, 10:34

Or you can use OnMessage():

Code: Select all

#Requires AutoHotkey v2.0
MyGui := Gui()
MyGui.Add('Edit')
MyGui.Add('Button',, 'My Button')
MyGui.Show
OnMessage(0x0204, (*) => MyGui.Destroy()) ; WM_RBUTTONDOWN = 0x0204
User avatar
RUBn
Posts: 51
Joined: 27 Nov 2013, 05:12
Contact:

Re: How to catch right click on a gui anywhere including its controls?

28 Feb 2024, 08:46

just me wrote:
12 Feb 2024, 10:34
Or you can use OnMessage():....
Thanks, but unfortunately it still triggers the context menu of the edit controls. I wonder how one could disable them. Or I''ll try the other answer here first maybe.
boiler wrote:
12 Feb 2024, 08:20
You can set a hotkey for the right mouse button that is only active when over the GUI:

Code: Select all

MyGui := Gui()
MyGui.Add('Edit')
MyGui.Add('Button',, 'My Button')
MyGui.Show

#HotIf MouseIsOver(MyGui.Hwnd)
RButton::MyGui.Destroy

MouseIsOver(hwnd) {
    MouseGetPos ,, &targetHwnd
    return hwnd = targetHwnd
}
Could be the solution, but I have undetermined amount of gui's. Not sure how to solve that with this solution,

I am also: Image-motiv for professional, volunteer & open source (web) development
User avatar
boiler
Posts: 17404
Joined: 21 Dec 2014, 02:44

Re: How to catch right click on a gui anywhere including its controls?

28 Feb 2024, 09:22

RUBn wrote: Could be the solution, but I have undetermined amount of gui's. Not sure how to solve that with this solution,
You could add the HWND to an array for each GUI created, then the function would check against the whole list of HWNDs in the array and return true if the mouse is over any of them.
User avatar
RUBn
Posts: 51
Joined: 27 Nov 2013, 05:12
Contact:

Re: How to catch right click on a gui anywhere including its controls?

04 Mar 2024, 08:40

boiler wrote:
28 Feb 2024, 09:22
RUBn wrote: Could be the solution, but I have undetermined amount of gui's. Not sure how to solve that with this solution,
You could add the HWND to an array for each GUI created, then the function would check against the whole list of HWNDs in the array and return true if the mouse is over any of them.
Thanks. I tried it, but I need it inside a nested function and I couldn't integrate the Hotif inside. So I took your method and tried to translate it into a nested function. Code below. Tell me if there is a more effeftive way, like with this HotIf inside a nested function...?

Code: Select all

myTrayTip(tip, titl:="Autohotkey", secs:=3, ico:=-1, Sound:="*64") {
	static WF:=258, trayTop,scrRight, scrBot:=0, trayMap:=Map()
	
	...
	
	g := Gui("+AlwaysOnTop -Caption +ToolWindow +LastFound")
	
	...
	
	trayMap[g]:={
	
	...
	
	}
	
	...
	
	if trayMap.Count <= 1 {
	
	...
	
		Hotkey "~RButton UP", MouseOverThenDestroy
	}
	
	remove(g) {
		trayMap.Delete(g)
		g.Destroy()
	}
	
	MouseOverThenDestroy(n) {
		for g,tray in trayMap {
		 MouseGetPos ,, &targetHwnd
		 if g.Hwnd = targetHwnd
			remove(g)
		}
	
	...
	
		if trayMap.Count = 0 {
				SetTimer , 0	
				Hotkey "~RButton UP", "Off"
			}
	
	...
	
	}
	
}

I am also: Image-motiv for professional, volunteer & open source (web) development
User avatar
Seven0528
Posts: 413
Joined: 23 Jan 2023, 04:52
Location: South Korea
Contact:

Re: How to catch right click on a gui anywhere including its controls?

04 Mar 2024, 09:36

Code: Select all

#Requires AutoHotkey v2.0
#SingleInstance Force
MyGui:=gui()
MyGui.add("Edit","w400 r5")
MyGui.add("MonthCal","w400")
MyGui.show()
onMessage(0x0205, WM_RBUTTONUP)

WM_RBUTTONUP(wParam, lParam, msg, hWnd)    {
    static GA_ROOT:=2
    guiHwnd:=dllCall("User32.dll\GetAncestor", "Ptr",hWnd, "UInt",GA_ROOT, "Ptr")
    controlHwnd:=hWnd
    switch (guiHwnd)
    {
        case MyGui.Hwnd:
            if (controlHwnd==guiHwnd) ;  If clicked on the background...
                return
            switch (getClassName(controlHwnd))
            {
                case "Edit":                return 0
                case "SysMonthCal32":
            }
    }
    /*
    If you want to interrupt the WM_RBUTTONUP, return 0.
    For more detailed information, please refer to the MSDN documentation.
    */
}
;   WM_RBUTTONUP message
;  https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-rbuttonup

GetClassName(hWnd, nMaxCount:=1024)    { ;  ahk2.0
    ;  static MAX_CLASS_NAME:=1024
    lpClassName:=buffer(2*nMaxCount,0)
    return (dllCall("User32.dll\GetClassName", "Ptr",hWnd, "Ptr",lpClassName.Ptr, "Int",nMaxCount, "Int"))
        ?strGet(lpClassName)
        :""
}
;   GetClassName function (winuser.h)
;  https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclassname
  • English is not my native language. Please forgive any awkward expressions.
  • 영어는 제 모국어가 아닙니다. 어색한 표현이 있어도 양해해 주세요.

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: pond_pop, Xeilous and 73 guests