mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-04 18:26:39 +02:00
whitespace forced changes (#6002)
This commit is contained in:
@@ -1,124 +1,124 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Class housing fuzzy matching methods
|
||||
/// </summary>
|
||||
public class FuzzyMatching
|
||||
{
|
||||
/// <summary>
|
||||
/// Finds the best match (the one with the most
|
||||
/// number of letters adjacent to each other) and
|
||||
/// returns the index location of each of the letters
|
||||
/// of the matches
|
||||
/// </summary>
|
||||
/// <param name="text">The text to search inside of</param>
|
||||
/// <param name="searchText">the text to search for</param>
|
||||
/// <returns>returns the index location of each of the letters of the matches</returns>
|
||||
public static List<int> FindBestFuzzyMatch(string text, string searchText)
|
||||
{
|
||||
searchText = searchText.ToLower();
|
||||
text = text.ToLower();
|
||||
|
||||
// Create a grid to march matches like
|
||||
// eg.
|
||||
// a b c a d e c f g
|
||||
// a x x
|
||||
// c x x
|
||||
bool[,] matches = new bool[text.Length, searchText.Length];
|
||||
for (int firstIndex = 0; firstIndex < text.Length; firstIndex++)
|
||||
{
|
||||
for (int secondIndex = 0; secondIndex < searchText.Length; secondIndex++)
|
||||
{
|
||||
matches[firstIndex, secondIndex] =
|
||||
searchText[secondIndex] == text[firstIndex] ?
|
||||
true :
|
||||
false;
|
||||
}
|
||||
}
|
||||
|
||||
// use this table to get all the possible matches
|
||||
List<List<int>> allMatches = GetAllMatchIndexes(matches);
|
||||
|
||||
// return the score that is the max
|
||||
int maxScore = allMatches.Count > 0 ? CalculateScoreForMatches(allMatches[0]) : 0;
|
||||
List<int> bestMatch = allMatches.Count > 0 ? allMatches[0] : new List<int>();
|
||||
|
||||
foreach (var match in allMatches)
|
||||
{
|
||||
int score = CalculateScoreForMatches(match);
|
||||
if (score > maxScore)
|
||||
{
|
||||
bestMatch = match;
|
||||
maxScore = score;
|
||||
}
|
||||
}
|
||||
|
||||
return bestMatch;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all the possible matches to the search string with in the text
|
||||
/// </summary>
|
||||
/// <param name="matches"> a table showing the matches as generated by
|
||||
/// a two dimensional array with the first dimension the text and the second
|
||||
/// one the search string and each cell marked as an intersection between the two</param>
|
||||
/// <returns>a list of the possible combinations that match the search text</returns>
|
||||
public static List<List<int>> GetAllMatchIndexes(bool[,] matches)
|
||||
{
|
||||
List<List<int>> results = new List<List<int>>();
|
||||
|
||||
for (int secondIndex = 0; secondIndex < matches.GetLength(1); secondIndex++)
|
||||
{
|
||||
for (int firstIndex = 0; firstIndex < matches.GetLength(0); firstIndex++)
|
||||
{
|
||||
if (secondIndex == 0 && matches[firstIndex, secondIndex])
|
||||
{
|
||||
results.Add(new List<int> { firstIndex });
|
||||
}
|
||||
else if (matches[firstIndex, secondIndex])
|
||||
{
|
||||
var tempList = results.Where(x => x.Count == secondIndex && x[x.Count - 1] < firstIndex).Select(x => x.ToList()).ToList();
|
||||
|
||||
foreach (var pathSofar in tempList)
|
||||
{
|
||||
pathSofar.Add(firstIndex);
|
||||
}
|
||||
|
||||
results.AddRange(tempList);
|
||||
}
|
||||
}
|
||||
|
||||
results = results.Where(x => x.Count == secondIndex + 1).ToList();
|
||||
}
|
||||
|
||||
return results.Where(x => x.Count == matches.GetLength(1)).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the score for a string
|
||||
/// </summary>
|
||||
/// <param name="matches">the index of the matches</param>
|
||||
/// <returns>an integer representing the score</returns>
|
||||
public static int CalculateScoreForMatches(List<int> matches)
|
||||
{
|
||||
var score = 0;
|
||||
|
||||
for (int currentIndex = 1; currentIndex < matches.Count; currentIndex++)
|
||||
{
|
||||
var previousIndex = currentIndex - 1;
|
||||
|
||||
score -= matches[currentIndex] - matches[previousIndex];
|
||||
}
|
||||
|
||||
return score == 0 ? -10000 : score;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Class housing fuzzy matching methods
|
||||
/// </summary>
|
||||
public class FuzzyMatching
|
||||
{
|
||||
/// <summary>
|
||||
/// Finds the best match (the one with the most
|
||||
/// number of letters adjacent to each other) and
|
||||
/// returns the index location of each of the letters
|
||||
/// of the matches
|
||||
/// </summary>
|
||||
/// <param name="text">The text to search inside of</param>
|
||||
/// <param name="searchText">the text to search for</param>
|
||||
/// <returns>returns the index location of each of the letters of the matches</returns>
|
||||
public static List<int> FindBestFuzzyMatch(string text, string searchText)
|
||||
{
|
||||
searchText = searchText.ToLower();
|
||||
text = text.ToLower();
|
||||
|
||||
// Create a grid to march matches like
|
||||
// eg.
|
||||
// a b c a d e c f g
|
||||
// a x x
|
||||
// c x x
|
||||
bool[,] matches = new bool[text.Length, searchText.Length];
|
||||
for (int firstIndex = 0; firstIndex < text.Length; firstIndex++)
|
||||
{
|
||||
for (int secondIndex = 0; secondIndex < searchText.Length; secondIndex++)
|
||||
{
|
||||
matches[firstIndex, secondIndex] =
|
||||
searchText[secondIndex] == text[firstIndex] ?
|
||||
true :
|
||||
false;
|
||||
}
|
||||
}
|
||||
|
||||
// use this table to get all the possible matches
|
||||
List<List<int>> allMatches = GetAllMatchIndexes(matches);
|
||||
|
||||
// return the score that is the max
|
||||
int maxScore = allMatches.Count > 0 ? CalculateScoreForMatches(allMatches[0]) : 0;
|
||||
List<int> bestMatch = allMatches.Count > 0 ? allMatches[0] : new List<int>();
|
||||
|
||||
foreach (var match in allMatches)
|
||||
{
|
||||
int score = CalculateScoreForMatches(match);
|
||||
if (score > maxScore)
|
||||
{
|
||||
bestMatch = match;
|
||||
maxScore = score;
|
||||
}
|
||||
}
|
||||
|
||||
return bestMatch;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all the possible matches to the search string with in the text
|
||||
/// </summary>
|
||||
/// <param name="matches"> a table showing the matches as generated by
|
||||
/// a two dimensional array with the first dimension the text and the second
|
||||
/// one the search string and each cell marked as an intersection between the two</param>
|
||||
/// <returns>a list of the possible combinations that match the search text</returns>
|
||||
public static List<List<int>> GetAllMatchIndexes(bool[,] matches)
|
||||
{
|
||||
List<List<int>> results = new List<List<int>>();
|
||||
|
||||
for (int secondIndex = 0; secondIndex < matches.GetLength(1); secondIndex++)
|
||||
{
|
||||
for (int firstIndex = 0; firstIndex < matches.GetLength(0); firstIndex++)
|
||||
{
|
||||
if (secondIndex == 0 && matches[firstIndex, secondIndex])
|
||||
{
|
||||
results.Add(new List<int> { firstIndex });
|
||||
}
|
||||
else if (matches[firstIndex, secondIndex])
|
||||
{
|
||||
var tempList = results.Where(x => x.Count == secondIndex && x[x.Count - 1] < firstIndex).Select(x => x.ToList()).ToList();
|
||||
|
||||
foreach (var pathSofar in tempList)
|
||||
{
|
||||
pathSofar.Add(firstIndex);
|
||||
}
|
||||
|
||||
results.AddRange(tempList);
|
||||
}
|
||||
}
|
||||
|
||||
results = results.Where(x => x.Count == secondIndex + 1).ToList();
|
||||
}
|
||||
|
||||
return results.Where(x => x.Count == matches.GetLength(1)).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the score for a string
|
||||
/// </summary>
|
||||
/// <param name="matches">the index of the matches</param>
|
||||
/// <returns>an integer representing the score</returns>
|
||||
public static int CalculateScoreForMatches(List<int> matches)
|
||||
{
|
||||
var score = 0;
|
||||
|
||||
for (int currentIndex = 1; currentIndex < matches.Count; currentIndex++)
|
||||
{
|
||||
var previousIndex = currentIndex - 1;
|
||||
|
||||
score -= matches[currentIndex] - matches[previousIndex];
|
||||
}
|
||||
|
||||
return score == 0 ? -10000 : score;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,58 +1,58 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Class containing methods to control the live preview
|
||||
/// </summary>
|
||||
internal class LivePreview
|
||||
{
|
||||
/// <summary>
|
||||
/// Makes sure that a window is excluded from the live preview
|
||||
/// </summary>
|
||||
/// <param name="hwnd">handle to the window to exclude</param>
|
||||
public static void SetWindowExclusionFromLivePreview(IntPtr hwnd)
|
||||
{
|
||||
int renderPolicy = (int)InteropAndHelpers.DwmNCRenderingPolicy.Enabled;
|
||||
|
||||
InteropAndHelpers.DwmSetWindowAttribute(
|
||||
hwnd,
|
||||
12,
|
||||
ref renderPolicy,
|
||||
sizeof(int));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates the live preview
|
||||
/// </summary>
|
||||
/// <param name="targetWindow">the window to show by making all other windows transparent</param>
|
||||
/// <param name="windowToSpare">the window which should not be transparent but is not the target window</param>
|
||||
public static void ActivateLivePreview(IntPtr targetWindow, IntPtr windowToSpare)
|
||||
{
|
||||
InteropAndHelpers.DwmpActivateLivePreview(
|
||||
true,
|
||||
targetWindow,
|
||||
windowToSpare,
|
||||
InteropAndHelpers.LivePreviewTrigger.Superbar,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deactivates the live preview
|
||||
/// </summary>
|
||||
public static void DeactivateLivePreview()
|
||||
{
|
||||
InteropAndHelpers.DwmpActivateLivePreview(
|
||||
false,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
InteropAndHelpers.LivePreviewTrigger.AltTab,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Class containing methods to control the live preview
|
||||
/// </summary>
|
||||
internal class LivePreview
|
||||
{
|
||||
/// <summary>
|
||||
/// Makes sure that a window is excluded from the live preview
|
||||
/// </summary>
|
||||
/// <param name="hwnd">handle to the window to exclude</param>
|
||||
public static void SetWindowExclusionFromLivePreview(IntPtr hwnd)
|
||||
{
|
||||
int renderPolicy = (int)InteropAndHelpers.DwmNCRenderingPolicy.Enabled;
|
||||
|
||||
InteropAndHelpers.DwmSetWindowAttribute(
|
||||
hwnd,
|
||||
12,
|
||||
ref renderPolicy,
|
||||
sizeof(int));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates the live preview
|
||||
/// </summary>
|
||||
/// <param name="targetWindow">the window to show by making all other windows transparent</param>
|
||||
/// <param name="windowToSpare">the window which should not be transparent but is not the target window</param>
|
||||
public static void ActivateLivePreview(IntPtr targetWindow, IntPtr windowToSpare)
|
||||
{
|
||||
InteropAndHelpers.DwmpActivateLivePreview(
|
||||
true,
|
||||
targetWindow,
|
||||
windowToSpare,
|
||||
InteropAndHelpers.LivePreviewTrigger.Superbar,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deactivates the live preview
|
||||
/// </summary>
|
||||
public static void DeactivateLivePreview()
|
||||
{
|
||||
InteropAndHelpers.DwmpActivateLivePreview(
|
||||
false,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
InteropAndHelpers.LivePreviewTrigger.AltTab,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,106 +1,106 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that represents the state of the desktops windows
|
||||
/// </summary>
|
||||
internal class OpenWindows
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate handler for open windows updates
|
||||
/// </summary>
|
||||
public delegate void OpenWindowsUpdateHandler(object sender, SearchController.SearchResultUpdateEventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when there is an update to the list of open windows
|
||||
/// </summary>
|
||||
public event OpenWindowsUpdateHandler OnOpenWindowsUpdate
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of all the open windows
|
||||
/// </summary>
|
||||
private readonly List<Window> windows = new List<Window>();
|
||||
|
||||
/// <summary>
|
||||
/// An instance of the class OpenWindows
|
||||
/// </summary>
|
||||
private static OpenWindows instance;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of all open windows
|
||||
/// </summary>
|
||||
public List<Window> Windows
|
||||
{
|
||||
get { return new List<Window>(windows); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an instance property of this class that makes sure that
|
||||
/// the first instance gets created and that all the requests
|
||||
/// end up at that one instance
|
||||
/// </summary>
|
||||
public static OpenWindows Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new OpenWindows();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OpenWindows"/> class.
|
||||
/// Private constructor to make sure there is never
|
||||
/// more than one instance of this class
|
||||
/// </summary>
|
||||
private OpenWindows()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the list of open windows
|
||||
/// </summary>
|
||||
public void UpdateOpenWindowsList()
|
||||
{
|
||||
windows.Clear();
|
||||
InteropAndHelpers.CallBackPtr callbackptr = new InteropAndHelpers.CallBackPtr(WindowEnumerationCallBack);
|
||||
InteropAndHelpers.EnumWindows(callbackptr, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call back method for window enumeration
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The handle to the current window being enumerated</param>
|
||||
/// <param name="lParam">Value being passed from the caller (we don't use this but might come in handy
|
||||
/// in the future</param>
|
||||
/// <returns>true to make sure to continue enumeration</returns>
|
||||
public bool WindowEnumerationCallBack(IntPtr hwnd, IntPtr lParam)
|
||||
{
|
||||
Window newWindow = new Window(hwnd);
|
||||
|
||||
if (newWindow.IsWindow && newWindow.Visible && newWindow.IsOwner &&
|
||||
(!newWindow.IsToolWindow || newWindow.IsAppWindow) && !newWindow.TaskListDeleted &&
|
||||
newWindow.ClassName != "Windows.UI.Core.CoreWindow")
|
||||
{
|
||||
windows.Add(newWindow);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that represents the state of the desktops windows
|
||||
/// </summary>
|
||||
internal class OpenWindows
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate handler for open windows updates
|
||||
/// </summary>
|
||||
public delegate void OpenWindowsUpdateHandler(object sender, SearchController.SearchResultUpdateEventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when there is an update to the list of open windows
|
||||
/// </summary>
|
||||
public event OpenWindowsUpdateHandler OnOpenWindowsUpdate
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of all the open windows
|
||||
/// </summary>
|
||||
private readonly List<Window> windows = new List<Window>();
|
||||
|
||||
/// <summary>
|
||||
/// An instance of the class OpenWindows
|
||||
/// </summary>
|
||||
private static OpenWindows instance;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of all open windows
|
||||
/// </summary>
|
||||
public List<Window> Windows
|
||||
{
|
||||
get { return new List<Window>(windows); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an instance property of this class that makes sure that
|
||||
/// the first instance gets created and that all the requests
|
||||
/// end up at that one instance
|
||||
/// </summary>
|
||||
public static OpenWindows Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new OpenWindows();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OpenWindows"/> class.
|
||||
/// Private constructor to make sure there is never
|
||||
/// more than one instance of this class
|
||||
/// </summary>
|
||||
private OpenWindows()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the list of open windows
|
||||
/// </summary>
|
||||
public void UpdateOpenWindowsList()
|
||||
{
|
||||
windows.Clear();
|
||||
InteropAndHelpers.CallBackPtr callbackptr = new InteropAndHelpers.CallBackPtr(WindowEnumerationCallBack);
|
||||
InteropAndHelpers.EnumWindows(callbackptr, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call back method for window enumeration
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The handle to the current window being enumerated</param>
|
||||
/// <param name="lParam">Value being passed from the caller (we don't use this but might come in handy
|
||||
/// in the future</param>
|
||||
/// <returns>true to make sure to continue enumeration</returns>
|
||||
public bool WindowEnumerationCallBack(IntPtr hwnd, IntPtr lParam)
|
||||
{
|
||||
Window newWindow = new Window(hwnd);
|
||||
|
||||
if (newWindow.IsWindow && newWindow.Visible && newWindow.IsOwner &&
|
||||
(!newWindow.IsToolWindow || newWindow.IsAppWindow) && !newWindow.TaskListDeleted &&
|
||||
newWindow.ClassName != "Windows.UI.Core.CoreWindow")
|
||||
{
|
||||
windows.Add(newWindow);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,186 +1,186 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Responsible for searching and finding matches for the strings provided.
|
||||
/// Essentially the UI independent model of the application
|
||||
/// </summary>
|
||||
internal class SearchController
|
||||
{
|
||||
/// <summary>
|
||||
/// the current search text
|
||||
/// </summary>
|
||||
private string searchText;
|
||||
|
||||
/// <summary>
|
||||
/// Open window search results
|
||||
/// </summary
|
||||
private List<SearchResult> searchMatches;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton pattern
|
||||
/// </summary>
|
||||
private static SearchController instance;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate handler for open windows updates
|
||||
/// </summary>
|
||||
public delegate void SearchResultUpdateHandler(object sender, SearchResultUpdateEventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when there is an update to the list of open windows
|
||||
/// </summary>
|
||||
public event SearchResultUpdateHandler OnSearchResultUpdate;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current search text
|
||||
/// </summary>
|
||||
public string SearchText
|
||||
{
|
||||
get
|
||||
{
|
||||
return searchText;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
searchText = value.ToLower().Trim();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the open window search results
|
||||
/// </summary>
|
||||
public List<SearchResult> SearchMatches
|
||||
{
|
||||
get { return new List<SearchResult>(searchMatches).OrderByDescending(x => x.Score).ToList(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets singleton Pattern
|
||||
/// </summary>
|
||||
public static SearchController Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new SearchController();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SearchController"/> class.
|
||||
/// Initializes the search controller object
|
||||
/// </summary>
|
||||
private SearchController()
|
||||
{
|
||||
searchText = string.Empty;
|
||||
OpenWindows.Instance.OnOpenWindowsUpdate += OpenWindowsUpdateHandler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler for when the search text has been updated
|
||||
/// </summary>
|
||||
public async Task UpdateSearchText(string searchText)
|
||||
{
|
||||
SearchText = searchText;
|
||||
await SyncOpenWindowsWithModelAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler called when the OpenWindows list changes
|
||||
/// </summary>
|
||||
/// <param name="sender">sending item</param>
|
||||
/// <param name="e">event arg</param>
|
||||
public async void OpenWindowsUpdateHandler(object sender, SearchResultUpdateEventArgs e)
|
||||
{
|
||||
await SyncOpenWindowsWithModelAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Syncs the open windows with the OpenWindows Model
|
||||
/// </summary>
|
||||
public async Task SyncOpenWindowsWithModelAsync()
|
||||
{
|
||||
System.Diagnostics.Debug.Print("Syncing WindowSearch result with OpenWindows Model");
|
||||
|
||||
List<Window> snapshotOfOpenWindows = OpenWindows.Instance.Windows;
|
||||
|
||||
if (SearchText == string.Empty)
|
||||
{
|
||||
searchMatches = new List<SearchResult>();
|
||||
}
|
||||
else
|
||||
{
|
||||
searchMatches = await FuzzySearchOpenWindowsAsync(snapshotOfOpenWindows);
|
||||
}
|
||||
|
||||
OnSearchResultUpdate?.Invoke(this, new SearchResultUpdateEventArgs());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redirecting method for Fuzzy searching
|
||||
/// </summary>
|
||||
/// <param name="openWindows">what windows are open</param>
|
||||
/// <returns>Returns search results</returns>
|
||||
private Task<List<SearchResult>> FuzzySearchOpenWindowsAsync(List<Window> openWindows)
|
||||
{
|
||||
return Task.Run(
|
||||
() =>
|
||||
FuzzySearchOpenWindows(openWindows));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search method that matches the title of windows with the user search text
|
||||
/// </summary>
|
||||
/// <param name="openWindows">what windows are open</param>
|
||||
/// <returns>Returns search results</returns>
|
||||
private List<SearchResult> FuzzySearchOpenWindows(List<Window> openWindows)
|
||||
{
|
||||
List<SearchResult> result = new List<SearchResult>();
|
||||
List<SearchString> searchStrings = new List<SearchString>();
|
||||
|
||||
searchStrings.Add(new SearchString(searchText, SearchResult.SearchType.Fuzzy));
|
||||
|
||||
foreach (var searchString in searchStrings)
|
||||
{
|
||||
foreach (var window in openWindows)
|
||||
{
|
||||
var titleMatch = FuzzyMatching.FindBestFuzzyMatch(window.Title, searchString.SearchText);
|
||||
var processMatch = FuzzyMatching.FindBestFuzzyMatch(window.ProcessName, searchString.SearchText);
|
||||
|
||||
if ((titleMatch.Count != 0 || processMatch.Count != 0) &&
|
||||
window.Title.Length != 0)
|
||||
{
|
||||
var temp = new SearchResult(window, titleMatch, processMatch, searchString.SearchType);
|
||||
result.Add(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.Diagnostics.Debug.Print("Found " + result.Count + " windows that match the search text");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event args for a window list update event
|
||||
/// </summary>
|
||||
public class SearchResultUpdateEventArgs : EventArgs
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Responsible for searching and finding matches for the strings provided.
|
||||
/// Essentially the UI independent model of the application
|
||||
/// </summary>
|
||||
internal class SearchController
|
||||
{
|
||||
/// <summary>
|
||||
/// the current search text
|
||||
/// </summary>
|
||||
private string searchText;
|
||||
|
||||
/// <summary>
|
||||
/// Open window search results
|
||||
/// </summary
|
||||
private List<SearchResult> searchMatches;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton pattern
|
||||
/// </summary>
|
||||
private static SearchController instance;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate handler for open windows updates
|
||||
/// </summary>
|
||||
public delegate void SearchResultUpdateHandler(object sender, SearchResultUpdateEventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when there is an update to the list of open windows
|
||||
/// </summary>
|
||||
public event SearchResultUpdateHandler OnSearchResultUpdate;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current search text
|
||||
/// </summary>
|
||||
public string SearchText
|
||||
{
|
||||
get
|
||||
{
|
||||
return searchText;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
searchText = value.ToLower().Trim();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the open window search results
|
||||
/// </summary>
|
||||
public List<SearchResult> SearchMatches
|
||||
{
|
||||
get { return new List<SearchResult>(searchMatches).OrderByDescending(x => x.Score).ToList(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets singleton Pattern
|
||||
/// </summary>
|
||||
public static SearchController Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new SearchController();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SearchController"/> class.
|
||||
/// Initializes the search controller object
|
||||
/// </summary>
|
||||
private SearchController()
|
||||
{
|
||||
searchText = string.Empty;
|
||||
OpenWindows.Instance.OnOpenWindowsUpdate += OpenWindowsUpdateHandler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler for when the search text has been updated
|
||||
/// </summary>
|
||||
public async Task UpdateSearchText(string searchText)
|
||||
{
|
||||
SearchText = searchText;
|
||||
await SyncOpenWindowsWithModelAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler called when the OpenWindows list changes
|
||||
/// </summary>
|
||||
/// <param name="sender">sending item</param>
|
||||
/// <param name="e">event arg</param>
|
||||
public async void OpenWindowsUpdateHandler(object sender, SearchResultUpdateEventArgs e)
|
||||
{
|
||||
await SyncOpenWindowsWithModelAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Syncs the open windows with the OpenWindows Model
|
||||
/// </summary>
|
||||
public async Task SyncOpenWindowsWithModelAsync()
|
||||
{
|
||||
System.Diagnostics.Debug.Print("Syncing WindowSearch result with OpenWindows Model");
|
||||
|
||||
List<Window> snapshotOfOpenWindows = OpenWindows.Instance.Windows;
|
||||
|
||||
if (SearchText == string.Empty)
|
||||
{
|
||||
searchMatches = new List<SearchResult>();
|
||||
}
|
||||
else
|
||||
{
|
||||
searchMatches = await FuzzySearchOpenWindowsAsync(snapshotOfOpenWindows);
|
||||
}
|
||||
|
||||
OnSearchResultUpdate?.Invoke(this, new SearchResultUpdateEventArgs());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redirecting method for Fuzzy searching
|
||||
/// </summary>
|
||||
/// <param name="openWindows">what windows are open</param>
|
||||
/// <returns>Returns search results</returns>
|
||||
private Task<List<SearchResult>> FuzzySearchOpenWindowsAsync(List<Window> openWindows)
|
||||
{
|
||||
return Task.Run(
|
||||
() =>
|
||||
FuzzySearchOpenWindows(openWindows));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search method that matches the title of windows with the user search text
|
||||
/// </summary>
|
||||
/// <param name="openWindows">what windows are open</param>
|
||||
/// <returns>Returns search results</returns>
|
||||
private List<SearchResult> FuzzySearchOpenWindows(List<Window> openWindows)
|
||||
{
|
||||
List<SearchResult> result = new List<SearchResult>();
|
||||
List<SearchString> searchStrings = new List<SearchString>();
|
||||
|
||||
searchStrings.Add(new SearchString(searchText, SearchResult.SearchType.Fuzzy));
|
||||
|
||||
foreach (var searchString in searchStrings)
|
||||
{
|
||||
foreach (var window in openWindows)
|
||||
{
|
||||
var titleMatch = FuzzyMatching.FindBestFuzzyMatch(window.Title, searchString.SearchText);
|
||||
var processMatch = FuzzyMatching.FindBestFuzzyMatch(window.ProcessName, searchString.SearchText);
|
||||
|
||||
if ((titleMatch.Count != 0 || processMatch.Count != 0) &&
|
||||
window.Title.Length != 0)
|
||||
{
|
||||
var temp = new SearchResult(window, titleMatch, processMatch, searchString.SearchType);
|
||||
result.Add(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.Diagnostics.Debug.Print("Found " + result.Count + " windows that match the search text");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event args for a window list update event
|
||||
/// </summary>
|
||||
public class SearchResultUpdateEventArgs : EventArgs
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,136 +1,136 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains search result windows with each window including the reason why the result was included
|
||||
/// </summary>
|
||||
public class SearchResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the actual window reference for the search result
|
||||
/// </summary>
|
||||
public Window Result
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of indexes of the matching characters for the search in the title window
|
||||
/// </summary>
|
||||
public List<int> SearchMatchesInTitle
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of indexes of the matching characters for the search in the
|
||||
/// name of the process
|
||||
/// </summary>
|
||||
public List<int> SearchMatchesInProcessName
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of match (shortcut, fuzzy or nothing)
|
||||
/// </summary>
|
||||
public SearchType SearchResultMatchType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a score indicating how well this matches what we are looking for
|
||||
/// </summary>
|
||||
public int Score
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the source of where the best score was found
|
||||
/// </summary>
|
||||
public TextType BestScoreSource
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SearchResult"/> class.
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public SearchResult(Window window, List<int> matchesInTitle, List<int> matchesInProcessName, SearchType matchType)
|
||||
{
|
||||
Result = window;
|
||||
SearchMatchesInTitle = matchesInTitle;
|
||||
SearchMatchesInProcessName = matchesInProcessName;
|
||||
SearchResultMatchType = matchType;
|
||||
CalculateScore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the score for how closely this window matches the search string
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Higher Score is better
|
||||
/// </remarks>
|
||||
private void CalculateScore()
|
||||
{
|
||||
if (FuzzyMatching.CalculateScoreForMatches(SearchMatchesInProcessName) >
|
||||
FuzzyMatching.CalculateScoreForMatches(SearchMatchesInTitle))
|
||||
{
|
||||
Score = FuzzyMatching.CalculateScoreForMatches(SearchMatchesInProcessName);
|
||||
BestScoreSource = TextType.ProcessName;
|
||||
}
|
||||
else
|
||||
{
|
||||
Score = FuzzyMatching.CalculateScoreForMatches(SearchMatchesInTitle);
|
||||
BestScoreSource = TextType.WindowTitle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The type of text that a string represents
|
||||
/// </summary>
|
||||
public enum TextType
|
||||
{
|
||||
ProcessName,
|
||||
WindowTitle,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The type of search
|
||||
/// </summary>
|
||||
public enum SearchType
|
||||
{
|
||||
/// <summary>
|
||||
/// the search string is empty, which means all open windows are
|
||||
/// going to be returned
|
||||
/// </summary>
|
||||
Empty,
|
||||
|
||||
/// <summary>
|
||||
/// Regular fuzzy match search
|
||||
/// </summary>
|
||||
Fuzzy,
|
||||
|
||||
/// <summary>
|
||||
/// The user has entered text that has been matched to a shortcut
|
||||
/// and the shortcut is now being searched
|
||||
/// </summary>
|
||||
Shortcut,
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains search result windows with each window including the reason why the result was included
|
||||
/// </summary>
|
||||
public class SearchResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the actual window reference for the search result
|
||||
/// </summary>
|
||||
public Window Result
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of indexes of the matching characters for the search in the title window
|
||||
/// </summary>
|
||||
public List<int> SearchMatchesInTitle
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of indexes of the matching characters for the search in the
|
||||
/// name of the process
|
||||
/// </summary>
|
||||
public List<int> SearchMatchesInProcessName
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of match (shortcut, fuzzy or nothing)
|
||||
/// </summary>
|
||||
public SearchType SearchResultMatchType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a score indicating how well this matches what we are looking for
|
||||
/// </summary>
|
||||
public int Score
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the source of where the best score was found
|
||||
/// </summary>
|
||||
public TextType BestScoreSource
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SearchResult"/> class.
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public SearchResult(Window window, List<int> matchesInTitle, List<int> matchesInProcessName, SearchType matchType)
|
||||
{
|
||||
Result = window;
|
||||
SearchMatchesInTitle = matchesInTitle;
|
||||
SearchMatchesInProcessName = matchesInProcessName;
|
||||
SearchResultMatchType = matchType;
|
||||
CalculateScore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the score for how closely this window matches the search string
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Higher Score is better
|
||||
/// </remarks>
|
||||
private void CalculateScore()
|
||||
{
|
||||
if (FuzzyMatching.CalculateScoreForMatches(SearchMatchesInProcessName) >
|
||||
FuzzyMatching.CalculateScoreForMatches(SearchMatchesInTitle))
|
||||
{
|
||||
Score = FuzzyMatching.CalculateScoreForMatches(SearchMatchesInProcessName);
|
||||
BestScoreSource = TextType.ProcessName;
|
||||
}
|
||||
else
|
||||
{
|
||||
Score = FuzzyMatching.CalculateScoreForMatches(SearchMatchesInTitle);
|
||||
BestScoreSource = TextType.WindowTitle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The type of text that a string represents
|
||||
/// </summary>
|
||||
public enum TextType
|
||||
{
|
||||
ProcessName,
|
||||
WindowTitle,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The type of search
|
||||
/// </summary>
|
||||
public enum SearchType
|
||||
{
|
||||
/// <summary>
|
||||
/// the search string is empty, which means all open windows are
|
||||
/// going to be returned
|
||||
/// </summary>
|
||||
Empty,
|
||||
|
||||
/// <summary>
|
||||
/// Regular fuzzy match search
|
||||
/// </summary>
|
||||
Fuzzy,
|
||||
|
||||
/// <summary>
|
||||
/// The user has entered text that has been matched to a shortcut
|
||||
/// and the shortcut is now being searched
|
||||
/// </summary>
|
||||
Shortcut,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// A class to represent a search string
|
||||
/// </summary>
|
||||
/// <remarks>Class was added inorder to be able to attach various context data to
|
||||
/// a search string</remarks>
|
||||
internal class SearchString
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets where is the search string coming from (is it a shortcut
|
||||
/// or direct string, etc...)
|
||||
/// </summary>
|
||||
public SearchResult.SearchType SearchType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the actual text we are searching for
|
||||
/// </summary>
|
||||
public string SearchText
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SearchString"/> class.
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="searchText">text from search</param>
|
||||
/// <param name="searchType">type of search</param>
|
||||
public SearchString(string searchText, SearchResult.SearchType searchType)
|
||||
{
|
||||
SearchText = searchText;
|
||||
SearchType = searchType;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// A class to represent a search string
|
||||
/// </summary>
|
||||
/// <remarks>Class was added inorder to be able to attach various context data to
|
||||
/// a search string</remarks>
|
||||
internal class SearchString
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets where is the search string coming from (is it a shortcut
|
||||
/// or direct string, etc...)
|
||||
/// </summary>
|
||||
public SearchResult.SearchType SearchType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the actual text we are searching for
|
||||
/// </summary>
|
||||
public string SearchText
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SearchString"/> class.
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="searchText">text from search</param>
|
||||
/// <param name="searchType">type of search</param>
|
||||
public SearchString(string searchText, SearchResult.SearchType searchType)
|
||||
{
|
||||
SearchText = searchText;
|
||||
SearchType = searchType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,402 +1,402 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a specific open window
|
||||
/// </summary>
|
||||
public class Window
|
||||
{
|
||||
/// <summary>
|
||||
/// Maximum size of a file name
|
||||
/// </summary>
|
||||
private const int MaximumFileNameLength = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// The list of owners of a window so that we don't have to
|
||||
/// constantly query for the process owning a specific window
|
||||
/// </summary>
|
||||
private static readonly Dictionary<IntPtr, string> _handlesToProcessCache = new Dictionary<IntPtr, string>();
|
||||
|
||||
/// <summary>
|
||||
/// The list of icons from process so that we don't have to keep
|
||||
/// loading them from disk
|
||||
/// </summary>
|
||||
private static readonly Dictionary<uint, ImageSource> _processIdsToIconsCache = new Dictionary<uint, ImageSource>();
|
||||
|
||||
/// <summary>
|
||||
/// The handle to the window
|
||||
/// </summary>
|
||||
private readonly IntPtr hwnd;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the title of the window (the string displayed at the top of the window)
|
||||
/// </summary>
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
int sizeOfTitle = InteropAndHelpers.GetWindowTextLength(hwnd);
|
||||
if (sizeOfTitle++ > 0)
|
||||
{
|
||||
StringBuilder titleBuffer = new StringBuilder(sizeOfTitle);
|
||||
InteropAndHelpers.GetWindowText(hwnd, titleBuffer, sizeOfTitle);
|
||||
return titleBuffer.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the handle to the window
|
||||
/// </summary>
|
||||
public IntPtr Hwnd
|
||||
{
|
||||
get { return hwnd; }
|
||||
}
|
||||
|
||||
public uint ProcessID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets returns the name of the process
|
||||
/// </summary>
|
||||
public string ProcessName
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_handlesToProcessCache)
|
||||
{
|
||||
if (_handlesToProcessCache.Count > 7000)
|
||||
{
|
||||
Debug.Print("Clearing Process Cache because it's size is " + _handlesToProcessCache.Count);
|
||||
_handlesToProcessCache.Clear();
|
||||
}
|
||||
|
||||
if (!_handlesToProcessCache.ContainsKey(Hwnd))
|
||||
{
|
||||
var processName = GetProcessNameFromWindowHandle(Hwnd);
|
||||
|
||||
if (processName.Length != 0)
|
||||
{
|
||||
_handlesToProcessCache.Add(
|
||||
Hwnd,
|
||||
processName.ToString().Split('\\').Reverse().ToArray()[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_handlesToProcessCache.Add(Hwnd, string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
if (_handlesToProcessCache[hwnd].ToLower() == "applicationframehost.exe")
|
||||
{
|
||||
new Task(() =>
|
||||
{
|
||||
InteropAndHelpers.CallBackPtr callbackptr = new InteropAndHelpers.CallBackPtr((IntPtr hwnd, IntPtr lParam) =>
|
||||
{
|
||||
var childProcessId = GetProcessIDFromWindowHandle(hwnd);
|
||||
if (childProcessId != ProcessID)
|
||||
{
|
||||
_handlesToProcessCache[Hwnd] = GetProcessNameFromWindowHandle(hwnd);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
InteropAndHelpers.EnumChildWindows(Hwnd, callbackptr, 0);
|
||||
}).Start();
|
||||
}
|
||||
|
||||
return _handlesToProcessCache[hwnd];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets returns the name of the class for the window represented
|
||||
/// </summary>
|
||||
public string ClassName
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder windowClassName = new StringBuilder(300);
|
||||
InteropAndHelpers.GetClassName(Hwnd, windowClassName, windowClassName.MaxCapacity);
|
||||
|
||||
return windowClassName.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets represents the Window Icon for the specified window
|
||||
/// </summary>
|
||||
public ImageSource WindowIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_processIdsToIconsCache)
|
||||
{
|
||||
InteropAndHelpers.GetWindowThreadProcessId(Hwnd, out uint processId);
|
||||
|
||||
if (!_processIdsToIconsCache.ContainsKey(processId))
|
||||
{
|
||||
try
|
||||
{
|
||||
Process process = Process.GetProcessById((int)processId);
|
||||
Icon tempIcon = Icon.ExtractAssociatedIcon(process.Modules[0].FileName);
|
||||
_processIdsToIconsCache.Add(processId, Imaging.CreateBitmapSourceFromHIcon(
|
||||
tempIcon.Handle,
|
||||
Int32Rect.Empty,
|
||||
BitmapSizeOptions.FromEmptyOptions()));
|
||||
}
|
||||
catch
|
||||
{
|
||||
BitmapImage failedImage = new BitmapImage(new Uri(@"Images\failedIcon.jpg", UriKind.Relative));
|
||||
_processIdsToIconsCache.Add(processId, failedImage);
|
||||
}
|
||||
}
|
||||
|
||||
return _processIdsToIconsCache[processId];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether is the window visible (might return false if it is a hidden IE tab)
|
||||
/// </summary>
|
||||
public bool Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
return InteropAndHelpers.IsWindowVisible(Hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether determines whether the specified window handle identifies an existing window.
|
||||
/// </summary>
|
||||
public bool IsWindow
|
||||
{
|
||||
get
|
||||
{
|
||||
return InteropAndHelpers.IsWindow(Hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether get a value indicating whether is the window GWL_EX_STYLE is a toolwindow
|
||||
/// </summary>
|
||||
public bool IsToolWindow
|
||||
{
|
||||
get
|
||||
{
|
||||
return (InteropAndHelpers.GetWindowLong(Hwnd, InteropAndHelpers.GWL_EXSTYLE) &
|
||||
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_TOOLWINDOW) ==
|
||||
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_TOOLWINDOW;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether get a value indicating whether the window GWL_EX_STYLE is an appwindow
|
||||
/// </summary>
|
||||
public bool IsAppWindow
|
||||
{
|
||||
get
|
||||
{
|
||||
return (InteropAndHelpers.GetWindowLong(Hwnd, InteropAndHelpers.GWL_EXSTYLE) &
|
||||
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_APPWINDOW) ==
|
||||
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_APPWINDOW;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether get a value indicating whether the window has ITaskList_Deleted property
|
||||
/// </summary>
|
||||
public bool TaskListDeleted
|
||||
{
|
||||
get
|
||||
{
|
||||
return InteropAndHelpers.GetProp(Hwnd, "ITaskList_Deleted") != IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether get a value indicating whether the app is a cloaked UWP app
|
||||
/// </summary>
|
||||
public bool IsUWPCloaked
|
||||
{
|
||||
get
|
||||
{
|
||||
return IsWindowCloaked() && ClassName == "ApplicationFrameWindow";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether determines whether the specified windows is the owner
|
||||
/// </summary>
|
||||
public bool IsOwner
|
||||
{
|
||||
get
|
||||
{
|
||||
return InteropAndHelpers.GetWindow(Hwnd, InteropAndHelpers.GetWindowCmd.GW_OWNER) != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether is the window cloaked. To detect UWP apps in background or win32 apps running in another virtual desktop
|
||||
/// </summary>
|
||||
public bool IsWindowCloaked()
|
||||
{
|
||||
int isCloaked = 0;
|
||||
const int DWMWA_CLOAKED = 14;
|
||||
InteropAndHelpers.DwmGetWindowAttribute(hwnd, DWMWA_CLOAKED, out isCloaked, sizeof(int));
|
||||
return isCloaked != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether returns true if the window is minimized
|
||||
/// </summary>
|
||||
public bool Minimized
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetWindowSizeState() == WindowSizeState.Minimized;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Window"/> class.
|
||||
/// Initializes a new Window representation
|
||||
/// </summary>
|
||||
/// <param name="hwnd">the handle to the window we are representing</param>
|
||||
public Window(IntPtr hwnd)
|
||||
{
|
||||
// TODO: Add verification as to whether the window handle is valid
|
||||
this.hwnd = hwnd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Highlights a window to help the user identify the window that has been selected
|
||||
/// </summary>
|
||||
public void HighlightWindow()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Switches desktop focus to the window
|
||||
/// </summary>
|
||||
public void SwitchToWindow()
|
||||
{
|
||||
// The following block is necessary because
|
||||
// 1) There is a weird flashing behavior when trying
|
||||
// to use ShowWindow for switching tabs in IE
|
||||
// 2) SetForegroundWindow fails on minimized windows
|
||||
if (ProcessName.ToLower().Equals("iexplore.exe") || !Minimized)
|
||||
{
|
||||
InteropAndHelpers.SetForegroundWindow(Hwnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
InteropAndHelpers.ShowWindow(Hwnd, InteropAndHelpers.ShowWindowCommands.Restore);
|
||||
}
|
||||
|
||||
InteropAndHelpers.FlashWindow(Hwnd, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the window name to string along with the process name
|
||||
/// </summary>
|
||||
/// <returns>The title of the window</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Title + " (" + ProcessName.ToUpper() + ")";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns what the window size is
|
||||
/// </summary>
|
||||
/// <returns>The state (minimized, maximized, etc..) of the window</returns>
|
||||
public WindowSizeState GetWindowSizeState()
|
||||
{
|
||||
InteropAndHelpers.GetWindowPlacement(Hwnd, out InteropAndHelpers.WINDOWPLACEMENT placement);
|
||||
|
||||
switch (placement.ShowCmd)
|
||||
{
|
||||
case InteropAndHelpers.ShowWindowCommands.Normal:
|
||||
return WindowSizeState.Normal;
|
||||
case InteropAndHelpers.ShowWindowCommands.Minimize:
|
||||
case InteropAndHelpers.ShowWindowCommands.ShowMinimized:
|
||||
return WindowSizeState.Minimized;
|
||||
case InteropAndHelpers.ShowWindowCommands.Maximize: // No need for ShowMaximized here since its also of value 3
|
||||
return WindowSizeState.Maximized;
|
||||
default:
|
||||
// throw new Exception("Don't know how to handle window state = " + placement.ShowCmd);
|
||||
return WindowSizeState.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum to simplify the state of the window
|
||||
/// </summary>
|
||||
public enum WindowSizeState
|
||||
{
|
||||
Normal,
|
||||
Minimized,
|
||||
Maximized,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the process using the window handle
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The handle to the window</param>
|
||||
/// <returns>A string representing the process name or an empty string if the function fails</returns>
|
||||
private string GetProcessNameFromWindowHandle(IntPtr hwnd)
|
||||
{
|
||||
uint processId = GetProcessIDFromWindowHandle(hwnd);
|
||||
ProcessID = processId;
|
||||
IntPtr processHandle = InteropAndHelpers.OpenProcess(InteropAndHelpers.ProcessAccessFlags.AllAccess, true, (int)processId);
|
||||
StringBuilder processName = new StringBuilder(MaximumFileNameLength);
|
||||
|
||||
if (InteropAndHelpers.GetProcessImageFileName(processHandle, processName, MaximumFileNameLength) != 0)
|
||||
{
|
||||
return processName.ToString().Split('\\').Reverse().ToArray()[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the process ID for the Window handle
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The handle to the window</param>
|
||||
/// <returns>The process ID</returns>
|
||||
private uint GetProcessIDFromWindowHandle(IntPtr hwnd)
|
||||
{
|
||||
InteropAndHelpers.GetWindowThreadProcessId(hwnd, out uint processId);
|
||||
return processId;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a specific open window
|
||||
/// </summary>
|
||||
public class Window
|
||||
{
|
||||
/// <summary>
|
||||
/// Maximum size of a file name
|
||||
/// </summary>
|
||||
private const int MaximumFileNameLength = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// The list of owners of a window so that we don't have to
|
||||
/// constantly query for the process owning a specific window
|
||||
/// </summary>
|
||||
private static readonly Dictionary<IntPtr, string> _handlesToProcessCache = new Dictionary<IntPtr, string>();
|
||||
|
||||
/// <summary>
|
||||
/// The list of icons from process so that we don't have to keep
|
||||
/// loading them from disk
|
||||
/// </summary>
|
||||
private static readonly Dictionary<uint, ImageSource> _processIdsToIconsCache = new Dictionary<uint, ImageSource>();
|
||||
|
||||
/// <summary>
|
||||
/// The handle to the window
|
||||
/// </summary>
|
||||
private readonly IntPtr hwnd;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the title of the window (the string displayed at the top of the window)
|
||||
/// </summary>
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
int sizeOfTitle = InteropAndHelpers.GetWindowTextLength(hwnd);
|
||||
if (sizeOfTitle++ > 0)
|
||||
{
|
||||
StringBuilder titleBuffer = new StringBuilder(sizeOfTitle);
|
||||
InteropAndHelpers.GetWindowText(hwnd, titleBuffer, sizeOfTitle);
|
||||
return titleBuffer.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the handle to the window
|
||||
/// </summary>
|
||||
public IntPtr Hwnd
|
||||
{
|
||||
get { return hwnd; }
|
||||
}
|
||||
|
||||
public uint ProcessID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets returns the name of the process
|
||||
/// </summary>
|
||||
public string ProcessName
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_handlesToProcessCache)
|
||||
{
|
||||
if (_handlesToProcessCache.Count > 7000)
|
||||
{
|
||||
Debug.Print("Clearing Process Cache because it's size is " + _handlesToProcessCache.Count);
|
||||
_handlesToProcessCache.Clear();
|
||||
}
|
||||
|
||||
if (!_handlesToProcessCache.ContainsKey(Hwnd))
|
||||
{
|
||||
var processName = GetProcessNameFromWindowHandle(Hwnd);
|
||||
|
||||
if (processName.Length != 0)
|
||||
{
|
||||
_handlesToProcessCache.Add(
|
||||
Hwnd,
|
||||
processName.ToString().Split('\\').Reverse().ToArray()[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_handlesToProcessCache.Add(Hwnd, string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
if (_handlesToProcessCache[hwnd].ToLower() == "applicationframehost.exe")
|
||||
{
|
||||
new Task(() =>
|
||||
{
|
||||
InteropAndHelpers.CallBackPtr callbackptr = new InteropAndHelpers.CallBackPtr((IntPtr hwnd, IntPtr lParam) =>
|
||||
{
|
||||
var childProcessId = GetProcessIDFromWindowHandle(hwnd);
|
||||
if (childProcessId != ProcessID)
|
||||
{
|
||||
_handlesToProcessCache[Hwnd] = GetProcessNameFromWindowHandle(hwnd);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
InteropAndHelpers.EnumChildWindows(Hwnd, callbackptr, 0);
|
||||
}).Start();
|
||||
}
|
||||
|
||||
return _handlesToProcessCache[hwnd];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets returns the name of the class for the window represented
|
||||
/// </summary>
|
||||
public string ClassName
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder windowClassName = new StringBuilder(300);
|
||||
InteropAndHelpers.GetClassName(Hwnd, windowClassName, windowClassName.MaxCapacity);
|
||||
|
||||
return windowClassName.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets represents the Window Icon for the specified window
|
||||
/// </summary>
|
||||
public ImageSource WindowIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_processIdsToIconsCache)
|
||||
{
|
||||
InteropAndHelpers.GetWindowThreadProcessId(Hwnd, out uint processId);
|
||||
|
||||
if (!_processIdsToIconsCache.ContainsKey(processId))
|
||||
{
|
||||
try
|
||||
{
|
||||
Process process = Process.GetProcessById((int)processId);
|
||||
Icon tempIcon = Icon.ExtractAssociatedIcon(process.Modules[0].FileName);
|
||||
_processIdsToIconsCache.Add(processId, Imaging.CreateBitmapSourceFromHIcon(
|
||||
tempIcon.Handle,
|
||||
Int32Rect.Empty,
|
||||
BitmapSizeOptions.FromEmptyOptions()));
|
||||
}
|
||||
catch
|
||||
{
|
||||
BitmapImage failedImage = new BitmapImage(new Uri(@"Images\failedIcon.jpg", UriKind.Relative));
|
||||
_processIdsToIconsCache.Add(processId, failedImage);
|
||||
}
|
||||
}
|
||||
|
||||
return _processIdsToIconsCache[processId];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether is the window visible (might return false if it is a hidden IE tab)
|
||||
/// </summary>
|
||||
public bool Visible
|
||||
{
|
||||
get
|
||||
{
|
||||
return InteropAndHelpers.IsWindowVisible(Hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether determines whether the specified window handle identifies an existing window.
|
||||
/// </summary>
|
||||
public bool IsWindow
|
||||
{
|
||||
get
|
||||
{
|
||||
return InteropAndHelpers.IsWindow(Hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether get a value indicating whether is the window GWL_EX_STYLE is a toolwindow
|
||||
/// </summary>
|
||||
public bool IsToolWindow
|
||||
{
|
||||
get
|
||||
{
|
||||
return (InteropAndHelpers.GetWindowLong(Hwnd, InteropAndHelpers.GWL_EXSTYLE) &
|
||||
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_TOOLWINDOW) ==
|
||||
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_TOOLWINDOW;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether get a value indicating whether the window GWL_EX_STYLE is an appwindow
|
||||
/// </summary>
|
||||
public bool IsAppWindow
|
||||
{
|
||||
get
|
||||
{
|
||||
return (InteropAndHelpers.GetWindowLong(Hwnd, InteropAndHelpers.GWL_EXSTYLE) &
|
||||
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_APPWINDOW) ==
|
||||
(uint)InteropAndHelpers.ExtendedWindowStyles.WS_EX_APPWINDOW;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether get a value indicating whether the window has ITaskList_Deleted property
|
||||
/// </summary>
|
||||
public bool TaskListDeleted
|
||||
{
|
||||
get
|
||||
{
|
||||
return InteropAndHelpers.GetProp(Hwnd, "ITaskList_Deleted") != IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether get a value indicating whether the app is a cloaked UWP app
|
||||
/// </summary>
|
||||
public bool IsUWPCloaked
|
||||
{
|
||||
get
|
||||
{
|
||||
return IsWindowCloaked() && ClassName == "ApplicationFrameWindow";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether determines whether the specified windows is the owner
|
||||
/// </summary>
|
||||
public bool IsOwner
|
||||
{
|
||||
get
|
||||
{
|
||||
return InteropAndHelpers.GetWindow(Hwnd, InteropAndHelpers.GetWindowCmd.GW_OWNER) != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether is the window cloaked. To detect UWP apps in background or win32 apps running in another virtual desktop
|
||||
/// </summary>
|
||||
public bool IsWindowCloaked()
|
||||
{
|
||||
int isCloaked = 0;
|
||||
const int DWMWA_CLOAKED = 14;
|
||||
InteropAndHelpers.DwmGetWindowAttribute(hwnd, DWMWA_CLOAKED, out isCloaked, sizeof(int));
|
||||
return isCloaked != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether returns true if the window is minimized
|
||||
/// </summary>
|
||||
public bool Minimized
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetWindowSizeState() == WindowSizeState.Minimized;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Window"/> class.
|
||||
/// Initializes a new Window representation
|
||||
/// </summary>
|
||||
/// <param name="hwnd">the handle to the window we are representing</param>
|
||||
public Window(IntPtr hwnd)
|
||||
{
|
||||
// TODO: Add verification as to whether the window handle is valid
|
||||
this.hwnd = hwnd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Highlights a window to help the user identify the window that has been selected
|
||||
/// </summary>
|
||||
public void HighlightWindow()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Switches desktop focus to the window
|
||||
/// </summary>
|
||||
public void SwitchToWindow()
|
||||
{
|
||||
// The following block is necessary because
|
||||
// 1) There is a weird flashing behavior when trying
|
||||
// to use ShowWindow for switching tabs in IE
|
||||
// 2) SetForegroundWindow fails on minimized windows
|
||||
if (ProcessName.ToLower().Equals("iexplore.exe") || !Minimized)
|
||||
{
|
||||
InteropAndHelpers.SetForegroundWindow(Hwnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
InteropAndHelpers.ShowWindow(Hwnd, InteropAndHelpers.ShowWindowCommands.Restore);
|
||||
}
|
||||
|
||||
InteropAndHelpers.FlashWindow(Hwnd, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the window name to string along with the process name
|
||||
/// </summary>
|
||||
/// <returns>The title of the window</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Title + " (" + ProcessName.ToUpper() + ")";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns what the window size is
|
||||
/// </summary>
|
||||
/// <returns>The state (minimized, maximized, etc..) of the window</returns>
|
||||
public WindowSizeState GetWindowSizeState()
|
||||
{
|
||||
InteropAndHelpers.GetWindowPlacement(Hwnd, out InteropAndHelpers.WINDOWPLACEMENT placement);
|
||||
|
||||
switch (placement.ShowCmd)
|
||||
{
|
||||
case InteropAndHelpers.ShowWindowCommands.Normal:
|
||||
return WindowSizeState.Normal;
|
||||
case InteropAndHelpers.ShowWindowCommands.Minimize:
|
||||
case InteropAndHelpers.ShowWindowCommands.ShowMinimized:
|
||||
return WindowSizeState.Minimized;
|
||||
case InteropAndHelpers.ShowWindowCommands.Maximize: // No need for ShowMaximized here since its also of value 3
|
||||
return WindowSizeState.Maximized;
|
||||
default:
|
||||
// throw new Exception("Don't know how to handle window state = " + placement.ShowCmd);
|
||||
return WindowSizeState.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum to simplify the state of the window
|
||||
/// </summary>
|
||||
public enum WindowSizeState
|
||||
{
|
||||
Normal,
|
||||
Minimized,
|
||||
Maximized,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the process using the window handle
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The handle to the window</param>
|
||||
/// <returns>A string representing the process name or an empty string if the function fails</returns>
|
||||
private string GetProcessNameFromWindowHandle(IntPtr hwnd)
|
||||
{
|
||||
uint processId = GetProcessIDFromWindowHandle(hwnd);
|
||||
ProcessID = processId;
|
||||
IntPtr processHandle = InteropAndHelpers.OpenProcess(InteropAndHelpers.ProcessAccessFlags.AllAccess, true, (int)processId);
|
||||
StringBuilder processName = new StringBuilder(MaximumFileNameLength);
|
||||
|
||||
if (InteropAndHelpers.GetProcessImageFileName(processHandle, processName, MaximumFileNameLength) != 0)
|
||||
{
|
||||
return processName.ToString().Split('\\').Reverse().ToArray()[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the process ID for the Window handle
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The handle to the window</param>
|
||||
/// <returns>The process ID</returns>
|
||||
private uint GetProcessIDFromWindowHandle(IntPtr hwnd)
|
||||
{
|
||||
InteropAndHelpers.GetWindowThreadProcessId(hwnd, out uint processId);
|
||||
return processId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
internal class WindowResult : Window
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of letters in between constant for when
|
||||
/// the result hasn't been set yet
|
||||
/// </summary>
|
||||
public const int NoResult = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets properties that signify how many characters (including spaces)
|
||||
/// were found when matching the results
|
||||
/// </summary>
|
||||
public int LettersInBetweenScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WindowResult"/> class.
|
||||
/// Constructor for WindowResult
|
||||
/// </summary>
|
||||
public WindowResult(Window window)
|
||||
: base(window.Hwnd)
|
||||
{
|
||||
LettersInBetweenScore = NoResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.Plugin.WindowWalker.Components
|
||||
{
|
||||
internal class WindowResult : Window
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of letters in between constant for when
|
||||
/// the result hasn't been set yet
|
||||
/// </summary>
|
||||
public const int NoResult = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets properties that signify how many characters (including spaces)
|
||||
/// were found when matching the results
|
||||
/// </summary>
|
||||
public int LettersInBetweenScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WindowResult"/> class.
|
||||
/// Constructor for WindowResult
|
||||
/// </summary>
|
||||
public WindowResult(Window window)
|
||||
: base(window.Hwnd)
|
||||
{
|
||||
LettersInBetweenScore = NoResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user