Bring to front multiple windows

Hi!
I'm trying to bring up multiple windows when clicking on one of them (e.g. bring to front Graph1, Graph2 and Graph3 -- with Graph2 being the topmost -- when clicking on Graph2). The only solution I came up so far is to define a window hook for all windows I want to show up together like this:


Function myHook(s)
	STRUCT WMWinHookStruct &s
	
	NVAR clicked = root:clicked
	Variable i
	String WindowList = "Graph1;Graph2;Graph3;"
	String clickedWin = s.winName, currWin
	
	
	if ( s.eventCode == 0 )
		if ( abs(clicked - s.ticks) < 1 )
			return 0
		else
			clicked = s.ticks
		endif
		
		for (i=0; i<ItemsInList(WindowList); i+=1)
			currWin = StringFromList(i, WindowList)
			DoWindow /F $currWin
		endfor
		DoWindow /F $clickedWin
	endif
End

Function DemoWindows()
 	Display /N=Graph1; SetWindow Graph1, hook(myHook) = myHook
 	Display /N=Graph2; SetWindow Graph2, hook(myHook) = myHook
 	Display /N=Graph3; SetWindow Graph3, hook(myHook) = myHook
End


The reason I have to use the global variable ("clicked") is to avoid recursion, that is when clicking on Graph2, Graph1 is going to front, which in turn results in a call of "myHook".

Is there a more elegant way of doing this?

Cheers
A slightly less inelegant solution would be to disable the window hook functions at the start of your event handler and reenable them just before exiting the event handler. But this presupposes that you know which windows to act on.
Window user data is useful for stuff like this. Try this code. Before running DoWindow /F on the another window, it flags it with a named userdata called "UserClicked", then unflags it after. It still looks disappointingly "flickery" on my screen but is definitely less kludgey than using the computer timer to distinguish automated events. If you uncomment the print statements, you can see that each window is only brought to the front once except the originally clicked window. I cannot think of a way around needing that last DoWindow /F call.


Function myHook(s)
	STRUCT WMWinHookStruct &s
	Variable i
	String WindowList = "Graph1;Graph2;Graph3;"
	String clickedWin = s.winName, currWin
	string flaglist = RemoveFromList(s.winName,WindowList)
	
	if ( s.eventCode == 0 )
		if (!stringmatch(GetUserData(S.winName,"","UserClicked"),"N"))	// This should only be true for the first window the user clicked
			
//			print S.winName + " was clicked"
			for (i=0; i
Recently I had a similar challenge when I needed to bring up projections when selecting a broadband transient absorption spectrum. It seemed doable, because the window names of the projections were just as the parent spectrum, just a suffix was added. So the hook could be general.

However, Dowindow/F is a bit too powerful, it not only brings a window to the front, but also activates it.

The simple solution is put everything else behind it! Just use Dowindow/B inside a for-loop over the items of WinList. Import is the beginning, end and direction of the loop. And exclude the one you need to keep on top. Here's an example (I didn't run it, but it gets the point across):


Function Familyontop(s)
	STRUCT WMWinHookStruct &s 
	if(s.eventCode==0)	// eventcode 0 = activate
		String Swin=s.winName//get name of window
		String Swindowstack=winlist("*",";","WIN:7,VISIBLE:1"),Snu // Which windows are on top?
		Variable Vgver=WhichListItem(Swin+"_ver",Swindowstack) // Where is the cousin with suffix "_ver"?
		
		String Sdeep=StringFromList(Vgver,Swindowstack,";")  // What is this cousin called?   
		
		For(n=Vgver-1;n>=0;n-=1)	// Loop over all graphs, tables and layouts above the graph 
			Snow=StringFromList(n,Swindowstack,";") // Current graph to slide under the cousin
			dowindow /B=$Vgver $Snow  // slide below graph of interest
		endfor

		return 1
	endif
	return 0	// Zorgt dat Igor ook nog hotkeys verwerkt.
End
Thanks for the fast replies!

Just to close this thread and if anybody has a similar problem, I ended up with this solution:


Function myHook(s)
	STRUCT WMWinHookStruct &s
 	
	Variable i
	String WindowList = "Graph1;Graph2;Graph3;" 
 	
	if ( s.eventCode == 0 )
 		WindowList = RemoveFromList(s.winName, WindowList)
		for (i=0; i<ItemsInList(WindowList); i+=1)
			String currWin = StringFromList(i, WindowList)
			DoWindow /B=$s.winName $currWin
		endfor
	endif
End
 
Function DemoWindows()
 	Display /N=Graph1; SetWindow Graph1, hook(myHook) = myHook
 	Display /N=Graph2; SetWindow Graph2, hook(myHook) = myHook
 	Display /N=Graph3; SetWindow Graph3, hook(myHook) = myHook
End


The window that is clicked on is brought to front automatically (which can't be prevented anyway) and all other windows that should go to front are brought to the background just behind the topmost window.

Cheers