mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge pull request #2742 from Flow-Launcher/explorer-plugin-integrated-context-menu
Integrate native Windows context menu directly into the Explorer plugin
This commit is contained in:
commit
42939eaba2
7 changed files with 720 additions and 55 deletions
|
|
@ -62,13 +62,13 @@
|
||||||
<StackPanel
|
<StackPanel
|
||||||
x:Name="HotkeyArea"
|
x:Name="HotkeyArea"
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Margin="0,0,10,0"
|
Margin="0 0 10 0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Visibility="{Binding ShowOpenResultHotkey}">
|
Visibility="{Binding ShowOpenResultHotkey}">
|
||||||
<TextBlock
|
<TextBlock
|
||||||
x:Name="Hotkey"
|
x:Name="Hotkey"
|
||||||
Margin="12,0,12,0"
|
Margin="12 0 12 0"
|
||||||
Padding="0,0,0,0"
|
Padding="0 0 0 0"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Style="{DynamicResource ItemHotkeyStyle}">
|
Style="{DynamicResource ItemHotkeyStyle}">
|
||||||
|
|
@ -97,17 +97,18 @@
|
||||||
|
|
||||||
<Border
|
<Border
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="9,0,0,0"
|
Margin="9 0 0 0"
|
||||||
BorderBrush="Transparent"
|
BorderBrush="Transparent"
|
||||||
BorderThickness="1">
|
BorderThickness="1">
|
||||||
<Image
|
<Image
|
||||||
x:Name="ImageIcon"
|
x:Name="ImageIcon"
|
||||||
Margin="0,0,0,0"
|
Margin="0 0 0 0"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
IsHitTestVisible="False"
|
IsHitTestVisible="False"
|
||||||
RenderOptions.BitmapScalingMode="Fant"
|
RenderOptions.BitmapScalingMode="Fant"
|
||||||
Source="{Binding Image, TargetNullValue={x:Null}}"
|
Source="{Binding Image, TargetNullValue={x:Null}}"
|
||||||
Stretch="Uniform"
|
Stretch="Uniform"
|
||||||
|
StretchDirection="DownOnly"
|
||||||
Style="{DynamicResource ImageIconStyle}"
|
Style="{DynamicResource ImageIconStyle}"
|
||||||
Visibility="{Binding ShowIcon}">
|
Visibility="{Binding ShowIcon}">
|
||||||
<Image.Clip>
|
<Image.Clip>
|
||||||
|
|
@ -130,7 +131,7 @@
|
||||||
</Border>
|
</Border>
|
||||||
<Border
|
<Border
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="9,0,0,0"
|
Margin="9 0 0 0"
|
||||||
BorderBrush="Transparent"
|
BorderBrush="Transparent"
|
||||||
BorderThickness="0">
|
BorderThickness="0">
|
||||||
<TextBlock
|
<TextBlock
|
||||||
|
|
@ -146,7 +147,7 @@
|
||||||
|
|
||||||
<Grid
|
<Grid
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="6,0,10,0"
|
Margin="6 0 10 0"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Center">
|
VerticalAlignment="Center">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
|
@ -172,7 +173,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
x:Name="Title"
|
x:Name="Title"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Margin="0,0,0,1"
|
Margin="0 0 0 1"
|
||||||
VerticalAlignment="Bottom"
|
VerticalAlignment="Bottom"
|
||||||
DockPanel.Dock="Left"
|
DockPanel.Dock="Left"
|
||||||
FontSize="{Binding Settings.ResultItemFontSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
FontSize="{Binding Settings.ResultItemFontSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
|
@ -192,7 +193,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
x:Name="SubTitle"
|
x:Name="SubTitle"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Margin="0,1,0,0"
|
Margin="0 1 0 0"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
FontSize="{Binding Settings.ResultSubItemFontSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
FontSize="{Binding Settings.ResultSubItemFontSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
IsEnabled="False"
|
IsEnabled="False"
|
||||||
|
|
@ -221,9 +222,10 @@
|
||||||
<!-- http://stackoverflow.com/questions/16819577/setting-background-color-or-wpf-4-0-listbox-windows-8/#16820062 -->
|
<!-- http://stackoverflow.com/questions/16819577/setting-background-color-or-wpf-4-0-listbox-windows-8/#16820062 -->
|
||||||
<ListBox.ItemContainerStyle>
|
<ListBox.ItemContainerStyle>
|
||||||
<Style TargetType="{x:Type ListBoxItem}">
|
<Style TargetType="{x:Type ListBoxItem}">
|
||||||
|
<Setter Property="Height" Value="{Binding Settings.ItemHeightSize}" />
|
||||||
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
<EventSetter Event="MouseEnter" Handler="OnMouseEnter" />
|
<EventSetter Event="MouseEnter" Handler="OnMouseEnter" />
|
||||||
<EventSetter Event="MouseMove" Handler="OnMouseMove" />
|
<EventSetter Event="MouseMove" Handler="OnMouseMove" />
|
||||||
<Setter Property="Height" Value="{Binding Settings.ItemHeightSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
|
||||||
<Setter Property="Margin" Value="0" />
|
<Setter Property="Margin" Value="0" />
|
||||||
<Setter Property="Padding" Value="0" />
|
<Setter Property="Padding" Value="0" />
|
||||||
<Setter Property="BorderThickness" Value="0" />
|
<Setter Property="BorderThickness" Value="0" />
|
||||||
|
|
@ -256,4 +258,4 @@
|
||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
</ListBox.ItemContainerStyle>
|
</ListBox.ItemContainerStyle>
|
||||||
</ListBox>
|
</ListBox>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ using Flow.Launcher.Plugin.SharedCommands;
|
||||||
using Flow.Launcher.Plugin.Explorer.Search;
|
using Flow.Launcher.Plugin.Explorer.Search;
|
||||||
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
|
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Flow.Launcher.Plugin.Explorer.Helper;
|
||||||
using MessageBox = System.Windows.Forms.MessageBox;
|
using MessageBox = System.Windows.Forms.MessageBox;
|
||||||
using MessageBoxIcon = System.Windows.Forms.MessageBoxIcon;
|
using MessageBoxIcon = System.Windows.Forms.MessageBoxIcon;
|
||||||
using MessageBoxButton = System.Windows.Forms.MessageBoxButtons;
|
using MessageBoxButton = System.Windows.Forms.MessageBoxButtons;
|
||||||
|
|
@ -252,6 +253,45 @@ namespace Flow.Launcher.Plugin.Explorer
|
||||||
IcoPath = Constants.DifferentUserIconImagePath,
|
IcoPath = Constants.DifferentUserIconImagePath,
|
||||||
Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\ue748"),
|
Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\ue748"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (record.Type is ResultType.File or ResultType.Folder && Settings.ShowInlinedWindowsContextMenu)
|
||||||
|
{
|
||||||
|
var includedItems = Settings
|
||||||
|
.WindowsContextMenuIncludedItems
|
||||||
|
.Replace("\r", "")
|
||||||
|
.Split("\n")
|
||||||
|
.Where(v => !string.IsNullOrWhiteSpace(v))
|
||||||
|
.ToArray();
|
||||||
|
var excludedItems = Settings
|
||||||
|
.WindowsContextMenuExcludedItems
|
||||||
|
.Replace("\r", "")
|
||||||
|
.Split("\n")
|
||||||
|
.Where(v => !string.IsNullOrWhiteSpace(v))
|
||||||
|
.ToArray();
|
||||||
|
var menuItems = ShellContextMenuDisplayHelper
|
||||||
|
.GetContextMenuWithIcons(record.FullPath)
|
||||||
|
.Where(contextMenuItem =>
|
||||||
|
(includedItems.Length == 0 || includedItems.Any(filter =>
|
||||||
|
contextMenuItem.Label.Contains(filter, StringComparison.OrdinalIgnoreCase)
|
||||||
|
)) &&
|
||||||
|
(excludedItems.Length == 0 || !excludedItems.Any(filter =>
|
||||||
|
contextMenuItem.Label.Contains(filter, StringComparison.OrdinalIgnoreCase)
|
||||||
|
))
|
||||||
|
);
|
||||||
|
foreach (var menuItem in menuItems)
|
||||||
|
{
|
||||||
|
contextMenus.Add(new Result
|
||||||
|
{
|
||||||
|
Title = menuItem.Label,
|
||||||
|
Icon = () => menuItem.Icon,
|
||||||
|
Action = _ =>
|
||||||
|
{
|
||||||
|
ShellContextMenuDisplayHelper.ExecuteContextMenuItem(record.FullPath, menuItem.CommandId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return contextMenus;
|
return contextMenus;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,524 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Interop;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
|
||||||
|
namespace Flow.Launcher.Plugin.Explorer.Helper;
|
||||||
|
|
||||||
|
public static class ShellContextMenuDisplayHelper
|
||||||
|
{
|
||||||
|
#region DllImport
|
||||||
|
|
||||||
|
[DllImport("shell32.dll")]
|
||||||
|
private static extern Int32 SHGetMalloc(out IntPtr hObject);
|
||||||
|
|
||||||
|
[DllImport("shell32.dll")]
|
||||||
|
private static extern Int32 SHParseDisplayName(
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)] string pszName,
|
||||||
|
IntPtr pbc,
|
||||||
|
out IntPtr ppidl,
|
||||||
|
UInt32 sfgaoIn,
|
||||||
|
out UInt32 psfgaoOut
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("shell32.dll")]
|
||||||
|
private static extern Int32 SHBindToParent(
|
||||||
|
IntPtr pidl,
|
||||||
|
[MarshalAs(UnmanagedType.LPStruct)] Guid riid,
|
||||||
|
out IntPtr ppv,
|
||||||
|
ref IntPtr ppidlLast
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||||
|
private static extern IntPtr CreatePopupMenu();
|
||||||
|
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||||
|
private static extern bool DestroyMenu(IntPtr hMenu);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||||
|
private static extern uint GetMenuItemCount(IntPtr hMenu);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||||
|
private static extern uint GetMenuString(
|
||||||
|
IntPtr hMenu, uint uIDItem, StringBuilder lpString, int nMaxCount, uint uFlag
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||||
|
private static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||||
|
private static extern bool GetMenuItemInfo(IntPtr hMenu, uint uItem, bool fByPosition, ref MENUITEMINFO lpmii);
|
||||||
|
|
||||||
|
[DllImport("gdi32.dll")]
|
||||||
|
private static extern bool DeleteObject(IntPtr hObject);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constants
|
||||||
|
|
||||||
|
private const uint ContextMenuStartId = 0x0001;
|
||||||
|
private const uint ContextMenuEndId = 0x7FFF;
|
||||||
|
|
||||||
|
private static readonly string[] IgnoredContextMenuCommands =
|
||||||
|
{
|
||||||
|
// We haven't managed to make these work, so we don't display them in the context menu.
|
||||||
|
"Share",
|
||||||
|
"Windows.ModernShare",
|
||||||
|
"PinToStartScreen",
|
||||||
|
"CopyAsPath",
|
||||||
|
|
||||||
|
// Hide functionality provided by the Explorer plugin itself
|
||||||
|
"Copy",
|
||||||
|
"Delete"
|
||||||
|
};
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Enums
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
enum ContextMenuFlags : uint
|
||||||
|
{
|
||||||
|
Normal = 0x00000000,
|
||||||
|
DefaultOnly = 0x00000001,
|
||||||
|
VerbsOnly = 0x00000002,
|
||||||
|
Explore = 0x00000004,
|
||||||
|
NoVerbs = 0x00000008,
|
||||||
|
CanRename = 0x00000010,
|
||||||
|
NoDefault = 0x00000020,
|
||||||
|
IncludeStatic = 0x00000040,
|
||||||
|
ItemMenu = 0x00000080,
|
||||||
|
ExtendedVerbs = 0x00000100,
|
||||||
|
DisabledVerbs = 0x00000200,
|
||||||
|
AsyncVerbState = 0x00000400,
|
||||||
|
OptimizeForInvoke = 0x00000800,
|
||||||
|
SyncCascadeMenu = 0x00001000,
|
||||||
|
DoNotPickDefault = 0x00002000,
|
||||||
|
Reserved = 0xffff0000
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
enum ContextMenuInvokeCommandFlags : uint
|
||||||
|
{
|
||||||
|
Icon = 0x00000010,
|
||||||
|
Hotkey = 0x00000020,
|
||||||
|
FlagNoUi = 0x00000400,
|
||||||
|
Unicode = 0x00004000,
|
||||||
|
NoConsole = 0x00008000,
|
||||||
|
AsyncOk = 0x00100000,
|
||||||
|
NoZoneChecks = 0x00800000,
|
||||||
|
ShiftDown = 0x10000000,
|
||||||
|
ControlDown = 0x40000000,
|
||||||
|
FlagLogUsage = 0x04000000,
|
||||||
|
PointInvoke = 0x20000000
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
enum MenuItemInformationMask : uint
|
||||||
|
{
|
||||||
|
Bitmap = 0x00000080,
|
||||||
|
Checkmarks = 0x00000008,
|
||||||
|
Data = 0x00000020,
|
||||||
|
Ftype = 0x00000100,
|
||||||
|
Id = 0x00000002,
|
||||||
|
State = 0x00000001,
|
||||||
|
String = 0x00000040,
|
||||||
|
Submenu = 0x00000004,
|
||||||
|
Type = 0x00000010
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MenuItemFtype : uint
|
||||||
|
{
|
||||||
|
Bitmap = 0x00000004,
|
||||||
|
MenuBarBreak = 0x00000020,
|
||||||
|
MenuBreak = 0x00000040,
|
||||||
|
OwnerDraw = 0x00000100,
|
||||||
|
RadioCheck = 0x00000200,
|
||||||
|
RightJustify = 0x00004000,
|
||||||
|
RightOrder = 0x00002000,
|
||||||
|
Separator = 0x00000800,
|
||||||
|
String = 0x00000000,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GetCommandStringFlags : uint
|
||||||
|
{
|
||||||
|
VerbA = 0x00000000,
|
||||||
|
HelpTextA = 0x00000001,
|
||||||
|
ValidateA = 0x00000002,
|
||||||
|
Unicode = VerbW,
|
||||||
|
Verb = VerbW,
|
||||||
|
VerbW = 0x00000004,
|
||||||
|
HelpText = HelpTextW,
|
||||||
|
HelpTextW = 0x00000005,
|
||||||
|
Validate = ValidateW,
|
||||||
|
ValidateW = 0x00000006,
|
||||||
|
VerbIconW = 0x00000014
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private static IMalloc GetMalloc()
|
||||||
|
{
|
||||||
|
SHGetMalloc(out var pMalloc);
|
||||||
|
return (IMalloc)Marshal.GetTypedObjectForIUnknown(pMalloc, typeof(IMalloc));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ExecuteContextMenuItem(string fileName, uint menuItemId)
|
||||||
|
{
|
||||||
|
IMalloc malloc = null;
|
||||||
|
IntPtr originalPidl = IntPtr.Zero;
|
||||||
|
IntPtr pShellFolder = IntPtr.Zero;
|
||||||
|
IntPtr pContextMenu = IntPtr.Zero;
|
||||||
|
IntPtr hMenu = IntPtr.Zero;
|
||||||
|
IContextMenu contextMenu = null;
|
||||||
|
IShellFolder shellFolder = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
malloc = GetMalloc();
|
||||||
|
var hr = SHParseDisplayName(fileName, IntPtr.Zero, out var pidl, 0, out _);
|
||||||
|
if (hr != 0) throw new Exception("SHParseDisplayName failed");
|
||||||
|
|
||||||
|
originalPidl = pidl;
|
||||||
|
|
||||||
|
var guid = typeof(IShellFolder).GUID;
|
||||||
|
hr = SHBindToParent(pidl, guid, out pShellFolder, ref pidl);
|
||||||
|
if (hr != 0) throw new Exception("SHBindToParent failed");
|
||||||
|
|
||||||
|
shellFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(pShellFolder, typeof(IShellFolder));
|
||||||
|
hr = shellFolder.GetUIObjectOf(
|
||||||
|
IntPtr.Zero, 1, new[] { pidl }, typeof(IContextMenu).GUID, IntPtr.Zero, out pContextMenu
|
||||||
|
);
|
||||||
|
if (hr != 0) throw new Exception("GetUIObjectOf failed");
|
||||||
|
|
||||||
|
contextMenu = (IContextMenu)Marshal.GetTypedObjectForIUnknown(pContextMenu, typeof(IContextMenu));
|
||||||
|
|
||||||
|
hMenu = CreatePopupMenu();
|
||||||
|
contextMenu.QueryContextMenu(hMenu, 0, ContextMenuStartId, ContextMenuEndId, (uint)ContextMenuFlags.Explore);
|
||||||
|
|
||||||
|
var directory = Path.GetDirectoryName(fileName);
|
||||||
|
var invokeCommandInfo = new CMINVOKECOMMANDINFO
|
||||||
|
{
|
||||||
|
cbSize = (uint)Marshal.SizeOf(typeof(CMINVOKECOMMANDINFO)),
|
||||||
|
fMask = (uint)ContextMenuInvokeCommandFlags.Unicode,
|
||||||
|
hwnd = IntPtr.Zero,
|
||||||
|
lpVerb = (IntPtr)(menuItemId - ContextMenuStartId),
|
||||||
|
lpParameters = null,
|
||||||
|
lpDirectory = null,
|
||||||
|
nShow = 1,
|
||||||
|
hIcon = IntPtr.Zero,
|
||||||
|
};
|
||||||
|
|
||||||
|
hr = contextMenu.InvokeCommand(ref invokeCommandInfo);
|
||||||
|
if (hr != 0)
|
||||||
|
{
|
||||||
|
throw new Exception($"InvokeCommand failed with code {hr:X}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (hMenu != IntPtr.Zero)
|
||||||
|
DestroyMenu(hMenu);
|
||||||
|
|
||||||
|
if (contextMenu != null)
|
||||||
|
Marshal.ReleaseComObject(contextMenu);
|
||||||
|
|
||||||
|
if (pContextMenu != IntPtr.Zero)
|
||||||
|
Marshal.Release(pContextMenu);
|
||||||
|
|
||||||
|
if (shellFolder != null)
|
||||||
|
Marshal.ReleaseComObject(shellFolder);
|
||||||
|
|
||||||
|
if (pShellFolder != IntPtr.Zero)
|
||||||
|
Marshal.Release(pShellFolder);
|
||||||
|
|
||||||
|
if (originalPidl != IntPtr.Zero)
|
||||||
|
malloc?.Free(originalPidl);
|
||||||
|
|
||||||
|
if (malloc != null)
|
||||||
|
Marshal.ReleaseComObject(malloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ContextMenuItem> GetContextMenuWithIcons(string filePath)
|
||||||
|
{
|
||||||
|
IMalloc malloc = null;
|
||||||
|
IntPtr originalPidl = IntPtr.Zero;
|
||||||
|
IntPtr pShellFolder = IntPtr.Zero;
|
||||||
|
IntPtr pContextMenu = IntPtr.Zero;
|
||||||
|
IntPtr hMenu = IntPtr.Zero;
|
||||||
|
IShellFolder shellFolder = null;
|
||||||
|
IContextMenu contextMenu = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
malloc = GetMalloc();
|
||||||
|
var hr = SHParseDisplayName(filePath, IntPtr.Zero, out var pidl, 0, out _);
|
||||||
|
if (hr != 0) throw new Exception("SHParseDisplayName failed");
|
||||||
|
|
||||||
|
originalPidl = pidl;
|
||||||
|
|
||||||
|
var guid = typeof(IShellFolder).GUID;
|
||||||
|
hr = SHBindToParent(pidl, guid, out pShellFolder, ref pidl);
|
||||||
|
if (hr != 0) throw new Exception("SHBindToParent failed");
|
||||||
|
|
||||||
|
shellFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(pShellFolder, typeof(IShellFolder));
|
||||||
|
hr = shellFolder.GetUIObjectOf(
|
||||||
|
IntPtr.Zero, 1, new[] { pidl }, typeof(IContextMenu).GUID, IntPtr.Zero, out pContextMenu
|
||||||
|
);
|
||||||
|
if (hr != 0) throw new Exception("GetUIObjectOf failed");
|
||||||
|
|
||||||
|
contextMenu = (IContextMenu)Marshal.GetTypedObjectForIUnknown(pContextMenu, typeof(IContextMenu));
|
||||||
|
|
||||||
|
// Without waiting, some items, such as "Send to > Documents", don't always appear, which shifts item ids
|
||||||
|
// even though it shouldn't. Please replace this if you find a better way to fix this bug.
|
||||||
|
Thread.Sleep(200);
|
||||||
|
|
||||||
|
hMenu = CreatePopupMenu();
|
||||||
|
contextMenu.QueryContextMenu(hMenu, 0, ContextMenuStartId, ContextMenuEndId, (uint)ContextMenuFlags.Explore);
|
||||||
|
|
||||||
|
var menuItems = new List<ContextMenuItem>();
|
||||||
|
ProcessMenuWithIcons(hMenu, contextMenu, menuItems);
|
||||||
|
|
||||||
|
return menuItems;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (hMenu != IntPtr.Zero)
|
||||||
|
DestroyMenu(hMenu);
|
||||||
|
|
||||||
|
if (contextMenu != null)
|
||||||
|
Marshal.ReleaseComObject(contextMenu);
|
||||||
|
|
||||||
|
if (pContextMenu != IntPtr.Zero)
|
||||||
|
Marshal.Release(pContextMenu);
|
||||||
|
|
||||||
|
if (shellFolder != null)
|
||||||
|
Marshal.ReleaseComObject(shellFolder);
|
||||||
|
|
||||||
|
if (pShellFolder != IntPtr.Zero)
|
||||||
|
Marshal.Release(pShellFolder);
|
||||||
|
|
||||||
|
if (originalPidl != IntPtr.Zero)
|
||||||
|
malloc?.Free(originalPidl);
|
||||||
|
|
||||||
|
if (malloc != null)
|
||||||
|
Marshal.ReleaseComObject(malloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void ProcessMenuWithIcons(IntPtr hMenu, IContextMenu contextMenu, List<ContextMenuItem> menuItems, string prefix = "")
|
||||||
|
{
|
||||||
|
uint menuCount = GetMenuItemCount(hMenu);
|
||||||
|
|
||||||
|
for (uint i = 0; i < menuCount; i++)
|
||||||
|
{
|
||||||
|
var mii = new MENUITEMINFO
|
||||||
|
{
|
||||||
|
cbSize = (uint)Marshal.SizeOf(typeof(MENUITEMINFO)),
|
||||||
|
fMask = (uint)(MenuItemInformationMask.Bitmap | MenuItemInformationMask.Ftype |
|
||||||
|
MenuItemInformationMask.Submenu | MenuItemInformationMask.Id)
|
||||||
|
};
|
||||||
|
|
||||||
|
GetMenuItemInfo(hMenu, i, true, ref mii);
|
||||||
|
var menuText = new StringBuilder(256);
|
||||||
|
uint result = GetMenuString(hMenu, mii.wID, menuText, menuText.Capacity, 0);
|
||||||
|
|
||||||
|
if (result == 0 || string.IsNullOrWhiteSpace(menuText.ToString()))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuText.Replace("&", "");
|
||||||
|
|
||||||
|
IntPtr hSubMenu = GetSubMenu(hMenu, (int)i);
|
||||||
|
if (hSubMenu != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
ProcessMenuWithIcons(hSubMenu, contextMenu, menuItems, prefix + menuText + " > ");
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrWhiteSpace(menuText.ToString()))
|
||||||
|
{
|
||||||
|
var commandBuilder = new StringBuilder(256);
|
||||||
|
contextMenu.GetCommandString(
|
||||||
|
mii.wID - ContextMenuStartId,
|
||||||
|
(uint)GetCommandStringFlags.Verb,
|
||||||
|
IntPtr.Zero,
|
||||||
|
commandBuilder,
|
||||||
|
commandBuilder.Capacity
|
||||||
|
);
|
||||||
|
if (IgnoredContextMenuCommands.Contains(commandBuilder.ToString(), StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageSource icon = null;
|
||||||
|
if (mii.hbmpItem != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
icon = GetBitmapSourceFromHBitmap(mii.hbmpItem);
|
||||||
|
}
|
||||||
|
else if (mii.hbmpChecked != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
icon = GetBitmapSourceFromHBitmap(mii.hbmpChecked);
|
||||||
|
}
|
||||||
|
|
||||||
|
menuItems.Add(new ContextMenuItem(prefix + menuText, icon, mii.wID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BitmapSource GetBitmapSourceFromHBitmap(IntPtr hBitmap)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
|
||||||
|
hBitmap,
|
||||||
|
IntPtr.Zero,
|
||||||
|
Int32Rect.Empty,
|
||||||
|
BitmapSizeOptions.FromWidthAndHeight(16, 16)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!DeleteObject(hBitmap))
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to delete HBitmap.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitmapSource;
|
||||||
|
}
|
||||||
|
catch (COMException)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Data Structures
|
||||||
|
|
||||||
|
[ComImport]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[Guid("000214E6-0000-0000-C000-000000000046")]
|
||||||
|
public interface IShellFolder
|
||||||
|
{
|
||||||
|
[PreserveSig]
|
||||||
|
int ParseDisplayName(
|
||||||
|
IntPtr hwnd, IntPtr pbc, [In, MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, out uint pchEaten,
|
||||||
|
out IntPtr ppidl, ref uint pdwAttributes
|
||||||
|
);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int EnumObjects(IntPtr hwnd, uint grfFlags, out IntPtr ppenumIDList);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int BindToObject(IntPtr pidl, IntPtr pbc, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppv);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int BindToStorage(IntPtr pidl, IntPtr pbc, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppv);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int CreateViewObject(IntPtr hwndOwner, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr ppv);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetAttributesOf(
|
||||||
|
uint cidl, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] apidl, ref uint rgfInOut
|
||||||
|
);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetUIObjectOf(
|
||||||
|
IntPtr hwndOwner, uint cidl, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] IntPtr[] apidl,
|
||||||
|
[In, MarshalAs(UnmanagedType.LPStruct)]
|
||||||
|
Guid riid, IntPtr rgfReserved, out IntPtr ppv
|
||||||
|
);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetDisplayNameOf(IntPtr pidl, uint uFlags, IntPtr pName);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int SetNameOf(
|
||||||
|
IntPtr hwnd, IntPtr pidl, [In, MarshalAs(UnmanagedType.LPWStr)] string pszName, uint uFlags, out IntPtr ppidlOut
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ComImport]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[Guid("00000002-0000-0000-C000-000000000046")]
|
||||||
|
public interface IMalloc
|
||||||
|
{
|
||||||
|
[PreserveSig]
|
||||||
|
IntPtr Alloc(UInt32 cb);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
IntPtr Realloc(IntPtr pv, UInt32 cb);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
void Free(IntPtr pv);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
UInt32 GetSize(IntPtr pv);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
Int16 DidAlloc(IntPtr pv);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
void HeapMinimize();
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct CMINVOKECOMMANDINFO
|
||||||
|
{
|
||||||
|
public uint cbSize;
|
||||||
|
public uint fMask;
|
||||||
|
public IntPtr hwnd;
|
||||||
|
public IntPtr lpVerb;
|
||||||
|
[MarshalAs(UnmanagedType.LPStr)] public string lpParameters;
|
||||||
|
[MarshalAs(UnmanagedType.LPStr)] public string lpDirectory;
|
||||||
|
public int nShow;
|
||||||
|
public uint dwHotKey;
|
||||||
|
public IntPtr hIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct MENUITEMINFO
|
||||||
|
{
|
||||||
|
public uint cbSize;
|
||||||
|
public uint fMask;
|
||||||
|
public uint fType;
|
||||||
|
public uint fState;
|
||||||
|
public uint wID;
|
||||||
|
public IntPtr hSubMenu;
|
||||||
|
public IntPtr hbmpChecked;
|
||||||
|
public IntPtr hbmpUnchecked;
|
||||||
|
public IntPtr dwItemData;
|
||||||
|
public IntPtr dwTypeData;
|
||||||
|
public uint cch;
|
||||||
|
public IntPtr hbmpItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ComImport]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||||
|
[Guid("000214E4-0000-0000-C000-000000000046")]
|
||||||
|
public interface IContextMenu
|
||||||
|
{
|
||||||
|
[PreserveSig]
|
||||||
|
int QueryContextMenu(IntPtr hmenu, uint indexMenu, uint idCmdFirst, uint idCmdLast, uint uFlags);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int InvokeCommand(ref CMINVOKECOMMANDINFO pici);
|
||||||
|
|
||||||
|
[PreserveSig]
|
||||||
|
int GetCommandString(uint idcmd, uint uflags, IntPtr reserved, StringBuilder commandstring, int cch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record ContextMenuItem(string Label, ImageSource Icon, uint CommandId);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
@ -152,4 +152,9 @@
|
||||||
<system:String x:Key="flowlauncher_plugin_everything_enable_content_search">Do you want to enable content search for Everything?</system:String>
|
<system:String x:Key="flowlauncher_plugin_everything_enable_content_search">Do you want to enable content search for Everything?</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_everything_enable_content_search_tips">It can be very slow without index (which is only supported in Everything v1.5+)</system:String>
|
<system:String x:Key="flowlauncher_plugin_everything_enable_content_search_tips">It can be very slow without index (which is only supported in Everything v1.5+)</system:String>
|
||||||
|
|
||||||
|
<!-- Native Context Menu -->
|
||||||
|
<system:String x:Key="plugin_explorer_native_context_menu_header">Native Context Menu</system:String>
|
||||||
|
<system:String x:Key="plugin_explorer_native_context_menu_display_context_menu">Display native context menu (experimental)</system:String>
|
||||||
|
<system:String x:Key="plugin_explorer_native_context_menu_include_patterns_guide">Below you can specify items you want to include in the context menu, they can be partial (e.g. 'pen wit') or complete ('Open with').</system:String>
|
||||||
|
<system:String x:Key="plugin_explorer_native_context_menu_exclude_patterns_guide">Below you can specify items you want to exclude from context menu, they can be partial (e.g. 'pen wit') or complete ('Open with')</system:String>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,11 @@ namespace Flow.Launcher.Plugin.Explorer
|
||||||
|
|
||||||
public bool UseLocationAsWorkingDir { get; set; } = false;
|
public bool UseLocationAsWorkingDir { get; set; } = false;
|
||||||
|
|
||||||
public bool ShowWindowsContextMenu { get; set; } = true;
|
public bool ShowInlinedWindowsContextMenu { get; set; } = false;
|
||||||
|
|
||||||
|
public string WindowsContextMenuIncludedItems { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public string WindowsContextMenuExcludedItems { get; set; } = string.Empty;
|
||||||
|
|
||||||
public bool DefaultOpenFolderInFileManager { get; set; } = false;
|
public bool DefaultOpenFolderInFileManager { get; set; } = false;
|
||||||
|
|
||||||
|
|
@ -62,7 +66,7 @@ namespace Flow.Launcher.Plugin.Explorer
|
||||||
public bool ShowModifiedDateInPreviewPanel { get; set; } = true;
|
public bool ShowModifiedDateInPreviewPanel { get; set; } = true;
|
||||||
|
|
||||||
public string PreviewPanelDateFormat { get; set; } = "yyyy-MM-dd";
|
public string PreviewPanelDateFormat { get; set; } = "yyyy-MM-dd";
|
||||||
|
|
||||||
public string PreviewPanelTimeFormat { get; set; } = "HH:mm";
|
public string PreviewPanelTimeFormat { get; set; } = "HH:mm";
|
||||||
|
|
||||||
private EverythingSearchManager _everythingManagerInstance;
|
private EverythingSearchManager _everythingManagerInstance;
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,40 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Native Context Menu
|
||||||
|
|
||||||
|
public bool ShowWindowsContextMenu
|
||||||
|
{
|
||||||
|
get => Settings.ShowInlinedWindowsContextMenu;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Settings.ShowInlinedWindowsContextMenu = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string WindowsContextMenuIncludedItems
|
||||||
|
{
|
||||||
|
get => Settings.WindowsContextMenuIncludedItems;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Settings.WindowsContextMenuIncludedItems = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string WindowsContextMenuExcludedItems
|
||||||
|
{
|
||||||
|
get => Settings.WindowsContextMenuExcludedItems;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Settings.WindowsContextMenuExcludedItems = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Preview Panel
|
#region Preview Panel
|
||||||
|
|
||||||
public bool ShowFileSizeInPreviewPanel
|
public bool ShowFileSizeInPreviewPanel
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
<Border
|
<Border
|
||||||
x:Name="LayoutRoot"
|
x:Name="LayoutRoot"
|
||||||
Margin="0,0,0,0"
|
Margin="0 0 0 0"
|
||||||
Padding="{TemplateBinding Padding}"
|
Padding="{TemplateBinding Padding}"
|
||||||
SnapsToDevicePixels="True">
|
SnapsToDevicePixels="True">
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|
@ -105,13 +105,13 @@
|
||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
<DataTemplate x:Key="ListViewTemplateAccessLinks" DataType="qa:AccessLink">
|
<DataTemplate x:Key="ListViewTemplateAccessLinks" DataType="qa:AccessLink">
|
||||||
<TextBlock Margin="0,5,0,5" Text="{Binding Path, Mode=OneTime}" />
|
<TextBlock Margin="0 5 0 5" Text="{Binding Path, Mode=OneTime}" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
<core:TranslationConverter x:Key="TranslationConverter" />
|
<core:TranslationConverter x:Key="TranslationConverter" />
|
||||||
<DataTemplate x:Key="ListViewActionKeywords" DataType="{x:Type views:ActionKeywordModel}">
|
<DataTemplate x:Key="ListViewActionKeywords" DataType="{x:Type views:ActionKeywordModel}">
|
||||||
<Grid>
|
<Grid>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="0,5,0,0"
|
Margin="0 5 0 0"
|
||||||
IsEnabled="{Binding Enabled}"
|
IsEnabled="{Binding Enabled}"
|
||||||
Text="{Binding Description, Mode=OneTime, Converter={StaticResource TranslationConverter}}">
|
Text="{Binding Description, Mode=OneTime, Converter={StaticResource TranslationConverter}}">
|
||||||
<TextBlock.Style>
|
<TextBlock.Style>
|
||||||
|
|
@ -128,7 +128,7 @@
|
||||||
</TextBlock.Style>
|
</TextBlock.Style>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="250,5,0,0"
|
Margin="250 5 0 0"
|
||||||
IsEnabled="{Binding Enabled}"
|
IsEnabled="{Binding Enabled}"
|
||||||
Text="{Binding Keyword}">
|
Text="{Binding Keyword}">
|
||||||
<TextBlock.Style>
|
<TextBlock.Style>
|
||||||
|
|
@ -160,20 +160,20 @@
|
||||||
Width="Auto"
|
Width="Auto"
|
||||||
Header="{DynamicResource plugin_explorer_generalsetting_header}"
|
Header="{DynamicResource plugin_explorer_generalsetting_header}"
|
||||||
Style="{DynamicResource ExplorerTabItem}">
|
Style="{DynamicResource ExplorerTabItem}">
|
||||||
<StackPanel Grid.Row="0" Margin="30,10,0,0">
|
<StackPanel Grid.Row="0" Margin="30 10 0 0">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<CheckBox
|
<CheckBox
|
||||||
Margin="0,10,0,0"
|
Margin="0 10 0 0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Content="{DynamicResource plugin_explorer_use_location_as_working_dir}"
|
Content="{DynamicResource plugin_explorer_use_location_as_working_dir}"
|
||||||
IsChecked="{Binding Settings.UseLocationAsWorkingDir}" />
|
IsChecked="{Binding Settings.UseLocationAsWorkingDir}" />
|
||||||
<CheckBox
|
<CheckBox
|
||||||
Margin="0,10,0,0"
|
Margin="0 10 0 0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Content="{DynamicResource plugin_explorer_default_open_in_file_manager}"
|
Content="{DynamicResource plugin_explorer_default_open_in_file_manager}"
|
||||||
IsChecked="{Binding Settings.DefaultOpenFolderInFileManager}" />
|
IsChecked="{Binding Settings.DefaultOpenFolderInFileManager}" />
|
||||||
<StackPanel Margin="0,10,0,10" Orientation="Horizontal">
|
<StackPanel Margin="0 10 0 10" Orientation="Horizontal">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="A" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="A" />
|
||||||
|
|
@ -188,7 +188,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="0,6,16,6"
|
Margin="0 6 16 6"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{DynamicResource plugin_explorer_file_editor_path}"
|
Text="{DynamicResource plugin_explorer_file_editor_path}"
|
||||||
|
|
@ -196,7 +196,7 @@
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="0,6,6,6"
|
Margin="0 6 6 6"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<TextBox
|
<TextBox
|
||||||
Width="250"
|
Width="250"
|
||||||
|
|
@ -206,7 +206,7 @@
|
||||||
TextWrapping="NoWrap" />
|
TextWrapping="NoWrap" />
|
||||||
<Button
|
<Button
|
||||||
MinWidth="50"
|
MinWidth="50"
|
||||||
Margin="5,0,0,0"
|
Margin="5 0 0 0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Command="{Binding OpenFileEditorPath}"
|
Command="{Binding OpenFileEditorPath}"
|
||||||
|
|
@ -216,7 +216,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="0,6,16,6"
|
Margin="0 6 16 6"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{DynamicResource plugin_explorer_folder_editor_path}"
|
Text="{DynamicResource plugin_explorer_folder_editor_path}"
|
||||||
|
|
@ -224,7 +224,7 @@
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="0,6,6,6"
|
Margin="0 6 6 6"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<TextBox
|
<TextBox
|
||||||
Width="250"
|
Width="250"
|
||||||
|
|
@ -234,7 +234,7 @@
|
||||||
TextWrapping="NoWrap" />
|
TextWrapping="NoWrap" />
|
||||||
<Button
|
<Button
|
||||||
MinWidth="50"
|
MinWidth="50"
|
||||||
Margin="5,0,0,0"
|
Margin="5 0 0 0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Command="{Binding OpenFolderEditorPath}"
|
Command="{Binding OpenFolderEditorPath}"
|
||||||
|
|
@ -244,7 +244,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="0,16,6,6"
|
Margin="0 16 6 6"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{DynamicResource plugin_explorer_shell_path}"
|
Text="{DynamicResource plugin_explorer_shell_path}"
|
||||||
|
|
@ -255,14 +255,14 @@
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<TextBox
|
<TextBox
|
||||||
Width="250"
|
Width="250"
|
||||||
Margin="0,10,0,0"
|
Margin="0 10 0 0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{Binding ShellPath}"
|
Text="{Binding ShellPath}"
|
||||||
TextWrapping="NoWrap" />
|
TextWrapping="NoWrap" />
|
||||||
<Button
|
<Button
|
||||||
MinWidth="50"
|
MinWidth="50"
|
||||||
Margin="5,10,0,0"
|
Margin="5 10 0 0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Command="{Binding OpenShellPath}"
|
Command="{Binding OpenShellPath}"
|
||||||
|
|
@ -271,7 +271,7 @@
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel Margin="0,0,0,5" Orientation="Horizontal">
|
<StackPanel Margin="0 0 0 5" Orientation="Horizontal">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="C" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="C" />
|
||||||
|
|
@ -285,7 +285,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="0,0,10,0"
|
Margin="0 0 10 0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{DynamicResource plugin_explorer_Index_Search_Engine}"
|
Text="{DynamicResource plugin_explorer_Index_Search_Engine}"
|
||||||
TextBlock.Foreground="{DynamicResource Color05B}" />
|
TextBlock.Foreground="{DynamicResource Color05B}" />
|
||||||
|
|
@ -293,7 +293,7 @@
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Width="250"
|
Width="250"
|
||||||
Margin="10,15,10,10"
|
Margin="10 15 10 10"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
DisplayMemberPath="Description"
|
DisplayMemberPath="Description"
|
||||||
|
|
@ -302,7 +302,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="0,0,10,0"
|
Margin="0 0 10 0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{DynamicResource plugin_explorer_Content_Search_Engine}"
|
Text="{DynamicResource plugin_explorer_Content_Search_Engine}"
|
||||||
TextBlock.Foreground="{DynamicResource Color05B}" />
|
TextBlock.Foreground="{DynamicResource Color05B}" />
|
||||||
|
|
@ -319,7 +319,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="0,0,10,0"
|
Margin="0 0 10 0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{DynamicResource plugin_explorer_Directory_Recursive_Search_Engine}"
|
Text="{DynamicResource plugin_explorer_Directory_Recursive_Search_Engine}"
|
||||||
TextBlock.Foreground="{DynamicResource Color05B}" />
|
TextBlock.Foreground="{DynamicResource Color05B}" />
|
||||||
|
|
@ -337,8 +337,8 @@
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<Button
|
<Button
|
||||||
Margin="0,10,10,20"
|
Margin="0 10 10 20"
|
||||||
Padding="20,10,20,10"
|
Padding="20 10 20 10"
|
||||||
Click="btnOpenIndexingOptions_Click"
|
Click="btnOpenIndexingOptions_Click"
|
||||||
Content="{DynamicResource plugin_explorer_Open_Window_Index_Option}" />
|
Content="{DynamicResource plugin_explorer_Open_Window_Index_Option}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
@ -348,50 +348,106 @@
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
<TabItem
|
||||||
|
Width="Auto"
|
||||||
|
Header="{DynamicResource plugin_explorer_native_context_menu_header}"
|
||||||
|
Style="{DynamicResource ExplorerTabItem}">
|
||||||
|
<StackPanel Margin="30 20 10 10">
|
||||||
|
<CheckBox
|
||||||
|
Margin="0 0 0 0"
|
||||||
|
Content="{DynamicResource plugin_explorer_native_context_menu_display_context_menu}"
|
||||||
|
IsChecked="{Binding ShowWindowsContextMenu}" />
|
||||||
|
|
||||||
|
<Grid Margin="0 10 20 10">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="0 0 6 6"
|
||||||
|
Foreground="{DynamicResource Color05B}"
|
||||||
|
Text="{DynamicResource plugin_explorer_native_context_menu_include_patterns_guide}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
|
||||||
|
<TextBox
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="0"
|
||||||
|
Height="300"
|
||||||
|
Margin="0 6 6 0"
|
||||||
|
AcceptsReturn="True"
|
||||||
|
Text="{Binding WindowsContextMenuIncludedItems}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="6 0 0 6"
|
||||||
|
Foreground="{DynamicResource Color05B}"
|
||||||
|
Text="{DynamicResource plugin_explorer_native_context_menu_exclude_patterns_guide}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
|
||||||
|
<TextBox
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="1"
|
||||||
|
Height="300"
|
||||||
|
Margin="6 6 0 0"
|
||||||
|
AcceptsReturn="True"
|
||||||
|
Text="{Binding WindowsContextMenuExcludedItems}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</TabItem>
|
||||||
<TabItem
|
<TabItem
|
||||||
Width="Auto"
|
Width="Auto"
|
||||||
Header="{DynamicResource plugin_explorer_previewpanel_setting_header}"
|
Header="{DynamicResource plugin_explorer_previewpanel_setting_header}"
|
||||||
Style="{DynamicResource ExplorerTabItem}">
|
Style="{DynamicResource ExplorerTabItem}">
|
||||||
<StackPanel Margin="30,20,0,10">
|
<StackPanel Margin="30 20 0 10">
|
||||||
<TextBlock Foreground="{DynamicResource Color05B}" Text="{DynamicResource plugin_explorer_previewpanel_file_info_label}" />
|
<TextBlock Foreground="{DynamicResource Color05B}" Text="{DynamicResource plugin_explorer_previewpanel_file_info_label}" />
|
||||||
<CheckBox
|
<CheckBox
|
||||||
Margin="0,10,0,0"
|
Margin="0 10 0 0"
|
||||||
Content="{DynamicResource plugin_explorer_previewpanel_display_file_size_checkbox}"
|
Content="{DynamicResource plugin_explorer_previewpanel_display_file_size_checkbox}"
|
||||||
IsChecked="{Binding ShowFileSizeInPreviewPanel}" />
|
IsChecked="{Binding ShowFileSizeInPreviewPanel}" />
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
Margin="0,10,0,0"
|
Margin="0 10 0 0"
|
||||||
Content="{DynamicResource plugin_explorer_previewpanel_display_file_creation_checkbox}"
|
Content="{DynamicResource plugin_explorer_previewpanel_display_file_creation_checkbox}"
|
||||||
IsChecked="{Binding ShowCreatedDateInPreviewPanel}" />
|
IsChecked="{Binding ShowCreatedDateInPreviewPanel}" />
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
Margin="0,10,0,0"
|
Margin="0 10 0 0"
|
||||||
Content="{DynamicResource plugin_explorer_previewpanel_display_file_modification_checkbox}"
|
Content="{DynamicResource plugin_explorer_previewpanel_display_file_modification_checkbox}"
|
||||||
IsChecked="{Binding ShowModifiedDateInPreviewPanel}" />
|
IsChecked="{Binding ShowModifiedDateInPreviewPanel}" />
|
||||||
|
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Margin="0,20,0,0"
|
Margin="0 20 0 0"
|
||||||
IsEnabled="{Binding ShowPreviewPanelDateTimeChoices}"
|
IsEnabled="{Binding ShowPreviewPanelDateTimeChoices}"
|
||||||
Visibility="{Binding PreviewPanelDateTimeChoicesVisibility}">
|
Visibility="{Binding PreviewPanelDateTimeChoicesVisibility}">
|
||||||
<TextBlock Foreground="{DynamicResource Color05B}" Text="{DynamicResource plugin_explorer_previewpanel_date_and_time_format_label}" />
|
<TextBlock Foreground="{DynamicResource Color05B}" Text="{DynamicResource plugin_explorer_previewpanel_date_and_time_format_label}" />
|
||||||
<StackPanel Margin="0,10,0,0" Orientation="Horizontal">
|
<StackPanel Margin="0 10 0 0" Orientation="Horizontal">
|
||||||
<ComboBox
|
<ComboBox
|
||||||
Width="200"
|
Width="200"
|
||||||
ItemsSource="{Binding DateFormatList}"
|
ItemsSource="{Binding DateFormatList}"
|
||||||
SelectedItem="{Binding PreviewPanelDateFormat}" />
|
SelectedItem="{Binding PreviewPanelDateFormat}" />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="12,0,0,0"
|
Margin="12 0 0 0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Foreground="{DynamicResource Color05B}"
|
Foreground="{DynamicResource Color05B}"
|
||||||
Text="{Binding PreviewPanelDateFormatDemo}" />
|
Text="{Binding PreviewPanelDateFormatDemo}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Margin="0,10,0,10" Orientation="Horizontal">
|
<StackPanel Margin="0 10 0 10" Orientation="Horizontal">
|
||||||
<ComboBox
|
<ComboBox
|
||||||
Width="200"
|
Width="200"
|
||||||
ItemsSource="{Binding TimeFormatList}"
|
ItemsSource="{Binding TimeFormatList}"
|
||||||
SelectedItem="{Binding PreviewPanelTimeFormat}" />
|
SelectedItem="{Binding PreviewPanelTimeFormat}" />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="12,0,0,0"
|
Margin="12 0 0 0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Foreground="{DynamicResource Color05B}"
|
Foreground="{DynamicResource Color05B}"
|
||||||
Text="{Binding PreviewPanelTimeFormatDemo}" />
|
Text="{Binding PreviewPanelTimeFormatDemo}" />
|
||||||
|
|
@ -405,12 +461,12 @@
|
||||||
Style="{DynamicResource ExplorerTabItem}">
|
Style="{DynamicResource ExplorerTabItem}">
|
||||||
<StackPanel Margin="10" Orientation="Vertical">
|
<StackPanel Margin="10" Orientation="Vertical">
|
||||||
<CheckBox
|
<CheckBox
|
||||||
Margin="20,10,0,0"
|
Margin="20 10 0 0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Content="{DynamicResource flowlauncher_plugin_everything_search_fullpath}"
|
Content="{DynamicResource flowlauncher_plugin_everything_search_fullpath}"
|
||||||
IsChecked="{Binding Settings.EverythingSearchFullPath}" />
|
IsChecked="{Binding Settings.EverythingSearchFullPath}" />
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<Grid Margin="20,10,0,10">
|
<Grid Margin="20 10 0 10">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="F" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="F" />
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
|
|
@ -423,7 +479,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="0,0,20,0"
|
Margin="0 0 20 0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{DynamicResource plugin_explorer_everything_sort_option}"
|
Text="{DynamicResource plugin_explorer_everything_sort_option}"
|
||||||
TextBlock.Foreground="{DynamicResource Color05B}" />
|
TextBlock.Foreground="{DynamicResource Color05B}" />
|
||||||
|
|
@ -447,7 +503,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="0,15,20,0"
|
Margin="0 15 20 0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{DynamicResource plugin_explorer_everything_installed_path}"
|
Text="{DynamicResource plugin_explorer_everything_installed_path}"
|
||||||
TextBlock.Foreground="{DynamicResource Color05B}" />
|
TextBlock.Foreground="{DynamicResource Color05B}" />
|
||||||
|
|
@ -455,14 +511,14 @@
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
MinWidth="350"
|
MinWidth="350"
|
||||||
Margin="0,15,0,0"
|
Margin="0 15 0 0"
|
||||||
Text="{Binding EverythingInstalledPath}" />
|
Text="{Binding EverythingInstalledPath}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Name="tbFastSortWarning"
|
Name="tbFastSortWarning"
|
||||||
Margin="20,10,10,10"
|
Margin="20 10 10 10"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
Foreground="Orange"
|
Foreground="Orange"
|
||||||
|
|
@ -479,7 +535,7 @@
|
||||||
Style="{DynamicResource ExplorerTabItem}">
|
Style="{DynamicResource ExplorerTabItem}">
|
||||||
<DockPanel HorizontalAlignment="Stretch">
|
<DockPanel HorizontalAlignment="Stretch">
|
||||||
<Border
|
<Border
|
||||||
Margin="10,10,10,5"
|
Margin="10 10 10 5"
|
||||||
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
|
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
DockPanel.Dock="Top">
|
DockPanel.Dock="Top">
|
||||||
|
|
@ -508,7 +564,7 @@
|
||||||
<ScrollViewer>
|
<ScrollViewer>
|
||||||
<DockPanel HorizontalAlignment="Stretch">
|
<DockPanel HorizontalAlignment="Stretch">
|
||||||
<Border
|
<Border
|
||||||
Margin="10,10,10,5"
|
Margin="10 10 10 5"
|
||||||
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
|
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
DockPanel.Dock="Top">
|
DockPanel.Dock="Top">
|
||||||
|
|
@ -556,7 +612,7 @@
|
||||||
<ScrollViewer>
|
<ScrollViewer>
|
||||||
<DockPanel HorizontalAlignment="Stretch">
|
<DockPanel HorizontalAlignment="Stretch">
|
||||||
<Border
|
<Border
|
||||||
Margin="10,10,10,5"
|
Margin="10 10 10 5"
|
||||||
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
|
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
DockPanel.Dock="Top">
|
DockPanel.Dock="Top">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue