【问题标题】:Stopping Scroll Bar Fade in Vista (.NET or WinAPI)在 Vista 中停止滚动条淡入淡出(.NET 或 WinAPI)
【发布时间】:2009-02-18 17:18:04
【问题描述】:

有没有人知道有什么方法可以抑制滚动条上的 Vista 淡入淡出动画?

我只想暂时这样做,我不认为子类化是一个选项,因为滚动条是由自动滚动功能生成的“自动”滚动条(它是一个 .NET 应用程序,但我认为互操作是必需的) .

我想这样做的原因是因为控件的内容可以(并且将会)改变并导致垂直滚动条被自动隐藏。但是 - 这是让我发疯的部分 - 如果用户在最后 1-2 秒内将鼠标悬停在滚动条上并且动画仍在进行中,则滚动条隐藏但动画仍然继续并留下幽灵图像,因此 SB 似乎仍然存在,即使它确实不存在(无法单击它,并且最小化/恢复表单使其完全消失)。

我认为 Vista 使用某种计时器来制作此动画,并希望可能有一些新的 API 来停止计时器(不幸的是,Google 对此没有帮助)。或者,如果其他人遇到过这个问题并且知道另一种解决方法,那也很好。

提前致谢,
亚伦

【问题讨论】:

  • 我最好的建议是用 MS 记录一个错误。

标签: .net winforms windows-vista scrollbar


【解决方案1】:

这篇文章中的解决方法对我有用:

http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/88abdb31-651b-4b47-ae24-8b923344c349

帖子中的示例使用 C++,但这里有一些 C# 代码说明了我如何通过 pinvoke 在 .NET 中使用它(在 Control 子类中工作...)

protected override void OnSizeChanged(EventArgs e)
{
    if (_vScrollVisible != VerticalScroll.Visible)
    {
        _vScrollVisible = VerticalScroll.Visible;

        if (!_vScrollVisible)
        {

            if (NativeMethods.IsThemeActive())
            {
                // Fix scrollbar fade issue                
                NativeMethods.SetWindowTheme(Handle, null, null);
            }
        }
    }
}

internal static class NativeMethods
{      
    [DllImport("uxtheme.dll", CharSet = CharSet.Unicode)]
    public static extern bool IsThemeActive();

    [DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
    public static extern int SetWindowTheme(IntPtr hWnd, String pszSubAppName, String pszSubIdList);
}

【讨论】:

    【解决方案2】:

    这是一个我也想知道的效果。

    我编写了一个从 ContainerControl 派生的控件,其中子控件可以通过用户交互来增长或缩小。所以我花了一些时间设置自己的 LayoutEngine 来获取子控件所需的布局。但即使是这个动画不间断的 SB 也是肮脏的。我有一个解决方法 - 请不要将其作为解决方案 - 在布局方法中,我在进行布局之前将焦点设置在容器控件上。这对我有用...

    rp

    另一种解决方法...

    is to inherit from the ScrollableControl (Panel, ...) and to
    

    覆盖 WndProc 方法并使用 PreventScrollAnimation 方法。 这将吃掉所有在滚动条中有命中测试的 WM_NCMOUSEMOVE 消息。 所以这将防止内部开始滚动条的褪色。 顺便说一句,衰落是在 VISTA-UI 中使用计时器回调实现的,所以有 没有可能阻止它。

    const int WM_NCMOUSEMOVE = 160;
    const int HTHSCROLL = 6;
    const int HTVSCROLL = 7;
    
    bool PreventScrollAnimation(ref Message m)
    {
        if (m.Msg == WM_NCMOUSEMOVE)
        {
            if ((m.WParam.ToInt32() == HTHSCROLL) ||
                (m.WParam.ToInt32() == HTVSCROLL))
            {
                m.Result = IntPtr.Zero;
                return true;
            }
        }
        return false;
    }
    
    protected override void WndProc(ref Message m)
    {
        if (PreventScrollAnimation(ref m))
            return;
    
        base.WndProc(ref m);
    }
    

    【讨论】:

      【解决方案3】:

      有任何理由有滚动条吗?您可以在不使用任何 Win32 API 技巧的情况下关闭它们,同时还可以设置窗口大小以适当地处理动画(或缩放动画)。

      我认为您唯一的其他选择是滚动您自己的 Window 对象,这将是一种皇家痛苦。

      【讨论】:

      • 内容过多,无法在不滚动的情况下放入表单。将大内容限制在其自己的滚动框中并不好,因为它最终会成为一个非常小的可用区域。考虑一个带有长页眉/页脚的报表 - 您通常希望滚动整个报表,而不仅仅是正文。
      【解决方案4】:

      如果您指的是应用程序或系统范围内的滚动条,这个问题并没有完全清楚。如果您指的是系统范围,那么除了为您的整个计算机设计一个全新的主题之外,我不确定您还能做什么。但是,如果您指的是仅更改您自己的应用程序,则可以使用 WPF 控件模板修改滚动条行为以执行您所描述的操作。

      如果您有 Expression Blend,这很容易做到,因为它可以创建默认滚动条的副本,您可以根据自己的喜好进行修改(例如在这种情况下将淡入淡出的时间更改为零)。 This link 并不完全是您要寻找的东西,但它应该让您了解可能涉及的内容。

      如果您没有 Expression Blend,仍然可以手动编写相同的代码,因为它只是 XAML 文本(即使 Blend 生成它),但需要更多的努力来学习如何做到这一点方式。

      Windows Presentation Foundation Unleashed 的第 15 章(出于多种原因的一本好书)解释了如何在 Win32 和 Windows 窗体应用程序中以及如何将 WPF 用作 Win32 和 Windows 窗体应用程序的主机,如果您无法将整个应用移植到 WPF,但仍希望有选择地使用某些 WPF 功能。

      【讨论】:

      • 它只是在应用程序中,特别是在一个控件中;它在另一个控件中自动调整大小,但是如果父滚动条位于动画中间,它不会消失。它也是一个 Winforms 2.0 应用程序 - 没有 WPF - 可能会调查嵌入。
      猜你喜欢
      • 2010-12-11
      • 2011-02-17
      • 1970-01-01
      • 2021-02-14
      • 1970-01-01
      • 2019-01-01
      • 2013-07-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多