【问题标题】:HWND API: How to disable window animations when calling ShowWindow(...)HWND API:如何在调用 ShowWindow(...) 时禁用窗口动画
【发布时间】:2016-06-07 04:44:40
【问题描述】:

我想知道在调用 HWnd ShowWindow() 方法时如何抑制动画。这是我的代码:

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);

public enum ShowWindowCommands
{
    HIDE = 0,
    SHOWNORMAL = 1,
    SHOWMINIMIZED = 2,
    MAXIMIZE = 3,
    SHOWNOACTIVATE = 4,
    SHOW = 5,
    MINIMIZE = 6,
    SHOWMINNOACTIVE = 7,
    SHOWNA = 8,
    RESTORE = 9,
    SHOWDEFAULT = 10,
    FORCEMINIMIZE = 11
}

public static void MinimizeWindow(IntPtr hWnd)
{
    ShowWindow(hWnd, ShowWindowCommands.MINIMIZE);
}

问题是,动画执行了,直到动画结束,方法才返回。

我尝试使用DwmSetWindowAttribute() 方法:

[DllImport("dwmapi.dll", PreserveSig = true)]
static extern int DwmSetWindowAttribute(IntPtr hWnd, uint attr, ref int attrValue, int size);

const uint DWM_TransitionsForceDisabled = 3;

public static void SetEnabled(IntPtr hWnd, bool enabled)
{
    int attrVal = enabled ? 0 : 1;
    DwmSetWindowAttribute(hWnd, DWM_TransitionsForceDisabled, ref attrVal, 4);
}

但是动画没有被抑制。 我的操作系统是 Windows 7,32 位。

【问题讨论】:

  • 检查DwmSetWindowAttribute的返回值,看看它是否失败,如果失败,原因是什么。
  • @Jonathan Potter 返回值为零,即操作成功
  • 查看stackoverflow.com/questions/6160118/…的答案,看来您传递的数据指针不正确。
  • 当我将方法签名更改为使用 IntPtr 时,它返回代码 0x800703e6(对内存位置的无效访问)。我使用的签名应该没问题,因为它是我问题链接中使用的签名。
  • 发布的sn-ps是正确的。寻找一个简单的错误,例如太晚调用 SetEnabled() 或反转其 enabled 参数的含义或使用错误的窗口句柄。

标签: c# winapi hwnd


【解决方案1】:

https://devblogs.microsoft.com/oldnewthing/20121003-00/?p=6423


BOOL ani = TRUE;
DwmSetWindowAttribute(m_top, DWMWA_TRANSITIONS_FORCEDISABLED, &ani, sizeof(ani));

【讨论】:

    【解决方案2】:

    不是最好的选择,但您可以尝试调用SystemParametersInfo() 指定SPI_GETANIMATION 以获取窗口动画的当前设置,如果启用则在显示窗口之前使用SPI_SETANIMATION 禁用它们,然后恢复以前的设置.例如:

    [StructLayout(LayoutKind.Sequential)]
    public struct ANIMATIONINFO
    {
      uint cbSize;
      int iMinAnimate;
    }
    
    [DllImport("User32.dll", SetLastError=true)]
    static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref ANIMATIONINFO pvParam, uint fWinIni);
    
    const uint SPI_GETANIMATION = 72;
    const uint SPI_SETANIMATION = 73;
    
    public static void MinimizeWindow(IntPtr hWnd)
    {
        ANIMATIONINFO anim;
        anim.cbSize = Marshal.SizeOf(anim);
        anim.iMinAnimate = 0;
    
        SystemParametersInfo(SPI_GETANIMATION, Marshal.SizeOf(anim), anim, 0);
    
        if (anim.iMinAnimate != 0)
        {
            anim.iMinAnimate = 0;
            SystemParametersInfo(SPI_SETANIMATION, Marshal.SizeOf(anim), anim, 0);
    
            ShowWindow(hWnd, ShowWindowCommands.MINIMIZE);
    
            anim.iMinAnimate = 1;
            SystemParametersInfo(SPI_SETANIMATION, Marshal.SizeOf(anim), anim, 0);
        }
        else
            ShowWindow(hWnd, ShowWindowCommands.MINIMIZE);
    }
    

    【讨论】:

    • 在 Old New Thing 博客上一般称为“使用全局设置解决本地问题”,通常frowned upon
    • 奇怪的是,即使我使用这个全局解决方案,动画仍然显示:(
    • @RemyLebeau - 我不反对这个答案,但它也不适合我。唯一对我有用的解决方案是:addictivetips.com/windows-tips/…,但显然我需要以编程方式完成。我开始认为这可能是我的环境(VirtualBox vm)的问题
    • @JonathanPotter 实际上,在他编辑答案之前,我就已经熟悉 SystemParametersInfo 的签名。我刚刚为我的操作系统安装了一个服务包,并且 SystemParametersInfo 方法现在可以工作,但是 DwmSetWindowAttribute 仍然不起作用。
    • @AhmedOsama 显然与SPI_SETANIMATION 相同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 2023-03-13
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多