在WPF应用程序中禁用Aero Peek

5

我希望在我的WPF应用程序中禁用Aero Peek(当用户将鼠标放置在“显示桌面”按钮上时,我的应用程序必须可见)。我使用以下PInvoke签名:

[Flags]
public enum DwmWindowAttribute : uint
{
    DWMWA_NCRENDERING_ENABLED = 1,
    DWMWA_NCRENDERING_POLICY,
    DWMWA_TRANSITIONS_FORCEDISABLED,
    DWMWA_ALLOW_NCPAINT,
    DWMWA_CAPTION_BUTTON_BOUNDS,
    DWMWA_NONCLIENT_RTL_LAYOUT,
    DWMWA_FORCE_ICONIC_REPRESENTATION,
    DWMWA_FLIP3D_POLICY,
    DWMWA_EXTENDED_FRAME_BOUNDS,
    DWMWA_HAS_ICONIC_BITMAP,
    DWMWA_DISALLOW_PEEK,
    DWMWA_EXCLUDED_FROM_PEEK,
    DWMWA_LAST
}

[Flags]
public enum DWMNCRenderingPolicy : uint
{
    UseWindowStyle,
    Disabled,
    Enabled,
    Last
}

[DllImport("dwmapi.dll", PreserveSig=false)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DwmIsCompositionEnabled();

[DllImport("dwmapi.dll", PreserveSig=false)]
public static extern Int32 DwmSetWindowAttribute(IntPtr hwnd,
                                                 DwmWindowAttribute dwmAttribute,
                                                 IntPtr pvAttribute,
                                                 uint cbAttribute);

还有这种用法:

    var helper = new WindowInteropHelper(this);
    helper.EnsureHandle();

    if (API.DwmIsCompositionEnabled())
    {
        var status = Marshal.AllocCoTaskMem(sizeof(uint));
        Marshal.Copy(new[] {(int) API.DWMNCRenderingPolicy.Enabled}, 0, status, 1);
        API.DwmSetWindowAttribute(helper.Handle,
                                  API.DwmWindowAttribute.DWMWA_EXCLUDED_FROM_PEEK,
                                  status,
                                  sizeof (uint));
    }

在我的64位系统(Windows 7 Professional)中,只有运行64位应用程序时才能正常工作。如果我以WOW64模式运行32位应用程序,则会收到异常信息:
“调用PInvoke函数'XXX::DwmSetWindowAttribute'已经破坏了堆栈平衡。这可能是因为托管PInvoke签名与非托管目标签名不匹配。请检查PInvoke签名的调用约定和参数是否与目标非托管签名相匹配。”
你对此有何看法?该如何解决?

可能是Unbalanced Stack!的重复问题。 - ChrisWue
这不是一个解决方案。当我使用任何调用约定时,我会得到异常或函数无法工作的情况。 - Aleksandr Vishnyakov
@Alexander,你能否在你的问题中添加你尝试过什么以及它是如何失败的? - ChrisWue
@ChrisWue 我不明白。我已经详细描述了一个问题。 - Aleksandr Vishnyakov
你的问题是收到了“不平衡堆栈”异常。原因是你需要使用Cdecl调用约定。你已经说过你尝试过了,但函数仍然无法工作。那么,它为什么不能工作呢?在将Cdecl添加到dllimport后,你是否仍然收到“不平衡堆栈”异常? - ChrisWue
@ChrisWue 是的,我在将Cdecl添加到DllImport后收到了“不平衡堆栈”异常。 - Aleksandr Vishnyakov
1个回答

6
我更改了签名:
[DllImport("dwmapi.dll", PreserveSig = true)]
public static extern int DwmSetWindowAttribute(IntPtr hwnd,
                                               DwmWindowAttribute dwmAttribute,
                                               IntPtr pvAttribute,
                                               uint cbAttribute);

使用方法:

if (API.DwmIsCompositionEnabled())
{
    var status = Marshal.AllocHGlobal(sizeof(int));
    Marshal.WriteInt32(status, 1); // true
    API.DwmSetWindowAttribute(helper.Handle,
                              API.DwmWindowAttribute.DWMWA_EXCLUDED_FROM_PEEK,
                              status,
                              sizeof(int));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接