-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce win11 window styles: acrylic, mica, micaAlt
- Loading branch information
Showing
13 changed files
with
507 additions
and
216 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,291 @@ | ||
using System.Runtime.InteropServices; | ||
using static Tiefsee.WindowAPI.PInvoke; | ||
using static Tiefsee.WindowAPI.PInvoke.ParameterTypes; | ||
|
||
namespace Tiefsee { | ||
public class WindowAPI { | ||
|
||
/// <summary> | ||
/// 視窗拖曳 | ||
/// </summary> | ||
public static void WindowDrag(IntPtr hwnd, ResizeDirection type) { | ||
|
||
/*if (_run== ResizeDirection.Move) { //拖曳視窗 | ||
int WM_NCLBUTTONDOWN = 161; // 0xA1 | ||
int HTCAPTION = 2; | ||
ReleaseCapture(); | ||
SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0); | ||
return; | ||
}*/ | ||
|
||
ReleaseCapture(); | ||
SendMessage(hwnd, WM_SYSCOMMAND, (int)(type), 0); | ||
} | ||
|
||
#region 視窗拖曳 | ||
|
||
public enum ResizeDirection { | ||
LC = 0xF001, // 左 | ||
RC = 0xF002, // 右 | ||
CT = 0xF003, // 上 | ||
LT = 0xF004, // 左上 | ||
RT = 0xF005, // 右上 | ||
CB = 0xF006, // 下 | ||
LB = 0xF007, // 左下 | ||
RB = 0xF008, // 右下 | ||
Move = 0xF009 // 移動 | ||
} | ||
|
||
// 指定滑鼠到特定視窗 | ||
[DllImport("user32.dll", CharSet = CharSet.Auto)] | ||
public static extern IntPtr SetCapture(IntPtr hWnd); | ||
|
||
// 釋放滑鼠 | ||
[DllImport("user32.dll", CharSet = CharSet.Auto)] | ||
public static extern bool ReleaseCapture(); | ||
|
||
// 拖曳視窗 | ||
[DllImport("user32.dll", CharSet = CharSet.Auto)] | ||
public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam); | ||
public const int WM_SYSCOMMAND = 0x0112; | ||
public const int WM_LBUTTONUP = 0x202; | ||
|
||
#endregion | ||
|
||
/// <summary> | ||
/// win10 視窗效果 | ||
/// </summary> | ||
/// <param name="type"> acrylic | aero </param> | ||
public static void WindowStyleForWin10(IntPtr hwnd, string type) { | ||
|
||
type = type.ToLower(); | ||
|
||
var accent = new AccentPolicy(); | ||
|
||
if (type == "acrylic") { | ||
accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND; | ||
accent.GradientColor = (_blurOpacity << 24) | (_blurBackgroundColor & 0xFFFFFF); | ||
} | ||
else if (type == "aero") { | ||
if (StartWindow.isWin11) { return; } | ||
accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; | ||
} | ||
else { | ||
return; | ||
} | ||
|
||
var accentStructSize = Marshal.SizeOf(accent); | ||
|
||
var accentPtr = Marshal.AllocHGlobal(accentStructSize); | ||
Marshal.StructureToPtr(accent, accentPtr, false); | ||
|
||
var data = new WindowCompositionAttributeData(); | ||
data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY; | ||
data.SizeOfData = accentStructSize; | ||
data.Data = accentPtr; | ||
|
||
SetWindowCompositionAttribute(hwnd, ref data); | ||
|
||
Marshal.FreeHGlobal(accentPtr); | ||
} | ||
|
||
/// <summary> | ||
/// win11 視窗效果 | ||
/// </summary> | ||
public static void WindowStyleForWin11(IntPtr hwnd, SystemBackdropType type) { | ||
if (StartWindow.isWin11 == false) { return; } | ||
SetWindowAttribute(hwnd, DWMWINDOWATTRIBUTE.DWMWA_SYSTEMBACKDROP_TYPE, (int)type); | ||
} | ||
|
||
/// <summary> | ||
/// win11 暗黑模式 | ||
/// </summary> | ||
public static void WindowThemeForWin11(IntPtr hwnd, ImmersiveDarkMode type) { | ||
if (StartWindow.isWin11 == false) { return; } | ||
SetWindowAttribute(hwnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, (int)type); | ||
} | ||
|
||
#region 視窗效果 | ||
|
||
[DllImport("user32.dll")] | ||
internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data); | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
internal struct WindowCompositionAttributeData { | ||
public WindowCompositionAttribute Attribute; | ||
public IntPtr Data; | ||
public int SizeOfData; | ||
} | ||
|
||
internal enum WindowCompositionAttribute { | ||
WCA_ACCENT_POLICY = 19 | ||
} | ||
|
||
internal enum AccentState { | ||
ACCENT_DISABLED = 0, | ||
ACCENT_ENABLE_GRADIENT = 1, | ||
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, | ||
ACCENT_ENABLE_BLURBEHIND = 3, | ||
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, | ||
ACCENT_INVALID_STATE = 5 | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
internal struct AccentPolicy { | ||
public AccentState AccentState; | ||
public uint AccentFlags; | ||
public uint GradientColor; | ||
public uint AnimationId; | ||
} | ||
|
||
private static uint _blurOpacity = 0; | ||
private static uint _blurBackgroundColor = 0x010101; /* BGR color format */ | ||
|
||
/// <summary> | ||
/// 視窗效果類型 | ||
/// </summary> | ||
public enum SystemBackdropType { | ||
None = 1, | ||
Acrylic = 3, | ||
Mica = 2, | ||
MicaAlt = 4, | ||
} | ||
|
||
/// <summary> | ||
/// 啟用或停用 win11 暗黑模式 | ||
/// </summary> | ||
public enum ImmersiveDarkMode { | ||
Disabled = 0, | ||
Enabled = 1 | ||
} | ||
|
||
[DllImport("dwmapi.dll")] | ||
private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins); | ||
|
||
[DllImport("dwmapi.dll")] | ||
static extern int DwmSetWindowAttribute(IntPtr hwnd, ParameterTypes.DWMWINDOWATTRIBUTE dwAttribute, ref int pvAttribute, int cbAttribute); | ||
|
||
public static int ExtendFrame(IntPtr hwnd, ParameterTypes.MARGINS margins) | ||
=> DwmExtendFrameIntoClientArea(hwnd, ref margins); | ||
|
||
public static int SetWindowAttribute(IntPtr hwnd, ParameterTypes.DWMWINDOWATTRIBUTE attribute, int parameter) | ||
=> DwmSetWindowAttribute(hwnd, attribute, ref parameter, Marshal.SizeOf<int>()); | ||
|
||
public class PInvoke { | ||
public class ParameterTypes { | ||
[Flags] | ||
public enum DWMWINDOWATTRIBUTE { | ||
DWMWA_WINDOW_CORNER_PREFERENCE = 33, | ||
|
||
DWMWA_USE_IMMERSIVE_DARK_MODE = 20, | ||
DWMWA_SYSTEMBACKDROP_TYPE = 38 | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
public struct MARGINS { | ||
public int cxLeftWidth; | ||
public int cxRightWidth; | ||
public int cyTopHeight; | ||
public int cyBottomHeight; | ||
} | ||
} | ||
|
||
public class Methods { | ||
[DllImport("dwmapi.dll")] | ||
public static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref ParameterTypes.MARGINS pMarInset); | ||
|
||
[DllImport("dwmapi.dll")] | ||
public static extern int DwmSetWindowAttribute(IntPtr hwnd, ParameterTypes.DWMWINDOWATTRIBUTE dwAttribute, ref int pvAttribute, int cbAttribute); | ||
|
||
public static int ExtendFrame(IntPtr hwnd, ParameterTypes.MARGINS margins) { | ||
return DwmExtendFrameIntoClientArea(hwnd, ref margins); | ||
} | ||
|
||
public static int SetWindowAttribute(IntPtr hwnd, ParameterTypes.DWMWINDOWATTRIBUTE attribute, int parameter) { | ||
return DwmSetWindowAttribute(hwnd, attribute, ref parameter, Marshal.SizeOf<int>()); | ||
} | ||
} | ||
} | ||
|
||
#endregion | ||
|
||
/// <summary> | ||
/// win11 視窗圓角 | ||
/// </summary> | ||
public static string WindowRoundedCorners(IntPtr hwnd, bool enable) { | ||
try { | ||
var attribute = DWMWINDOWATTRIBUTE.DWMWA_WINDOW_CORNER_PREFERENCE; | ||
DWM_WINDOW_CORNER_PREFERENCE preference; | ||
if (enable) { | ||
preference = DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_ROUND; | ||
} | ||
else { | ||
preference = DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_DEFAULT; | ||
} | ||
DwmSetWindowAttribute(hwnd, attribute, ref preference, sizeof(uint)); | ||
} | ||
catch (Exception e) { | ||
return e.ToString(); | ||
} | ||
return ""; | ||
} | ||
|
||
#region win11 視窗圓角 | ||
|
||
// The DWM_WINDOW_CORNER_PREFERENCE enum for DwmSetWindowAttribute's third parameter, which tells the function | ||
// what value of the enum to set. | ||
// Copied from dwmapi.h | ||
public enum DWM_WINDOW_CORNER_PREFERENCE { | ||
DWMWCP_DEFAULT = 0, | ||
DWMWCP_DONOTROUND = 1, | ||
DWMWCP_ROUND = 2, | ||
DWMWCP_ROUNDSMALL = 3 | ||
} | ||
|
||
// Import dwmapi.dll and define DwmSetWindowAttribute in C# corresponding to the native function. | ||
[DllImport("dwmapi.dll", CharSet = CharSet.Unicode, PreserveSig = false)] | ||
internal static extern void DwmSetWindowAttribute(IntPtr hwnd, | ||
DWMWINDOWATTRIBUTE attribute, | ||
ref DWM_WINDOW_CORNER_PREFERENCE pvAttribute, | ||
uint cbAttribute); | ||
#endregion | ||
|
||
|
||
#region 視窗取得焦點 | ||
|
||
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)] | ||
public static extern bool SwitchToThisWindow(IntPtr hWnd, Boolean fAltTab); | ||
|
||
// ------------- | ||
|
||
// https://stackoverflow.com/questions/257587/bring-a-window-to-the-front-in-wpf | ||
|
||
/// <summary> | ||
/// Activate a window from anywhere by attaching to the foreground window | ||
/// </summary> | ||
public static void GlobalActivate(IntPtr interopHelper) { | ||
//Get the process ID for this window's thread | ||
//var interopHelper = new WindowInteropHelper(w); | ||
UInt32 thisWindowThreadId = GetWindowThreadProcessId(interopHelper, IntPtr.Zero); | ||
|
||
//Get the process ID for the foreground window's thread | ||
var currentForegroundWindow = GetForegroundWindow(); | ||
var currentForegroundWindowThreadId = GetWindowThreadProcessId(currentForegroundWindow, IntPtr.Zero); | ||
|
||
//Attach this window's thread to the current window's thread | ||
AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true); | ||
} | ||
|
||
[DllImport("user32.dll")] | ||
private static extern IntPtr GetForegroundWindow(); | ||
|
||
[DllImport("user32.dll")] | ||
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); | ||
|
||
[DllImport("user32.dll")] | ||
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach); | ||
|
||
#endregion | ||
} | ||
|
||
} |
Oops, something went wrong.