From fe0153be088d8f82877d7ea06b46364a556c68f5 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Wed, 15 Dec 2021 05:21:40 -0500 Subject: [PATCH 01/11] Initial commit --- Flow.Launcher/Flow.Launcher.csproj | 33 ++++++++++++ Flow.Launcher/ViewModel/MainViewModel.cs | 65 +++++++++++++++++++++++- 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index f431504c2e4..117dececf5a 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -77,6 +77,24 @@ Designer PreserveNewest + + 1 + 1 + eab22ac0-30c1-11cf-a7eb-0000c05bae0b + 0 + tlbimp + false + true + + + 0 + 1 + 50a7e9b0-70ef-11d1-b75a-00a0c90564fe + 0 + tlbimp + false + true + PreserveNewest @@ -110,6 +128,21 @@ + + + True + True + Settings.settings + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index abf3a1d14ea..cbe35e0f587 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -20,7 +20,9 @@ using Microsoft.VisualStudio.Threading; using System.Threading.Channels; using ISavable = Flow.Launcher.Plugin.ISavable; - +using System.Runtime.InteropServices; +using System.Text; +using SHDocVw; namespace Flow.Launcher.ViewModel { @@ -720,6 +722,62 @@ private void SetOpenResultModifiers() OpenResultCommandModifiers = _settings.OpenResultModifiers ?? DefaultOpenResultModifiers; } + private static string GetActiveExplorerPath() + { + // get the active window + IntPtr handle = GetForegroundWindow(); + + // Required ref: SHDocVw (Microsoft Internet Controls COM Object) - C:\Windows\system32\ShDocVw.dll + ShellWindows shellWindows = new SHDocVw.ShellWindows(); + + // loop through all windows + foreach (InternetExplorer window in shellWindows) + { + // match active window + if (window.HWND == (int)handle) + { + // Required ref: Shell32 - C:\Windows\system32\Shell32.dll + var shellWindow = window.Document as Shell32.IShellFolderViewDual2; + + // will be null if you are in Internet Explorer for example + if (shellWindow != null) + { + // Item without an index returns the current object + var currentFolder = shellWindow.Folder.Items().Item(); + + // special folder - use window title + // for some reason on "Desktop" gives null + if (currentFolder == null || currentFolder.Path.StartsWith("::")) + { + // Get window title instead + const int nChars = 256; + StringBuilder Buff = new StringBuilder(nChars); + if (GetWindowText(handle, Buff, nChars) > 0) + { + return Buff.ToString(); + } + } + else + { + return currentFolder.Path; + } + } + + break; + } + } + + return null; + } + + // COM Imports + + [DllImport("user32.dll")] + private static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll")] + static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); + public void ToggleFlowLauncher() { if (!MainWindowVisibilityStatus) @@ -734,6 +792,9 @@ public void ToggleFlowLauncher() public void Show() { + string _explorerPath = GetActiveExplorerPath(); + + ChangeQueryText($"{_explorerPath}\\>"); if (_settings.UseSound) { MediaPlayer media = new MediaPlayer(); @@ -749,6 +810,8 @@ public void Show() ((MainWindow)Application.Current.MainWindow).WindowAnimator(); MainWindowOpacity = 1; + + } public async void Hide() From 79a6fda289dfa641e011588f500d98b22425b3d2 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Wed, 15 Dec 2021 05:24:31 -0500 Subject: [PATCH 02/11] Only insert when explorer is active --- Flow.Launcher/ViewModel/MainViewModel.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index cbe35e0f587..7a48d159fca 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -793,8 +793,11 @@ public void ToggleFlowLauncher() public void Show() { string _explorerPath = GetActiveExplorerPath(); - - ChangeQueryText($"{_explorerPath}\\>"); + if (_explorerPath != null) + { + ChangeQueryText($"{_explorerPath}\\>"); + } + if (_settings.UseSound) { MediaPlayer media = new MediaPlayer(); From 1fdaec2648f14994b9b15fc86c732629796f6f13 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Wed, 15 Dec 2021 06:15:05 -0500 Subject: [PATCH 03/11] ChangeQuery after window is visible --- Flow.Launcher/ViewModel/MainViewModel.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 7a48d159fca..b525ac34222 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -731,7 +731,7 @@ private static string GetActiveExplorerPath() ShellWindows shellWindows = new SHDocVw.ShellWindows(); // loop through all windows - foreach (InternetExplorer window in shellWindows) + foreach (SHDocVw.InternetExplorer window in shellWindows) { // match active window if (window.HWND == (int)handle) @@ -793,10 +793,7 @@ public void ToggleFlowLauncher() public void Show() { string _explorerPath = GetActiveExplorerPath(); - if (_explorerPath != null) - { - ChangeQueryText($"{_explorerPath}\\>"); - } + if (_settings.UseSound) { @@ -813,7 +810,10 @@ public void Show() ((MainWindow)Application.Current.MainWindow).WindowAnimator(); MainWindowOpacity = 1; - + if (_explorerPath != null && _explorerPath != "File Explorer") + { + ChangeQueryText($"{_explorerPath}\\>"); + } } From 1109f9887e78ddcfda62f0e775893f6161344ec2 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Thu, 16 Dec 2021 02:03:22 -0500 Subject: [PATCH 04/11] Remove unnecessary changes --- Flow.Launcher/Flow.Launcher.csproj | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 117dececf5a..9d40427005a 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -128,21 +128,6 @@ - - - True - True - Settings.settings - - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - From aa5ca76b180b94680ee4f1f677581eb35bbf7424 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Mon, 20 Dec 2021 03:34:41 -0500 Subject: [PATCH 05/11] Check window is InternetExplorer type --- Flow.Launcher/ViewModel/MainViewModel.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index b525ac34222..412af09fdfd 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -731,13 +731,19 @@ private static string GetActiveExplorerPath() ShellWindows shellWindows = new SHDocVw.ShellWindows(); // loop through all windows - foreach (SHDocVw.InternetExplorer window in shellWindows) + foreach (var window in shellWindows) { + if (window is not SHDocVw.InternetExplorer) + { + continue; + } + + var explorerWindow = (SHDocVw.InternetExplorer)window; // match active window - if (window.HWND == (int)handle) + if (explorerWindow.HWND == (int)handle) { // Required ref: Shell32 - C:\Windows\system32\Shell32.dll - var shellWindow = window.Document as Shell32.IShellFolderViewDual2; + var shellWindow = explorerWindow.Document as Shell32.IShellFolderViewDual2; // will be null if you are in Internet Explorer for example if (shellWindow != null) From c039b17d93c66717dbdaf4a14843ce19a224f5c8 Mon Sep 17 00:00:00 2001 From: stefnotch Date: Sat, 16 Jul 2022 11:16:00 +0200 Subject: [PATCH 06/11] Refactor file explorer path getting --- Flow.Launcher/Helper/FileExplorerHelper.cs | 70 ++++++++++++++++++++++ Flow.Launcher/ViewModel/MainViewModel.cs | 66 +------------------- 2 files changed, 72 insertions(+), 64 deletions(-) create mode 100644 Flow.Launcher/Helper/FileExplorerHelper.cs diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs new file mode 100644 index 00000000000..16152e8306d --- /dev/null +++ b/Flow.Launcher/Helper/FileExplorerHelper.cs @@ -0,0 +1,70 @@ +using System; +using System.Text; +using System.Runtime.InteropServices; +using System.IO; + +namespace Flow.Launcher.Helper +{ + public class FileExplorerHelper + { + + /// + /// Gets the path of the file explorer that is currently in the foreground + /// + public static string GetActiveExplorerPath() + { + var explorerWindow = GetActiveExplorer(); + string locationUrl = explorerWindow.LocationURL; + if (!string.IsNullOrEmpty(locationUrl)) + { + return new Uri(locationUrl).LocalPath; + } + else + { + return null; + } + } + + /// + /// Gets the file explorer that is currently in the foreground + /// + private static SHDocVw.InternetExplorer GetActiveExplorer() + { + // get the active window + IntPtr handle = GetForegroundWindow(); + + // Required ref: SHDocVw (Microsoft Internet Controls COM Object) - C:\Windows\system32\ShDocVw.dll + var shellWindows = new SHDocVw.ShellWindows(); + + // loop through all windows + foreach (var window in shellWindows) + { + if (window is SHDocVw.InternetExplorer explorerWindow && new IntPtr(explorerWindow.HWND) == handle) + { + // we have found the desired window, now let's make sure that it is indeed a file explorer + // we don't want the Internet Explorer or the classic control panel + if (explorerWindow.Document is not Shell32.IShellFolderViewDual2) + { + return null; + } + if (Path.GetFileName(explorerWindow.FullName) != "explorer.exe") + { + return null; + } + + return explorerWindow; + } + } + + return null; + } + + // COM Imports + + [DllImport("user32.dll")] + private static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll")] + static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); + } +} diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 412af09fdfd..ff0c8833931 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -722,68 +722,6 @@ private void SetOpenResultModifiers() OpenResultCommandModifiers = _settings.OpenResultModifiers ?? DefaultOpenResultModifiers; } - private static string GetActiveExplorerPath() - { - // get the active window - IntPtr handle = GetForegroundWindow(); - - // Required ref: SHDocVw (Microsoft Internet Controls COM Object) - C:\Windows\system32\ShDocVw.dll - ShellWindows shellWindows = new SHDocVw.ShellWindows(); - - // loop through all windows - foreach (var window in shellWindows) - { - if (window is not SHDocVw.InternetExplorer) - { - continue; - } - - var explorerWindow = (SHDocVw.InternetExplorer)window; - // match active window - if (explorerWindow.HWND == (int)handle) - { - // Required ref: Shell32 - C:\Windows\system32\Shell32.dll - var shellWindow = explorerWindow.Document as Shell32.IShellFolderViewDual2; - - // will be null if you are in Internet Explorer for example - if (shellWindow != null) - { - // Item without an index returns the current object - var currentFolder = shellWindow.Folder.Items().Item(); - - // special folder - use window title - // for some reason on "Desktop" gives null - if (currentFolder == null || currentFolder.Path.StartsWith("::")) - { - // Get window title instead - const int nChars = 256; - StringBuilder Buff = new StringBuilder(nChars); - if (GetWindowText(handle, Buff, nChars) > 0) - { - return Buff.ToString(); - } - } - else - { - return currentFolder.Path; - } - } - - break; - } - } - - return null; - } - - // COM Imports - - [DllImport("user32.dll")] - private static extern IntPtr GetForegroundWindow(); - - [DllImport("user32.dll")] - static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); - public void ToggleFlowLauncher() { if (!MainWindowVisibilityStatus) @@ -798,7 +736,7 @@ public void ToggleFlowLauncher() public void Show() { - string _explorerPath = GetActiveExplorerPath(); + string _explorerPath = FileExplorerHelper.GetActiveExplorerPath(); if (_settings.UseSound) @@ -816,7 +754,7 @@ public void Show() ((MainWindow)Application.Current.MainWindow).WindowAnimator(); MainWindowOpacity = 1; - if (_explorerPath != null && _explorerPath != "File Explorer") + if (_explorerPath != null) { ChangeQueryText($"{_explorerPath}\\>"); } From 81bacdb9a72e5482788d2f90933e46659fd4ce42 Mon Sep 17 00:00:00 2001 From: stefnotch Date: Sat, 16 Jul 2022 11:20:36 +0200 Subject: [PATCH 07/11] Remove unused function --- Flow.Launcher/Helper/FileExplorerHelper.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs index 16152e8306d..3b24b741407 100644 --- a/Flow.Launcher/Helper/FileExplorerHelper.cs +++ b/Flow.Launcher/Helper/FileExplorerHelper.cs @@ -63,8 +63,5 @@ private static SHDocVw.InternetExplorer GetActiveExplorer() [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); - - [DllImport("user32.dll")] - static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); } } From ab306d90cc1ef0187b3227c9174d303e846c38fa Mon Sep 17 00:00:00 2001 From: stefnotch Date: Sat, 16 Jul 2022 11:22:31 +0200 Subject: [PATCH 08/11] Remove unused imports --- Flow.Launcher/ViewModel/MainViewModel.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index ff0c8833931..d785249a6f7 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -20,9 +20,6 @@ using Microsoft.VisualStudio.Threading; using System.Threading.Channels; using ISavable = Flow.Launcher.Plugin.ISavable; -using System.Runtime.InteropServices; -using System.Text; -using SHDocVw; namespace Flow.Launcher.ViewModel { From 1606908d28484c1cc63410be0bbd2ef499730e25 Mon Sep 17 00:00:00 2001 From: stefnotch Date: Mon, 8 Aug 2022 19:07:18 +0200 Subject: [PATCH 09/11] Move to dynamic --- Flow.Launcher/Flow.Launcher.csproj | 18 ------------ Flow.Launcher/Helper/FileExplorerHelper.cs | 34 +++++++++------------- 2 files changed, 14 insertions(+), 38 deletions(-) diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 9d40427005a..f431504c2e4 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -77,24 +77,6 @@ Designer PreserveNewest - - 1 - 1 - eab22ac0-30c1-11cf-a7eb-0000c05bae0b - 0 - tlbimp - false - true - - - 0 - 1 - 50a7e9b0-70ef-11d1-b75a-00a0c90564fe - 0 - tlbimp - false - true - PreserveNewest diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs index 3b24b741407..22c3de63ff9 100644 --- a/Flow.Launcher/Helper/FileExplorerHelper.cs +++ b/Flow.Launcher/Helper/FileExplorerHelper.cs @@ -14,7 +14,7 @@ public class FileExplorerHelper public static string GetActiveExplorerPath() { var explorerWindow = GetActiveExplorer(); - string locationUrl = explorerWindow.LocationURL; + string locationUrl = explorerWindow?.LocationURL; if (!string.IsNullOrEmpty(locationUrl)) { return new Uri(locationUrl).LocalPath; @@ -28,31 +28,25 @@ public static string GetActiveExplorerPath() /// /// Gets the file explorer that is currently in the foreground /// - private static SHDocVw.InternetExplorer GetActiveExplorer() + private static dynamic GetActiveExplorer() { // get the active window IntPtr handle = GetForegroundWindow(); - // Required ref: SHDocVw (Microsoft Internet Controls COM Object) - C:\Windows\system32\ShDocVw.dll - var shellWindows = new SHDocVw.ShellWindows(); - - // loop through all windows - foreach (var window in shellWindows) + Type type = Type.GetTypeFromProgID("Shell.Application"); + if (type == null) return null; + dynamic shell = Activator.CreateInstance(type); + var openWindows = shell.Windows(); + for (int i = 0; i < openWindows.Count; i++) { - if (window is SHDocVw.InternetExplorer explorerWindow && new IntPtr(explorerWindow.HWND) == handle) - { - // we have found the desired window, now let's make sure that it is indeed a file explorer - // we don't want the Internet Explorer or the classic control panel - if (explorerWindow.Document is not Shell32.IShellFolderViewDual2) - { - return null; - } - if (Path.GetFileName(explorerWindow.FullName) != "explorer.exe") - { - return null; - } + var window = openWindows.Item(i); + if (window == null) continue; - return explorerWindow; + // find the desired window and make sure that it is indeed a file explorer + // we don't want the Internet Explorer or the classic control panel + if (Path.GetFileName((string)window.FullName) == "explorer.exe" && new IntPtr(window.HWND) == handle) + { + return window; } } From 0a062c310a1386d9e7c9bbe4ad59e3927981ea96 Mon Sep 17 00:00:00 2001 From: stefnotch Date: Mon, 8 Aug 2022 19:19:05 +0200 Subject: [PATCH 10/11] Fix querying of explorer window --- Flow.Launcher/Helper/FileExplorerHelper.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs index 22c3de63ff9..c6d50f514d0 100644 --- a/Flow.Launcher/Helper/FileExplorerHelper.cs +++ b/Flow.Launcher/Helper/FileExplorerHelper.cs @@ -44,7 +44,8 @@ private static dynamic GetActiveExplorer() // find the desired window and make sure that it is indeed a file explorer // we don't want the Internet Explorer or the classic control panel - if (Path.GetFileName((string)window.FullName) == "explorer.exe" && new IntPtr(window.HWND) == handle) + // ToLower() is needed, because Windows can report the path as "C:\\Windows\\Explorer.EXE" + if (Path.GetFileName((string)window.FullName).ToLower() == "explorer.exe" && new IntPtr(window.HWND) == handle) { return window; } @@ -53,8 +54,6 @@ private static dynamic GetActiveExplorer() return null; } - // COM Imports - [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); } From 55dee4f471641651583208f4ffbdc4b07299a4ab Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Tue, 3 Jan 2023 23:05:35 -0500 Subject: [PATCH 11/11] Use the explorer window with the lowest z-index to allow active explorer path be a built-in shortcut --- .../FileExplorerHelper.cs | 89 +++++++++++++++++++ .../UserSettings/Settings.cs | 6 +- Flow.Launcher/Helper/FileExplorerHelper.cs | 60 ------------- Flow.Launcher/Languages/en.xaml | 1 + 4 files changed, 94 insertions(+), 62 deletions(-) create mode 100644 Flow.Launcher.Infrastructure/FileExplorerHelper.cs delete mode 100644 Flow.Launcher/Helper/FileExplorerHelper.cs diff --git a/Flow.Launcher.Infrastructure/FileExplorerHelper.cs b/Flow.Launcher.Infrastructure/FileExplorerHelper.cs new file mode 100644 index 00000000000..a3b1bd6b7e6 --- /dev/null +++ b/Flow.Launcher.Infrastructure/FileExplorerHelper.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; + +namespace Flow.Launcher.Infrastructure +{ + public static class FileExplorerHelper + { + /// + /// Gets the path of the file explorer that is currently in the foreground + /// + public static string GetActiveExplorerPath() + { + var explorerWindow = GetActiveExplorer(); + string locationUrl = explorerWindow?.LocationURL; + return !string.IsNullOrEmpty(locationUrl) ? new Uri(locationUrl).LocalPath : null; + } + + /// + /// Gets the file explorer that is currently in the foreground + /// + private static dynamic GetActiveExplorer() + { + Type type = Type.GetTypeFromProgID("Shell.Application"); + if (type == null) return null; + dynamic shell = Activator.CreateInstance(type); + if (shell == null) + { + return null; + } + + var explorerWindows = new List(); + var openWindows = shell.Windows(); + for (int i = 0; i < openWindows.Count; i++) + { + var window = openWindows.Item(i); + if (window == null) continue; + + // find the desired window and make sure that it is indeed a file explorer + // we don't want the Internet Explorer or the classic control panel + // ToLower() is needed, because Windows can report the path as "C:\\Windows\\Explorer.EXE" + if (Path.GetFileName((string)window.FullName)?.ToLower() == "explorer.exe") + { + explorerWindows.Add(window); + } + } + + if (explorerWindows.Count == 0) return null; + + var zOrders = GetZOrder(explorerWindows); + + return explorerWindows.Zip(zOrders).MinBy(x => x.Second).First; + } + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); + + private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); + + /// + /// Gets the z-order for one or more windows atomically with respect to each other. In Windows, smaller z-order is higher. If the window is not top level, the z order is returned as -1. + /// + private static IEnumerable GetZOrder(List hWnds) + { + var z = new int[hWnds.Count]; + for (var i = 0; i < hWnds.Count; i++) z[i] = -1; + + var index = 0; + var numRemaining = hWnds.Count; + EnumWindows((wnd, _) => + { + var searchIndex = hWnds.FindIndex(x => x.HWND == wnd.ToInt32()); + if (searchIndex != -1) + { + z[searchIndex] = index; + numRemaining--; + if (numRemaining == 0) return false; + } + index++; + return true; + }, IntPtr.Zero); + + return z; + } + } +} diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index a184520d081..753334e2392 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -192,8 +192,10 @@ public string QuerySearchPrecisionString public ObservableCollection CustomShortcuts { get; set; } = new ObservableCollection(); [JsonIgnore] - public ObservableCollection BuiltinShortcuts { get; set; } = new ObservableCollection() { - new BuiltinShortcutModel("{clipboard}", "shortcut_clipboard_description", Clipboard.GetText) + public ObservableCollection BuiltinShortcuts { get; set; } = new() + { + new BuiltinShortcutModel("{clipboard}", "shortcut_clipboard_description", Clipboard.GetText), + new BuiltinShortcutModel("{active_explorer_path}", "shortcut_active_explorer_path", FileExplorerHelper.GetActiveExplorerPath) }; public bool DontPromptUpdateMsg { get; set; } diff --git a/Flow.Launcher/Helper/FileExplorerHelper.cs b/Flow.Launcher/Helper/FileExplorerHelper.cs deleted file mode 100644 index c6d50f514d0..00000000000 --- a/Flow.Launcher/Helper/FileExplorerHelper.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Text; -using System.Runtime.InteropServices; -using System.IO; - -namespace Flow.Launcher.Helper -{ - public class FileExplorerHelper - { - - /// - /// Gets the path of the file explorer that is currently in the foreground - /// - public static string GetActiveExplorerPath() - { - var explorerWindow = GetActiveExplorer(); - string locationUrl = explorerWindow?.LocationURL; - if (!string.IsNullOrEmpty(locationUrl)) - { - return new Uri(locationUrl).LocalPath; - } - else - { - return null; - } - } - - /// - /// Gets the file explorer that is currently in the foreground - /// - private static dynamic GetActiveExplorer() - { - // get the active window - IntPtr handle = GetForegroundWindow(); - - Type type = Type.GetTypeFromProgID("Shell.Application"); - if (type == null) return null; - dynamic shell = Activator.CreateInstance(type); - var openWindows = shell.Windows(); - for (int i = 0; i < openWindows.Count; i++) - { - var window = openWindows.Item(i); - if (window == null) continue; - - // find the desired window and make sure that it is indeed a file explorer - // we don't want the Internet Explorer or the classic control panel - // ToLower() is needed, because Windows can report the path as "C:\\Windows\\Explorer.EXE" - if (Path.GetFileName((string)window.FullName).ToLower() == "explorer.exe" && new IntPtr(window.HWND) == handle) - { - return window; - } - } - - return null; - } - - [DllImport("user32.dll")] - private static extern IntPtr GetForegroundWindow(); - } -} diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index b192617cb79..49c603dc851 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -176,6 +176,7 @@ Are you sure you want to delete {0} plugin hotkey? Are you sure you want to delete shortcut: {0} with expansion {1}? Get text from clipboard. + Get path from active explorer. Query window shadow effect Shadow effect has a substantial usage of GPU. Not recommended if your computer performance is limited. Window Width Size