mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Improve code quality
This commit is contained in:
parent
1ca17aa2db
commit
2cd1683741
12 changed files with 434 additions and 378 deletions
123
Flow.Launcher.Infrastructure/MonitorInfo.cs
Normal file
123
Flow.Launcher.Infrastructure/MonitorInfo.cs
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.Graphics.Gdi;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
|
||||
namespace Flow.Launcher.Infrastructure;
|
||||
|
||||
/// <summary>
|
||||
/// Contains full information about a display monitor.
|
||||
/// Codes are edited from: <see href="https://github.com/Jack251970/DesktopWidgets3">.
|
||||
/// </summary>
|
||||
internal class MonitorInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the display monitors (including invisible pseudo-monitors associated with the mirroring drivers).
|
||||
/// </summary>
|
||||
/// <returns>A list of display monitors</returns>
|
||||
public static unsafe IList<MonitorInfo> GetDisplayMonitors()
|
||||
{
|
||||
var monitorCount = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CMONITORS);
|
||||
var list = new List<MonitorInfo>(monitorCount);
|
||||
var callback = new MONITORENUMPROC((HMONITOR monitor, HDC deviceContext, RECT* rect, LPARAM data) =>
|
||||
{
|
||||
list.Add(new MonitorInfo(monitor, rect));
|
||||
return true;
|
||||
});
|
||||
var dwData = new LPARAM();
|
||||
var hdc = new HDC();
|
||||
bool ok = PInvoke.EnumDisplayMonitors(hdc, (RECT?)null, callback, dwData);
|
||||
if (!ok)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the display monitor that is nearest to a given window.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">Window handle</param>
|
||||
/// <returns>The display monitor that is nearest to a given window, or null if no monitor is found.</returns>
|
||||
public static unsafe MonitorInfo GetNearestDisplayMonitor(HWND hwnd)
|
||||
{
|
||||
var nearestMonitor = PInvoke.MonitorFromWindow(hwnd, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST);
|
||||
MonitorInfo nearestMonitorInfo = null;
|
||||
var callback = new MONITORENUMPROC((HMONITOR monitor, HDC deviceContext, RECT* rect, LPARAM data) =>
|
||||
{
|
||||
if (monitor == nearestMonitor)
|
||||
{
|
||||
nearestMonitorInfo = new MonitorInfo(monitor, rect);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
var dwData = new LPARAM();
|
||||
var hdc = new HDC();
|
||||
bool ok = PInvoke.EnumDisplayMonitors(hdc, (RECT?)null, callback, dwData);
|
||||
if (!ok)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
|
||||
}
|
||||
return nearestMonitorInfo;
|
||||
}
|
||||
|
||||
private readonly HMONITOR _monitor;
|
||||
|
||||
internal unsafe MonitorInfo(HMONITOR monitor, RECT* rect)
|
||||
{
|
||||
RectMonitor =
|
||||
new Rect(new Point(rect->left, rect->top),
|
||||
new Point(rect->right, rect->bottom));
|
||||
_monitor = monitor;
|
||||
var info = new MONITORINFOEXW() { monitorInfo = new MONITORINFO() { cbSize = (uint)sizeof(MONITORINFOEXW) } };
|
||||
GetMonitorInfo(monitor, ref info);
|
||||
RectWork =
|
||||
new Rect(new Point(info.monitorInfo.rcWork.left, info.monitorInfo.rcWork.top),
|
||||
new Point(info.monitorInfo.rcWork.right, info.monitorInfo.rcWork.bottom));
|
||||
Name = new string(info.szDevice.AsSpan()).Replace("\0", "").Trim();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the display.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the display monitor rectangle, expressed in virtual-screen coordinates.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <note>If the monitor is not the primary display monitor, some of the rectangle's coordinates may be negative values.</note>
|
||||
/// </remarks>
|
||||
public Rect RectMonitor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the work area rectangle of the display monitor, expressed in virtual-screen coordinates.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <note>If the monitor is not the primary display monitor, some of the rectangle's coordinates may be negative values.</note>
|
||||
/// </remarks>
|
||||
public Rect RectWork { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets if the monitor is the the primary display monitor.
|
||||
/// </summary>
|
||||
public bool IsPrimary => _monitor == PInvoke.MonitorFromWindow(new(IntPtr.Zero), MONITOR_FROM_FLAGS.MONITOR_DEFAULTTOPRIMARY);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString() => $"{Name} {RectMonitor.Width}x{RectMonitor.Height}";
|
||||
|
||||
private static unsafe bool GetMonitorInfo(HMONITOR hMonitor, ref MONITORINFOEXW lpmi)
|
||||
{
|
||||
fixed (MONITORINFOEXW* lpmiLocal = &lpmi)
|
||||
{
|
||||
var lpmiBase = (MONITORINFO*)lpmiLocal;
|
||||
var __result = PInvoke.GetMonitorInfo(hMonitor, lpmiBase);
|
||||
return __result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,4 +20,31 @@ EnumWindows
|
|||
|
||||
DwmSetWindowAttribute
|
||||
DWM_SYSTEMBACKDROP_TYPE
|
||||
DWM_WINDOW_CORNER_PREFERENCE
|
||||
DWM_WINDOW_CORNER_PREFERENCE
|
||||
|
||||
MAX_PATH
|
||||
SystemParametersInfo
|
||||
|
||||
SetForegroundWindow
|
||||
|
||||
GetWindowLong
|
||||
SetWindowLong
|
||||
GetForegroundWindow
|
||||
GetDesktopWindow
|
||||
GetShellWindow
|
||||
GetWindowRect
|
||||
GetClassName
|
||||
FindWindowEx
|
||||
WINDOW_STYLE
|
||||
|
||||
SetLastError
|
||||
WINDOW_EX_STYLE
|
||||
|
||||
GetSystemMetrics
|
||||
EnumDisplayMonitors
|
||||
MonitorFromWindow
|
||||
GetMonitorInfo
|
||||
MONITORINFOEXW
|
||||
|
||||
WM_ENTERSIZEMOVE
|
||||
WM_EXITSIZEMOVE
|
||||
|
|
@ -1,9 +1,13 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.Graphics.Dwm;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
|
||||
namespace Flow.Launcher.Infrastructure
|
||||
|
|
@ -14,20 +18,17 @@ namespace Flow.Launcher.Infrastructure
|
|||
|
||||
public static bool IsBackdropSupported()
|
||||
{
|
||||
// Windows 11 (22000) 이상에서만 Mica 및 Acrylic 효과 지원
|
||||
// Mica and Acrylic only supported Windows 11 22000+
|
||||
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
|
||||
Environment.OSVersion.Version.Build >= 22000;
|
||||
}
|
||||
|
||||
public static unsafe bool DWMSetCloakForWindow(Window window, bool cloak)
|
||||
{
|
||||
var windowHelper = new WindowInteropHelper(window);
|
||||
windowHelper.EnsureHandle();
|
||||
|
||||
var cloaked = cloak ? 1 : 0;
|
||||
|
||||
return PInvoke.DwmSetWindowAttribute(
|
||||
new(windowHelper.Handle),
|
||||
GetWindowHandle(window),
|
||||
DWMWINDOWATTRIBUTE.DWMWA_CLOAK,
|
||||
&cloaked,
|
||||
(uint)Marshal.SizeOf<int>()).Succeeded;
|
||||
|
|
@ -35,9 +36,6 @@ namespace Flow.Launcher.Infrastructure
|
|||
|
||||
public static unsafe bool DWMSetBackdropForWindow(Window window, BackdropTypes backdrop)
|
||||
{
|
||||
var windowHelper = new WindowInteropHelper(window);
|
||||
windowHelper.EnsureHandle();
|
||||
|
||||
var backdropType = backdrop switch
|
||||
{
|
||||
BackdropTypes.Acrylic => DWM_SYSTEMBACKDROP_TYPE.DWMSBT_TRANSIENTWINDOW,
|
||||
|
|
@ -47,7 +45,7 @@ namespace Flow.Launcher.Infrastructure
|
|||
};
|
||||
|
||||
return PInvoke.DwmSetWindowAttribute(
|
||||
new(windowHelper.Handle),
|
||||
GetWindowHandle(window),
|
||||
DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE,
|
||||
&backdropType,
|
||||
(uint)Marshal.SizeOf<int>()).Succeeded;
|
||||
|
|
@ -55,13 +53,10 @@ namespace Flow.Launcher.Infrastructure
|
|||
|
||||
public static unsafe bool DWMSetDarkModeForWindow(Window window, bool useDarkMode)
|
||||
{
|
||||
var windowHelper = new WindowInteropHelper(window);
|
||||
windowHelper.EnsureHandle();
|
||||
|
||||
var darkMode = useDarkMode ? 1 : 0;
|
||||
|
||||
return PInvoke.DwmSetWindowAttribute(
|
||||
new(windowHelper.Handle),
|
||||
GetWindowHandle(window),
|
||||
DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE,
|
||||
&darkMode,
|
||||
(uint)Marshal.SizeOf<int>()).Succeeded;
|
||||
|
|
@ -75,9 +70,6 @@ namespace Flow.Launcher.Infrastructure
|
|||
/// <returns></returns>
|
||||
public static unsafe bool DWMSetCornerPreferenceForWindow(Window window, string cornerType)
|
||||
{
|
||||
var windowHelper = new WindowInteropHelper(window);
|
||||
windowHelper.EnsureHandle();
|
||||
|
||||
var preference = cornerType switch
|
||||
{
|
||||
"DoNotRound" => DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_DONOTROUND,
|
||||
|
|
@ -88,12 +80,246 @@ namespace Flow.Launcher.Infrastructure
|
|||
};
|
||||
|
||||
return PInvoke.DwmSetWindowAttribute(
|
||||
new(windowHelper.Handle),
|
||||
GetWindowHandle(window),
|
||||
DWMWINDOWATTRIBUTE.DWMWA_WINDOW_CORNER_PREFERENCE,
|
||||
&preference,
|
||||
(uint)Marshal.SizeOf<int>()).Succeeded;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Wallpaper
|
||||
|
||||
public static unsafe string GetWallpaperPath()
|
||||
{
|
||||
var wallpaperPtr = stackalloc char[(int)PInvoke.MAX_PATH];
|
||||
PInvoke.SystemParametersInfo(SYSTEM_PARAMETERS_INFO_ACTION.SPI_GETDESKWALLPAPER, PInvoke.MAX_PATH,
|
||||
wallpaperPtr,
|
||||
0);
|
||||
var wallpaper = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(wallpaperPtr);
|
||||
|
||||
return wallpaper.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Window Foreground
|
||||
|
||||
public static nint GetForegroundWindow()
|
||||
{
|
||||
return PInvoke.GetForegroundWindow().Value;
|
||||
}
|
||||
|
||||
public static bool SetForegroundWindow(Window window)
|
||||
{
|
||||
return PInvoke.SetForegroundWindow(GetWindowHandle(window));
|
||||
}
|
||||
|
||||
public static bool SetForegroundWindow(nint handle)
|
||||
{
|
||||
return PInvoke.SetForegroundWindow(new(handle));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Task Switching
|
||||
|
||||
/// <summary>
|
||||
/// Hide windows in the Alt+Tab window list
|
||||
/// </summary>
|
||||
/// <param name="window">To hide a window</param>
|
||||
public static void HideFromAltTab(Window window)
|
||||
{
|
||||
var hwnd = GetWindowHandle(window);
|
||||
|
||||
var exStyle = GetCurrentWindowStyle(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE);
|
||||
|
||||
// Add TOOLWINDOW style, remove APPWINDOW style
|
||||
var newExStyle = ((uint)exStyle | (uint)WINDOW_EX_STYLE.WS_EX_TOOLWINDOW) & ~(uint)WINDOW_EX_STYLE.WS_EX_APPWINDOW;
|
||||
|
||||
SetWindowLong(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, (int)newExStyle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restore window display in the Alt+Tab window list.
|
||||
/// </summary>
|
||||
/// <param name="window">To restore the displayed window</param>
|
||||
public static void ShowInAltTab(Window window)
|
||||
{
|
||||
var hwnd = GetWindowHandle(window);
|
||||
|
||||
var exStyle = GetCurrentWindowStyle(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE);
|
||||
|
||||
// Remove the TOOLWINDOW style and add the APPWINDOW style.
|
||||
var newExStyle = ((uint)exStyle & ~(uint)WINDOW_EX_STYLE.WS_EX_TOOLWINDOW) | (uint)WINDOW_EX_STYLE.WS_EX_APPWINDOW;
|
||||
|
||||
SetWindowLong(GetWindowHandle(window), WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, (int)newExStyle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disable windows toolbar's control box
|
||||
/// This will also disable system menu with Alt+Space hotkey
|
||||
/// </summary>
|
||||
public static void DisableControlBox(Window window)
|
||||
{
|
||||
var hwnd = GetWindowHandle(window);
|
||||
|
||||
var style = GetCurrentWindowStyle(hwnd, WINDOW_LONG_PTR_INDEX.GWL_STYLE);
|
||||
|
||||
style &= ~(int)WINDOW_STYLE.WS_SYSMENU;
|
||||
|
||||
SetWindowLong(hwnd, WINDOW_LONG_PTR_INDEX.GWL_STYLE, style);
|
||||
}
|
||||
|
||||
private static int GetCurrentWindowStyle(HWND hWnd, WINDOW_LONG_PTR_INDEX nIndex)
|
||||
{
|
||||
var style = PInvoke.GetWindowLong(hWnd, nIndex);
|
||||
if (style == 0 && Marshal.GetLastPInvokeError() != 0)
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastPInvokeError());
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
private static int SetWindowLong(HWND hWnd, WINDOW_LONG_PTR_INDEX nIndex, int dwNewLong)
|
||||
{
|
||||
PInvoke.SetLastError(WIN32_ERROR.NO_ERROR); // Clear any existing error
|
||||
|
||||
var result = PInvoke.SetWindowLong(hWnd, nIndex, dwNewLong);
|
||||
if (result == 0 && Marshal.GetLastPInvokeError() != 0)
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastPInvokeError());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Window Fullscreen
|
||||
|
||||
private const string WINDOW_CLASS_CONSOLE = "ConsoleWindowClass";
|
||||
private const string WINDOW_CLASS_WINTAB = "Flip3D";
|
||||
private const string WINDOW_CLASS_PROGMAN = "Progman";
|
||||
private const string WINDOW_CLASS_WORKERW = "WorkerW";
|
||||
|
||||
private static HWND _hwnd_shell;
|
||||
private static HWND HWND_SHELL =>
|
||||
_hwnd_shell != HWND.Null ? _hwnd_shell : _hwnd_shell = PInvoke.GetShellWindow();
|
||||
|
||||
private static HWND _hwnd_desktop;
|
||||
private static HWND HWND_DESKTOP =>
|
||||
_hwnd_desktop != HWND.Null ? _hwnd_desktop : _hwnd_desktop = PInvoke.GetDesktopWindow();
|
||||
|
||||
public static unsafe bool IsForegroundWindowFullscreen()
|
||||
{
|
||||
// Get current active window
|
||||
var hWnd = PInvoke.GetForegroundWindow();
|
||||
if (hWnd.Equals(HWND.Null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If current active window is desktop or shell, exit early
|
||||
if (hWnd.Equals(HWND_DESKTOP) || hWnd.Equals(HWND_SHELL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string windowClass;
|
||||
const int capacity = 256;
|
||||
Span<char> buffer = stackalloc char[capacity];
|
||||
int validLength;
|
||||
fixed (char* pBuffer = buffer)
|
||||
{
|
||||
validLength = PInvoke.GetClassName(hWnd, pBuffer, capacity);
|
||||
}
|
||||
|
||||
windowClass = buffer[..validLength].ToString();
|
||||
|
||||
// For Win+Tab (Flip3D)
|
||||
if (windowClass == WINDOW_CLASS_WINTAB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PInvoke.GetWindowRect(hWnd, out var appBounds);
|
||||
|
||||
// For console (ConsoleWindowClass), we have to check for negative dimensions
|
||||
if (windowClass == WINDOW_CLASS_CONSOLE)
|
||||
{
|
||||
return appBounds.top < 0 && appBounds.bottom < 0;
|
||||
}
|
||||
|
||||
// For desktop (Progman or WorkerW, depends on the system), we have to check
|
||||
if (windowClass is WINDOW_CLASS_PROGMAN or WINDOW_CLASS_WORKERW)
|
||||
{
|
||||
var hWndDesktop = PInvoke.FindWindowEx(hWnd, HWND.Null, "SHELLDLL_DefView", null);
|
||||
hWndDesktop = PInvoke.FindWindowEx(hWndDesktop, HWND.Null, "SysListView32", "FolderView");
|
||||
if (hWndDesktop.Value != IntPtr.Zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var monitorInfo = MonitorInfo.GetNearestDisplayMonitor(hWnd);
|
||||
return (appBounds.bottom - appBounds.top) == monitorInfo.RectMonitor.Height &&
|
||||
(appBounds.right - appBounds.left) == monitorInfo.RectMonitor.Width;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Pixel to DIP
|
||||
|
||||
/// <summary>
|
||||
/// Transforms pixels to Device Independent Pixels used by WPF
|
||||
/// </summary>
|
||||
/// <param name="visual">current window, required to get presentation source</param>
|
||||
/// <param name="unitX">horizontal position in pixels</param>
|
||||
/// <param name="unitY">vertical position in pixels</param>
|
||||
/// <returns>point containing device independent pixels</returns>
|
||||
public static Point TransformPixelsToDIP(Visual visual, double unitX, double unitY)
|
||||
{
|
||||
Matrix matrix;
|
||||
var source = PresentationSource.FromVisual(visual);
|
||||
if (source is not null)
|
||||
{
|
||||
matrix = source.CompositionTarget.TransformFromDevice;
|
||||
}
|
||||
else
|
||||
{
|
||||
using var src = new HwndSource(new HwndSourceParameters());
|
||||
matrix = src.CompositionTarget.TransformFromDevice;
|
||||
}
|
||||
|
||||
return new Point((int)(matrix.M11 * unitX), (int)(matrix.M22 * unitY));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region WndProc
|
||||
|
||||
public static bool WM_ENTERSIZEMOVE(int msg)
|
||||
{
|
||||
return msg == (int)PInvoke.WM_ENTERSIZEMOVE;
|
||||
}
|
||||
|
||||
public static bool WM_EXITSIZEMOVE(int msg)
|
||||
{
|
||||
return msg == (int)PInvoke.WM_EXITSIZEMOVE;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Window Handle
|
||||
|
||||
internal static HWND GetWindowHandle(Window window)
|
||||
{
|
||||
var windowHelper = new WindowInteropHelper(window);
|
||||
windowHelper.EnsureHandle();
|
||||
return new(windowHelper.Handle);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,10 +94,6 @@
|
|||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
|
||||
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.106">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<!-- ModernWpfUI v0.9.5 introduced WinRT changes that causes Notification platform unavailable error on some machines -->
|
||||
<!-- https://github.com/Flow-Launcher/Flow.Launcher/issues/1772#issuecomment-1502440801 -->
|
||||
<PackageReference Include="ModernWpfUI" Version="0.9.4" />
|
||||
|
|
|
|||
|
|
@ -1,66 +0,0 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.Graphics.Dwm;
|
||||
using Windows.Win32.UI.Controls;
|
||||
|
||||
namespace Flow.Launcher.Helper;
|
||||
|
||||
public class DwmDropShadow
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Drops a standard shadow to a WPF Window, even if the window isborderless. Only works with DWM (Vista and Seven).
|
||||
/// This method is much more efficient than setting AllowsTransparency to true and using the DropShadow effect,
|
||||
/// as AllowsTransparency involves a huge permormance issue (hardware acceleration is turned off for all the window).
|
||||
/// </summary>
|
||||
/// <param name="window">Window to which the shadow will be applied</param>
|
||||
public static void DropShadowToWindow(Window window)
|
||||
{
|
||||
if (!DropShadow(window))
|
||||
{
|
||||
window.SourceInitialized += window_SourceInitialized;
|
||||
}
|
||||
}
|
||||
|
||||
private static void window_SourceInitialized(object sender, EventArgs e) //fixed typo
|
||||
{
|
||||
Window window = (Window)sender;
|
||||
|
||||
DropShadow(window);
|
||||
|
||||
window.SourceInitialized -= window_SourceInitialized;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The actual method that makes API calls to drop the shadow to the window
|
||||
/// </summary>
|
||||
/// <param name="window">Window to which the shadow will be applied</param>
|
||||
/// <returns>True if the method succeeded, false if not</returns>
|
||||
private static unsafe bool DropShadow(Window window)
|
||||
{
|
||||
try
|
||||
{
|
||||
WindowInteropHelper helper = new WindowInteropHelper(window);
|
||||
int val = 2;
|
||||
var ret1 = PInvoke.DwmSetWindowAttribute(new (helper.Handle), DWMWINDOWATTRIBUTE.DWMWA_NCRENDERING_POLICY, &val, 4);
|
||||
|
||||
if (ret1 == HRESULT.S_OK)
|
||||
{
|
||||
var m = new MARGINS { cyBottomHeight = 0, cxLeftWidth = 0, cxRightWidth = 0, cyTopHeight = 0 };
|
||||
var ret2 = PInvoke.DwmExtendFrameIntoClientArea(new(helper.Handle), &m);
|
||||
return ret2 == HRESULT.S_OK;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Probably dwmapi.dll not found (incompatible OS)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,19 +2,16 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Flow.Launcher.Infrastructure;
|
||||
using Microsoft.Win32;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
|
||||
namespace Flow.Launcher.Helper;
|
||||
|
||||
public static class WallpaperPathRetrieval
|
||||
{
|
||||
private static readonly int MAX_PATH = 260;
|
||||
private static readonly int MAX_CACHE_SIZE = 3;
|
||||
|
||||
private static readonly Dictionary<(string, DateTime), ImageBrush> wallpaperCache = new();
|
||||
|
|
@ -29,7 +26,7 @@ public static class WallpaperPathRetrieval
|
|||
|
||||
try
|
||||
{
|
||||
var wallpaperPath = GetWallpaperPath();
|
||||
var wallpaperPath = Win32Helper.GetWallpaperPath();
|
||||
if (wallpaperPath is not null && File.Exists(wallpaperPath))
|
||||
{
|
||||
// Since the wallpaper file name can be the same (TranscodedWallpaper),
|
||||
|
|
@ -78,17 +75,6 @@ public static class WallpaperPathRetrieval
|
|||
}
|
||||
}
|
||||
|
||||
private static unsafe string GetWallpaperPath()
|
||||
{
|
||||
var wallpaperPtr = stackalloc char[MAX_PATH];
|
||||
PInvoke.SystemParametersInfo(SYSTEM_PARAMETERS_INFO_ACTION.SPI_GETDESKWALLPAPER, (uint)MAX_PATH,
|
||||
wallpaperPtr,
|
||||
0);
|
||||
var wallpaper = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(wallpaperPtr);
|
||||
|
||||
return wallpaper.ToString();
|
||||
}
|
||||
|
||||
private static Color GetWallpaperColor()
|
||||
{
|
||||
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Colors", true);
|
||||
|
|
|
|||
|
|
@ -1,211 +0,0 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
using Point = System.Windows.Point;
|
||||
|
||||
namespace Flow.Launcher.Helper;
|
||||
|
||||
public class WindowsInteropHelper
|
||||
{
|
||||
private static HWND _hwnd_shell;
|
||||
private static HWND _hwnd_desktop;
|
||||
|
||||
//Accessors for shell and desktop handlers
|
||||
//Will set the variables once and then will return them
|
||||
private static HWND HWND_SHELL
|
||||
{
|
||||
get
|
||||
{
|
||||
return _hwnd_shell != HWND.Null ? _hwnd_shell : _hwnd_shell = PInvoke.GetShellWindow();
|
||||
}
|
||||
}
|
||||
|
||||
private static HWND HWND_DESKTOP
|
||||
{
|
||||
get
|
||||
{
|
||||
return _hwnd_desktop != HWND.Null ? _hwnd_desktop : _hwnd_desktop = PInvoke.GetDesktopWindow();
|
||||
}
|
||||
}
|
||||
|
||||
const string WINDOW_CLASS_CONSOLE = "ConsoleWindowClass";
|
||||
const string WINDOW_CLASS_WINTAB = "Flip3D";
|
||||
const string WINDOW_CLASS_PROGMAN = "Progman";
|
||||
const string WINDOW_CLASS_WORKERW = "WorkerW";
|
||||
|
||||
public unsafe static bool IsWindowFullscreen()
|
||||
{
|
||||
//get current active window
|
||||
var hWnd = PInvoke.GetForegroundWindow();
|
||||
|
||||
if (hWnd.Equals(HWND.Null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//if current active window is desktop or shell, exit early
|
||||
if (hWnd.Equals(HWND_DESKTOP) || hWnd.Equals(HWND_SHELL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string windowClass;
|
||||
const int capacity = 256;
|
||||
Span<char> buffer = stackalloc char[capacity];
|
||||
int validLength;
|
||||
fixed (char* pBuffer = buffer)
|
||||
{
|
||||
validLength = PInvoke.GetClassName(hWnd, pBuffer, capacity);
|
||||
}
|
||||
|
||||
windowClass = buffer[..validLength].ToString();
|
||||
|
||||
|
||||
//for Win+Tab (Flip3D)
|
||||
if (windowClass == WINDOW_CLASS_WINTAB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PInvoke.GetWindowRect(hWnd, out var appBounds);
|
||||
|
||||
//for console (ConsoleWindowClass), we have to check for negative dimensions
|
||||
if (windowClass == WINDOW_CLASS_CONSOLE)
|
||||
{
|
||||
return appBounds.top < 0 && appBounds.bottom < 0;
|
||||
}
|
||||
|
||||
//for desktop (Progman or WorkerW, depends on the system), we have to check
|
||||
if (windowClass is WINDOW_CLASS_PROGMAN or WINDOW_CLASS_WORKERW)
|
||||
{
|
||||
var hWndDesktop = PInvoke.FindWindowEx(hWnd, HWND.Null, "SHELLDLL_DefView", null);
|
||||
hWndDesktop = PInvoke.FindWindowEx(hWndDesktop, HWND.Null, "SysListView32", "FolderView");
|
||||
if (hWndDesktop.Value != (IntPtr.Zero))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle screenBounds = Screen.FromHandle(hWnd).Bounds;
|
||||
return (appBounds.bottom - appBounds.top) == screenBounds.Height &&
|
||||
(appBounds.right - appBounds.left) == screenBounds.Width;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// disable windows toolbar's control box
|
||||
/// this will also disable system menu with Alt+Space hotkey
|
||||
/// </summary>
|
||||
public static void DisableControlBox(Window win)
|
||||
{
|
||||
var hwnd = new HWND(new WindowInteropHelper(win).Handle);
|
||||
|
||||
var style = PInvoke.GetWindowLong(hwnd, WINDOW_LONG_PTR_INDEX.GWL_STYLE);
|
||||
|
||||
if (style == 0)
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastPInvokeError());
|
||||
}
|
||||
|
||||
style &= ~(int)WINDOW_STYLE.WS_SYSMENU;
|
||||
|
||||
var previousStyle = PInvoke.SetWindowLong(hwnd, WINDOW_LONG_PTR_INDEX.GWL_STYLE,
|
||||
style);
|
||||
|
||||
if (previousStyle == 0)
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastPInvokeError());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms pixels to Device Independent Pixels used by WPF
|
||||
/// </summary>
|
||||
/// <param name="visual">current window, required to get presentation source</param>
|
||||
/// <param name="unitX">horizontal position in pixels</param>
|
||||
/// <param name="unitY">vertical position in pixels</param>
|
||||
/// <returns>point containing device independent pixels</returns>
|
||||
public static Point TransformPixelsToDIP(Visual visual, double unitX, double unitY)
|
||||
{
|
||||
Matrix matrix;
|
||||
var source = PresentationSource.FromVisual(visual);
|
||||
if (source is not null)
|
||||
{
|
||||
matrix = source.CompositionTarget.TransformFromDevice;
|
||||
}
|
||||
else
|
||||
{
|
||||
using var src = new HwndSource(new HwndSourceParameters());
|
||||
matrix = src.CompositionTarget.TransformFromDevice;
|
||||
}
|
||||
|
||||
return new Point((int)(matrix.M11 * unitX), (int)(matrix.M22 * unitY));
|
||||
}
|
||||
|
||||
#region Alt Tab
|
||||
|
||||
private static int SetWindowLong(HWND hWnd, WINDOW_LONG_PTR_INDEX nIndex, int dwNewLong)
|
||||
{
|
||||
PInvoke.SetLastError(WIN32_ERROR.NO_ERROR); // Clear any existing error
|
||||
|
||||
var result = PInvoke.SetWindowLong(hWnd, nIndex, dwNewLong);
|
||||
if (result == 0 && Marshal.GetLastPInvokeError() != 0)
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastPInvokeError());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hide windows in the Alt+Tab window list
|
||||
/// </summary>
|
||||
/// <param name="window">To hide a window</param>
|
||||
public static void HideFromAltTab(Window window)
|
||||
{
|
||||
var exStyle = GetCurrentWindowStyle(window);
|
||||
|
||||
// Add TOOLWINDOW style, remove APPWINDOW style
|
||||
var newExStyle = ((uint)exStyle | (uint)WINDOW_EX_STYLE.WS_EX_TOOLWINDOW) & ~(uint)WINDOW_EX_STYLE.WS_EX_APPWINDOW;
|
||||
|
||||
SetWindowLong(new(new WindowInteropHelper(window).Handle), WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, (int)newExStyle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restore window display in the Alt+Tab window list.
|
||||
/// </summary>
|
||||
/// <param name="window">To restore the displayed window</param>
|
||||
public static void ShowInAltTab(Window window)
|
||||
{
|
||||
var exStyle = GetCurrentWindowStyle(window);
|
||||
|
||||
// Remove the TOOLWINDOW style and add the APPWINDOW style.
|
||||
var newExStyle = ((uint)exStyle & ~(uint)WINDOW_EX_STYLE.WS_EX_TOOLWINDOW) | (uint)WINDOW_EX_STYLE.WS_EX_APPWINDOW;
|
||||
|
||||
SetWindowLong(new(new WindowInteropHelper(window).Handle), WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, (int)newExStyle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To obtain the current overridden style of a window.
|
||||
/// </summary>
|
||||
/// <param name="window">To obtain the style dialog window</param>
|
||||
/// <returns>current extension style value</returns>
|
||||
private static int GetCurrentWindowStyle(Window window)
|
||||
{
|
||||
var style = PInvoke.GetWindowLong(new(new WindowInteropHelper(window).Handle), WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE);
|
||||
if (style == 0 && Marshal.GetLastPInvokeError() != 0)
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastPInvokeError());
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -8,7 +8,6 @@ using System.Windows.Controls;
|
|||
using System.Windows.Forms;
|
||||
using Flow.Launcher.Core.Plugin;
|
||||
using Flow.Launcher.Core.Resource;
|
||||
using Flow.Launcher.Helper;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using Flow.Launcher.ViewModel;
|
||||
using Screen = System.Windows.Forms.Screen;
|
||||
|
|
@ -26,10 +25,10 @@ using System.Media;
|
|||
using DataObject = System.Windows.DataObject;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Interop;
|
||||
using Windows.Win32;
|
||||
using Window = System.Windows.Window;
|
||||
using System.Linq;
|
||||
using System.Windows.Shapes;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
|
||||
namespace Flow.Launcher
|
||||
{
|
||||
|
|
@ -78,14 +77,13 @@ namespace Flow.Launcher
|
|||
|
||||
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||
{
|
||||
if (msg == PInvoke.WM_ENTERSIZEMOVE)
|
||||
if (Win32Helper.WM_ENTERSIZEMOVE(msg))
|
||||
{
|
||||
_initialWidth = (int)Width;
|
||||
_initialHeight = (int)Height;
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (msg == PInvoke.WM_EXITSIZEMOVE)
|
||||
else if (Win32Helper.WM_EXITSIZEMOVE(msg))
|
||||
{
|
||||
if (_initialHeight != (int)Height)
|
||||
{
|
||||
|
|
@ -168,7 +166,8 @@ namespace Flow.Launcher
|
|||
|
||||
private void OnSourceInitialized(object sender, EventArgs e)
|
||||
{
|
||||
WindowsInteropHelper.HideFromAltTab(this);
|
||||
Win32Helper.HideFromAltTab(this);
|
||||
Win32Helper.DisableControlBox(this);
|
||||
}
|
||||
|
||||
private void OnInitialized(object sender, EventArgs e)
|
||||
|
|
@ -184,13 +183,12 @@ namespace Flow.Launcher
|
|||
// Show notify icon when flowlauncher is hidden
|
||||
InitializeNotifyIcon();
|
||||
InitializeColorScheme();
|
||||
WindowsInteropHelper.DisableControlBox(this);
|
||||
InitProgressbarAnimation();
|
||||
// Initialize call twice to work around multi-display alignment issue- https://github.com/Flow-Launcher/Flow.Launcher/issues/2910
|
||||
InitializePosition();
|
||||
InitializePosition();
|
||||
// Refresh frame
|
||||
await ThemeManager.Instance.RefreshFrameAsync();
|
||||
await Ioc.Default.GetRequiredService<Theme>().RefreshFrameAsync();
|
||||
PreviewReset();
|
||||
// Since the default main window visibility is visible, so we need set focus during startup
|
||||
QueryTextBox.Focus();
|
||||
|
|
@ -314,9 +312,9 @@ namespace Flow.Launcher
|
|||
Top = 10;
|
||||
break;
|
||||
case SearchWindowAligns.Custom:
|
||||
Left = WindowsInteropHelper.TransformPixelsToDIP(this,
|
||||
Left = Win32Helper.TransformPixelsToDIP(this,
|
||||
screen.WorkingArea.X + _settings.CustomWindowLeft, 0).X;
|
||||
Top = WindowsInteropHelper.TransformPixelsToDIP(this, 0,
|
||||
Top = Win32Helper.TransformPixelsToDIP(this, 0,
|
||||
screen.WorkingArea.Y + _settings.CustomWindowTop).Y;
|
||||
break;
|
||||
}
|
||||
|
|
@ -377,7 +375,7 @@ namespace Flow.Launcher
|
|||
|
||||
open.Click += (o, e) => _viewModel.ToggleFlowLauncher();
|
||||
gamemode.Click += (o, e) => _viewModel.ToggleGameMode();
|
||||
positionreset.Click += (o, e) => PositionReset();
|
||||
positionreset.Click += (o, e) => _ = PositionResetAsync();
|
||||
settings.Click += (o, e) => App.API.OpenSettingDialog();
|
||||
exit.Click += (o, e) => Close();
|
||||
|
||||
|
|
@ -403,7 +401,7 @@ namespace Flow.Launcher
|
|||
// Get context menu handle and bring it to the foreground
|
||||
if (PresentationSource.FromVisual(contextMenu) is HwndSource hwndSource)
|
||||
{
|
||||
PInvoke.SetForegroundWindow(new(hwndSource.Handle));
|
||||
Win32Helper.SetForegroundWindow(hwndSource.Handle);
|
||||
}
|
||||
|
||||
contextMenu.Focus();
|
||||
|
|
@ -422,13 +420,13 @@ namespace Flow.Launcher
|
|||
}
|
||||
}
|
||||
|
||||
private void OpenWelcomeWindow()
|
||||
private static void OpenWelcomeWindow()
|
||||
{
|
||||
var WelcomeWindow = new WelcomeWindow();
|
||||
WelcomeWindow.Show();
|
||||
}
|
||||
|
||||
private async void PositionReset()
|
||||
private async Task PositionResetAsync()
|
||||
{
|
||||
_viewModel.Show();
|
||||
await Task.Delay(300); // If don't give a time, Positioning will be weird.
|
||||
|
|
@ -846,7 +844,7 @@ namespace Flow.Launcher
|
|||
screen = Screen.PrimaryScreen;
|
||||
break;
|
||||
case SearchWindowScreens.Focus:
|
||||
var foregroundWindowHandle = PInvoke.GetForegroundWindow().Value;
|
||||
var foregroundWindowHandle = Win32Helper.GetForegroundWindow();
|
||||
screen = Screen.FromHandle(foregroundWindowHandle);
|
||||
break;
|
||||
case SearchWindowScreens.Custom:
|
||||
|
|
@ -865,38 +863,38 @@ namespace Flow.Launcher
|
|||
|
||||
public double HorizonCenter(Screen screen)
|
||||
{
|
||||
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
|
||||
var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0);
|
||||
var dip1 = Win32Helper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
|
||||
var dip2 = Win32Helper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0);
|
||||
var left = (dip2.X - ActualWidth) / 2 + dip1.X;
|
||||
return left;
|
||||
}
|
||||
|
||||
public double VerticalCenter(Screen screen)
|
||||
{
|
||||
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y);
|
||||
var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height);
|
||||
var dip1 = Win32Helper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y);
|
||||
var dip2 = Win32Helper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height);
|
||||
var top = (dip2.Y - QueryTextBox.ActualHeight) / 4 + dip1.Y;
|
||||
return top;
|
||||
}
|
||||
|
||||
public double HorizonRight(Screen screen)
|
||||
{
|
||||
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
|
||||
var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0);
|
||||
var dip1 = Win32Helper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
|
||||
var dip2 = Win32Helper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0);
|
||||
var left = (dip1.X + dip2.X - ActualWidth) - 10;
|
||||
return left;
|
||||
}
|
||||
|
||||
public double HorizonLeft(Screen screen)
|
||||
{
|
||||
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
|
||||
var dip1 = Win32Helper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
|
||||
var left = dip1.X + 10;
|
||||
return left;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register up and down key
|
||||
/// todo: any way to put this in xaml ?
|
||||
/// todo: Put this in xaml?
|
||||
/// </summary>
|
||||
private void OnKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media.Animation;
|
||||
using Flow.Launcher.Helper;
|
||||
using Flow.Launcher.Infrastructure;
|
||||
using Flow.Launcher.Infrastructure.Image;
|
||||
|
||||
|
|
@ -12,14 +11,14 @@ namespace Flow.Launcher
|
|||
{
|
||||
public partial class Msg : Window
|
||||
{
|
||||
Storyboard fadeOutStoryboard = new Storyboard();
|
||||
private readonly Storyboard fadeOutStoryboard = new();
|
||||
private bool closing;
|
||||
|
||||
public Msg()
|
||||
{
|
||||
InitializeComponent();
|
||||
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
|
||||
var dipWorkingArea = WindowsInteropHelper.TransformPixelsToDIP(this,
|
||||
var dipWorkingArea = Win32Helper.TransformPixelsToDIP(this,
|
||||
screen.WorkingArea.Width,
|
||||
screen.WorkingArea.Height);
|
||||
Left = dipWorkingArea.X - Width;
|
||||
|
|
@ -82,13 +81,13 @@ namespace Flow.Launcher
|
|||
Show();
|
||||
|
||||
await Dispatcher.InvokeAsync(async () =>
|
||||
{
|
||||
if (!closing)
|
||||
{
|
||||
closing = true;
|
||||
await Dispatcher.InvokeAsync(fadeOutStoryboard.Begin);
|
||||
}
|
||||
});
|
||||
{
|
||||
if (!closing)
|
||||
{
|
||||
closing = true;
|
||||
await Dispatcher.InvokeAsync(fadeOutStoryboard.Begin);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
DwmSetWindowAttribute
|
||||
DwmExtendFrameIntoClientArea
|
||||
SystemParametersInfo
|
||||
SetForegroundWindow
|
||||
|
||||
GetWindowLong
|
||||
SetWindowLong
|
||||
GetForegroundWindow
|
||||
GetDesktopWindow
|
||||
GetShellWindow
|
||||
GetWindowRect
|
||||
GetClassName
|
||||
FindWindowEx
|
||||
WINDOW_STYLE
|
||||
|
||||
WM_ENTERSIZEMOVE
|
||||
WM_EXITSIZEMOVE
|
||||
|
||||
SetLastError
|
||||
WINDOW_EX_STYLE
|
||||
|
|
@ -4,7 +4,7 @@ using System.Windows.Forms;
|
|||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Flow.Launcher.Helper;
|
||||
using Flow.Launcher.Infrastructure;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using Flow.Launcher.Plugin;
|
||||
using Flow.Launcher.SettingPages.Views;
|
||||
|
|
@ -143,8 +143,8 @@ public partial class SettingWindow
|
|||
private double WindowLeft()
|
||||
{
|
||||
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
|
||||
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
|
||||
var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0);
|
||||
var dip1 = Win32Helper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
|
||||
var dip2 = Win32Helper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0);
|
||||
var left = (dip2.X - ActualWidth) / 2 + dip1.X;
|
||||
return left;
|
||||
}
|
||||
|
|
@ -152,8 +152,8 @@ public partial class SettingWindow
|
|||
private double WindowTop()
|
||||
{
|
||||
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
|
||||
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y);
|
||||
var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height);
|
||||
var dip1 = Win32Helper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y);
|
||||
var dip2 = Win32Helper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height);
|
||||
var top = (dip2.Y - ActualHeight) / 2 + dip1.Y - 20;
|
||||
return top;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using System.Threading.Tasks;
|
|||
using System.Windows;
|
||||
using Flow.Launcher.Core.Plugin;
|
||||
using Flow.Launcher.Core.Resource;
|
||||
using Flow.Launcher.Helper;
|
||||
using Flow.Launcher.Infrastructure;
|
||||
using Flow.Launcher.Infrastructure.Hotkey;
|
||||
using Flow.Launcher.Infrastructure.Storage;
|
||||
|
|
@ -27,7 +26,6 @@ using Flow.Launcher.Infrastructure.Image;
|
|||
using System.Windows.Media;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using System.Windows.Threading;
|
||||
using System.Windows.Interop;
|
||||
|
||||
namespace Flow.Launcher.ViewModel
|
||||
{
|
||||
|
|
@ -1484,7 +1482,7 @@ namespace Flow.Launcher.ViewModel
|
|||
/// </summary>
|
||||
public bool ShouldIgnoreHotkeys()
|
||||
{
|
||||
return Settings.IgnoreHotkeysOnFullscreen && WindowsInteropHelper.IsWindowFullscreen() || GameModeStatus;
|
||||
return Settings.IgnoreHotkeysOnFullscreen && Win32Helper.IsForegroundWindowFullscreen() || GameModeStatus;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
|||
Loading…
Reference in a new issue