Processing Ajax...

Title

Message

Confirm

Confirm

Confirm

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure you want to delete this item?

Bring the Window Under the Mouse Cursor to the Front

Description
This script will bring the window that's under the mouse cursor to the front and give it focus.
Language
C#.net
Minimum Version
Created By
Thomas Malloch (BFS)
Contributors
-
Date Created
May 27, 2015
Date Last Modified
May 27, 2020

Scripted Function (Macro) Code

using System;
using System.Drawing;
using System.Collections.Generic;
using System.Runtime.InteropServices;

// The 'windowHandle' parameter will contain the window handle for the:
//   - Active window when run by hotkey
//   - Window Location target when run by a Window Location rule
//   - TitleBar Button owner when run by a TitleBar Button
//   - Jump List owner when run from a Taskbar Jump List
//   - Currently focused window if none of these match
public static class DisplayFusionFunction
{
	public static void Run(IntPtr windowHandle)
	{
		//a list to store the potential windows
		List<IntPtr> windows = new List<IntPtr>();
		
		//get the current position of the mouse
		Point mousePosition = new Point(BFS.Input.GetMousePositionX(), BFS.Input.GetMousePositionY());
		
		//loop through all of the visible windows
		foreach(IntPtr window in BFS.Window.GetVisibleWindowHandles())
		{
			//skip any DisplayFusion window (title bar buttons, etc) or the search pane
			string windowClass = BFS.Window.GetClass(window);
			if(windowClass.StartsWith("DF", StringComparison.Ordinal) || 
			   windowClass.Equals("SearchPane", StringComparison.Ordinal) ||
			   windowClass.Equals("ImmersiveLauncher", StringComparison.Ordinal) ||
			   windowClass.Equals("Windows.UI.Core.CoreWindow", StringComparison.Ordinal) ||
               windowClass.Equals("WorkerW", StringComparison.Ordinal))		   
		   {
				continue;
		   }

		   //skip if this is the charms bar
			if(BFS.Window.GetText(window).Equals("Charm Bar", StringComparison.Ordinal))
				continue;
				
			//get the bounds of the window and see if the mouse is over it
			Rectangle bounds = BFS.Window.GetBounds(window);
			if(!bounds.Contains(mousePosition))
				continue;
				
			//if it's over it, add it to the potential windows
			windows.Add(window);
		}
		
		//we found no eligable windows, exit
		if(windows.Count == 0)
			return;
			
		//sort the windows by their z-order
		windows.Sort(ZOrderComparer.Instance);
		
		//the first window in the list should now be the topmost window.
		//focus and maximize it
		BFS.Window.Focus(windows[0]);
	}
	
	//this custom comparer will sort window handles by their z-order
	private class ZOrderComparer : IComparer<IntPtr>
	{
		//this function is needed to find the z-order of windows
		[DllImport("User32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
		private static extern IntPtr GetWindow(IntPtr hWnd, GetWindowCommandEnum uCmd);
		
		//an enum so we can only put valid parameters into the GetWindow function
		private enum GetWindowCommandEnum : uint 
		{
			GW_CHILD = 5,
			GW_ENABLEDPOPUP = 6,
			GW_HWNDFIRST = 0,
			GW_HWNDLAST = 1,
			GW_HWNDNEXT = 2,
			GW_HWNDPREV = 3,
			GW_OWNER = 4,
		}
	
		//make it so this class only gets created once for the life of the script
		private static ZOrderComparer _Instance = null;
		internal static ZOrderComparer Instance 
		{
			get 
			{
				if(_Instance == null)
					_Instance = new ZOrderComparer();
					
				return _Instance;
			}
		}
		
		private ZOrderComparer(){}
		
		//a function that gets the z-order of windows. static to boost the speed a little
		private static int GetWindowZOrder(IntPtr handle)
		{
			int order = 0;
			for (IntPtr h = handle; h != IntPtr.Zero; h = GetWindow(h, GetWindowCommandEnum.GW_HWNDPREV))
				order++;
				
			return order;
		}
		
		//get the z-order of the windows and compare them
		public int Compare(IntPtr first, IntPtr second)
		{
			int z1 = GetWindowZOrder(first);
			int z2 = GetWindowZOrder(second);
			if(z1 > z2)
				return 1;
				
			if(z1 < z2)
				return -1;
				
			return 0;
		}
	}
}