c# - 通过 PowerShell 调用 user32.dll "SetWindowCompositionAttribute"

标签 c# powershell pinvoke

我一直在努力让 PowerShell 控制 SetWindowCompositionAttribute通过 Pinvoke(通过 PowerShell 向 Windows 任务栏和其他窗口添加 Windows 10 Acrylic Blur 效果)。

我很乐意发送简单的参数,例如 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)

最佳答案

编辑:添加了带有颜色着色的“亚克力”模糊选项。虽然移动窗口时似乎有点慢。

这就是你想要的吗?

运行函数前的窗口:

Before function

运行函数后的窗口(Set-WindowBlur -MainWindowHandle 853952 -Enable):

After function

主要代码:

$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)
}

调用类似的东西:

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

关于c# - 通过 PowerShell 调用 user32.dll "SetWindowCompositionAttribute",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66002667/

相关文章:

c# - SQL Server 插入

c# - 结构 DEVMODE 中的 Marshal.PtrToStructure() 和字符数组出现问题

C# P/调用结构对齐

c# - Windows 窗体中带有图标的驱动器选择框

c# - 为什么更喜欢在 IQueryable 上使用 linq 而不是在 IEnumerable 上使用 linq?

powershell - 查看网络适配器的高级属性,例如Get-NetAdapterAdvancedProperty

regex - PowerShell-搜索电子邮件地址并排除一些地址

.net - 检测从 .NET 调用的调用 dll 的崩溃

c# - 我正在尝试使基本碰撞动力学起作用

windows - PowerShell软件包管理-存储库vs提供程序vs源