问题描述
我一直在努力让 PowerShell 通过 Pinvoke 控制 SetWindowCompositionAttribute(通过 PowerShell 添加 Windows 10 丙烯酸模糊效果到 Windows 任务栏和其他窗口)。
我很乐意发送简单的参数,如 HWND 和相应的值(如下面的两个示例所示)。但是,我不确定如何增强下面的 PowerShell 代码,以便它也可以处理打包在结构中的发送参数。请参阅SetWindowCompositionAttribute。
我在 Delphi 和 AutoIt(而不是 PowerShell)中看到了执行此操作的代码示例。不幸的是,我无法弄清楚它们。
无论如何,下面是我的 PowerShell 代码和使用示例,演示了与 Windows API 的基本交互。我希望有人可以帮助我增强此代码(通过几个示例),以控制 SetwindowCompositionAttribute
提供的各种功能。
最终,我希望能够指定我也希望添加模糊的组件的 hWnd、Windows 类名和/或窗口标题名;并且,如果可能,指定模糊/透明度的量。
$script:nativeMethods = @();
function Register-NativeMethod([string]$dll,[string]$methodSignature) {
$script:nativeMethods += [PSCustomObject]@{ Dll = $dll; Signature = $methodSignature; }
}
function Add-NativeMethods() {
$nativeMethodsCode = $script:nativeMethods | % { "
[DllImport(`"$($_.Dll)`")]
public static extern $($_.Signature);
" }
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class NativeMethods {
$nativeMethodsCode
}
"@
}
#Build class and registers them:
Add-NativeMethods
#Example 1:
Register-NativeMethod "user32.dll" "bool SetForegroundWindow(IntPtr hWnd)"
[NativeMethods]::SetForegroundWindow((Get-Process -name notepad).MainWindowHandle)
#Example 2:
Register-NativeMethod "user32.dll" "bool ShowWindow(IntPtr hWnd,int nCmdshow)"
[NativeMethods]::ShowWindow((Get-Process -name notepad).MainWindowHandle,0)
解决方法
编辑:添加了带有颜色着色的“丙烯酸”模糊选项。移动窗户时似乎有点慢。
这就是你想要的吗?
运行函数前的窗口:
运行函数后的窗口(Set-WindowBlur -MainWindowHandle 853952 -Enable
):
主要代码:
$SetWindowComposition = @'
[DllImport("user32.dll")]
public static extern int SetWindowCompositionAttribute(IntPtr hwnd,ref WindowCompositionAttributeData data);
[StructLayout(LayoutKind.Sequential)]
public struct WindowCompositionAttributeData {
public WindowCompositionAttribute Attribute;
public IntPtr Data;
public int SizeOfData;
}
public enum WindowCompositionAttribute {
WCA_ACCENT_POLICY = 19
}
public enum AccentState {
ACCENT_DISABLED = 0,ACCENT_ENABLE_BLURBEHIND = 3,ACCENT_ENABLE_ACRYLICBLURBEHIND = 4
}
[StructLayout(LayoutKind.Sequential)]
public struct AccentPolicy {
public AccentState AccentState;
public int AccentFlags;
public int GradientColor;
public int AnimationId;
}
'@
Add-Type -MemberDefinition $SetWindowComposition -Namespace 'WindowStyle' -Name 'Blur'
function Set-WindowBlur {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[int]
$MainWindowHandle,[Parameter(ParameterSetName='Enable',Mandatory)]
[switch]
$Enable,[Parameter(ParameterSetName='Acrylic',Mandatory)]
[switch]
$Acrylic,# Color in BGR hex format (for ease,will just be used as an integer),eg. for red use 0x0000FF
[Parameter(ParameterSetName='Acrylic')]
[ValidateRange(0x000000,0xFFFFFF)]
[int]
$Color= 0x000000,# Transparency 0-255,0 full transparency and 255 is a solid $Color
[Parameter(ParameterSetName='Acrylic')]
[ValidateRange(0,255)]
[int]
$Transparency = 80,[Parameter(ParameterSetName='Disable',Mandatory)]
[switch]
$Disable
)
$Accent = [WindowStyle.Blur+AccentPolicy]::new()
switch ($PSCmdlet.ParameterSetName) {
'Enable' {
$Accent.AccentState = [WindowStyle.Blur+AccentState]::ACCENT_ENABLE_BLURBEHIND
}
'Acrylic' {
$Accent.AccentState = [WindowStyle.Blur+AccentState]::ACCENT_ENABLE_ACRYLICBLURBEHIND
$Accent.GradientColor = $Transparency -shl 24 -bor ($Color -band 0xFFFFFF)
}
'Disable' {
$Accent.AccentState = [WindowStyle.Blur+AccentState]::ACCENT_DISABLED
}
}
$AccentStructSize = [System.Runtime.InteropServices.Marshal]::SizeOf($Accent)
$AccentPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($AccentStructSize)
[System.Runtime.InteropServices.Marshal]::StructureToPtr($Accent,$AccentPtr,$false)
$Data = [WindowStyle.Blur+WindowCompositionAttributeData]::new()
$Data.Attribute = [WindowStyle.Blur+WindowCompositionAttribute]::WCA_ACCENT_POLICY
$Data.SizeOfData = $AccentStructSize
$Data.Data = $AccentPtr
$Result = [WindowStyle.Blur]::SetWindowCompositionAttribute($MainWindowHandle,[ref]$Data)
if ($Result -eq 1) {
Write-Verbose "Successfully set Window Blur status."
}
else {
Write-Verbose "Warning,couldn't set Window Blur status."
}
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($AccentPtr)
}
将 call 用于以下内容:
Set-WindowBlur -MainWindowHandle 1114716 -Acrylic -Color 0xFF0000 -Transparency 50
Set-WindowBlur -MainWindowHandle 1114716 -Disable
Set-WindowBlur -MainWindowHandle 1114716 -Enable
改编自:https://gist.github.com/riverar/fd6525579d6bbafc6e48 来自: https://github.com/riverar/sample-win32-acrylicblur/blob/master/MainWindow.xaml.cs
,我可以看到您通过在 Powershell 脚本中嵌入/构建 C# 源代码来调用这些 Windows API 函数。这可能是要走的路,尽管我认为我不会费心去尝试“添加”方法并逐个构建 C# 源代码(因为使用您的系统声明 SetWindowCompositionAttribute
不会那么容易) .
首先,因为 SetWindowCompositionAttribute
接受复杂的参数,所以您必须在 C# 代码中声明底层结构,然后您可以公开 C# 方法,以简化 SetWindowCompositionAttribute
的使用以供 Powershell 端使用.
通过谷歌搜索(只需输入TheMethodINeedToWrap C#),我很快找到了一些资源。我将这些发现混合到一个 C# 类中,该类公开了一个(足够简单,它是 Powershell 可调用的)方法来模糊窗口。我的测试结果并不理想,因为我最终得到了一个模糊的窗口边框,但看起来很奇怪的内部和控件(必须与 winforms 和/或窗口创建参数有关),但至少我得到了一些东西。
因为有点长,我把这个类保存为一个要点 here,但正如我所说,它由一堆互操作结构和方法定义组成,然后是一个公共方法,简化了对 {{1 }}。
PS:如果证明 SetWindowCompositionAttribute
太难包装,DwmSetWindowAttribute 可能是一个可行的选择。您还会发现,尽管有时需要调整,http://pinvoke.net/ 证明是互操作定义的可行来源。