GUI that does not become the foreground window when the user clicks it

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

GUI that does not become the foreground window when the user clicks it

Post by A_AhkUser » 10 Jul 2018, 02:56

I know a GUI window can be endowed with the WS_EX_NOACTIVATE extended style. However, it appears that this does not account for those cases when a user click causes an ahk GUI to take the place of another one; in the following example, if I 'come from' test1, test2 is activated:

Code: Select all

#NoEnv
#Warn
#SingleInstance force

Loop, 2 {
	GUI, %a_index%:New
	if (a_index = 2)
		GUI, +AlwaysOnTop +E0x08000000
	GUI, Show, % "w300 h300 NoActivate x" . 100 + (a_index) * 310, test%a_index%
}
return

GuiClose:
ExitApp
So my first question is, am I missing something? Otherwise, is it possible to create a GUI that does not become the foreground window when the user clicks it - deactivating in doing so another ahk GUI?
Background: I strive to create a window behaving the same way as a dropdown list menu. At this time, I use the +Parent option which is, at least, inadequate.

Thanks!
my scripts

A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: GUI that does not become the foreground window when the user clicks it

Post by A_AhkUser » 10 Jul 2018, 11:25

Here's maybe a kinda workaround - however, ideally, I don' want to use OnMessage :headwall:

Code: Select all

; https://www.codeproject.com/Questions/751002/Show-Window-without-activating#ctl00_ctl00_MC_AMC_Answers_ctl01_A_AnswerGroup
#NoEnv
#Warn
#SingleInstance force

Loop, 2 {
	GUI, %a_index%:New
	if (a_index = 2)
		GUI, +AlwaysOnTop +E0x08000080 +hwndGUIID
	GUI, Show, % "w300 h300 NoActivate x" . 100 + (a_index) * 310, test%a_index%
}
OnMessage(0x0021, "WM_MOUSEACTIVATE")
return


WM_MOUSEACTIVATE(_wParam, _lParam) {
static MA_NOACTIVATE := 3, MA_ACTIVATE := 1 ; https://docs.microsoft.com/fr-fr/windows/desktop/inputdev/wm-mouseactivate
global GUIID
if (_wParam = GUIID)
	return MA_NOACTIVATE
return MA_ACTIVATE
}
GuiClose:
ExitApp
my scripts

A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: GUI that does not become the foreground window when the user clicks it

Post by A_AhkUser » 13 Jan 2019, 18:10

A final revival in case a knowledgeable or creative look can resolve this situation. :headwall:
my scripts

A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: GUI that does not become the foreground window when the user clicks it

Post by A_AhkUser » 19 Jan 2019, 18:08

So I finally came up with something like the following:

Code: Select all

#NoEnv
#SingleInstance force
#Warn
; Windows 8.1 64 bit - Autohotkey v1.1.30.01 32-bit Unicode

GUI, New, +LastFound
GUI, Add, Edit, w400 h400
GUI, Show, AutoSize

WS_EX_NOACTIVATE := 0x08000000 ; A top-level window created with this style does not become the foreground window when the user clicks it.
WS_EX_WINDOWEDGE := 0x00000100 ; The window has a border with a raised edge.
WS_EX_TOOLWINDOW := 0x00000080 ; A tool window does not appear in the taskbar or in the dialog that appears when the user presses ALT+TAB.
WS_EX_TOPMOST := 0x00000008 ; The window should be placed above all non-topmost windows and should stay above them, even when the window is deactivated.
WS_EX_PALETTEWINDOW := (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST)

GUI New, % "+Owner" . WinExist()
GUI, +HWNDhGUI +LastFound
DetectHiddenWindows, On
WinSet, Transparent, 215
DetectHiddenWindows, Off
GUI, Margin, 0, 0
GUI +E%WS_EX_PALETTEWINDOW% +E%WS_EX_NOACTIVATE%
GUI, -Caption
GUI, Add, ListBox, x0 y0 w110 h140 +HWNDhListbox, a|b|c|d|e|f|g|h|i|j|k|l|m|n
GUI, Show, AutoSize NoActivate,

WM_MOUSEACTIVATE := 0x0021 ; this message is sent when the cursor is in an inactive window and the user presses a mouse button
OnMessage(WM_MOUSEACTIVATE, Func("__WM_MOUSEACTIVATE").bind(hGUI, hListBox))
return

GuiClose:
ExitApp

__WM_MOUSEACTIVATE(_hGUI, _hListBox, _wParam) {
static MA_ACTIVATE := 1
	, MA_NOACTIVATE := 3
	, MA_NOACTIVATEANDEAT := 4 ; https://docs.microsoft.com/fr-fr/windows/desktop/inputdev/wm-mouseactivate#return-value
static LB_SETCURSEL := 0x0186 ; https://docs.microsoft.com/fr-fr/windows/desktop/Controls/lb-setcursel (https://github.com/AHK-just-me/AHK_Gui_Constants/blob/master/Sources/Const_ListBox.ahk)
	local
	Critical
	if ((_wParam = _hGUI)) { ; if we're talking about our GUI...
		_item := LBEX_ItemFromCursor(_hListBox) ; get the zero-based index of the item nearest the cursor in the list box
		if (_item > -1) {
			PostMessage % LB_SETCURSEL, % _item, 0,, % "ahk_id " . _hListBox ; update the ListBox's selection
		return MA_NOACTIVATEANDEAT ; does not activate the window, and discards the mouse message
		} else ; with the design with wich we've endowed our GUI here, this means the cursor is currently hovering over the scroll bar
			return MA_NOACTIVATE ; does not activate the window, and does not discard the mouse message
	} else return MA_ACTIVATE
}

LBEX_ItemFromCursor(_hListBox) { ; LBEX_ItemFromCursor by 'just me' - https://www.autohotkey.com/boards/viewtopic.php?p=66813#profile66885
	static LB_ITEMFROMPOINT := 0x01A9
	local
	VarSetCapacity(_POINT_, 8, 0) ; POINT structure -> msdn.microsoft.com/en-us/library/dd162805(v=vs.85).aspx
	DllCall("GetCursorPos", "Ptr", &_POINT_) ; -> msdn.microsoft.com/en-us/library/ms648390(v=vs.85).aspx
	DllCall("ScreenToClient", "Ptr", _hListBox, "Ptr", &_POINT_) ; -> msdn.microsoft.com/en-us/library/dd162952(v=vs.85).aspx
	_x := NumGet(_POINT_, 0, "UShort") ; only 16 bits are used by LB_ITEMFROMPOINT
	_y := NumGet(_POINT_, 4, "UShort") << 16 ; only 16 bits are used by LB_ITEMFROMPOINT
	SendMessage % LB_ITEMFROMPOINT, 0, % (_x + _y),, % "ahk_id " . _hListBox ; LB_ITEMFROMPOINT -> msdn.microsoft.com/en-us/library/bb761323(v=vs.85).aspx
	if (ErrorLevel & 0xFFFF0000) ; the HIWORD of the return value is one if the cursor is outside the client area.
	return -1
	return (ErrorLevel & 0xFFFF) ; the return value contains the 0-based index of the item in the LOWORD.
}
Btw, once again this would not have been imaginable and possible for me without the invaluable working tools available upstream on the forum and shared by 'just me'.
my scripts

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: GUI that does not become the foreground window when the user clicks it

Post by doubledave22 » 19 Jan 2022, 12:13

Hi, I just wanted to say thank you for following up on your own issue here. Ran into this exact problem today with a +Owner GUI and not wanting to take focus from the owner on click of our GUI and processing WM_MOUSEACTIVATE solved it perfectly. You are my hero :)

Post Reply

Return to “Ask for Help (v1)”