【问题标题】:C# How to make hidden window keep repainting and be ready to fast show?C#如何使隐藏窗口不断重绘并准备好快速显示?
【发布时间】:2017-02-27 21:11:17
【问题描述】:

我有一个窗口,大部分时间都是隐藏的。用户有时通过全局热键显示它,他希望它很快变得可见。但是窗口有很多控件,每个隐藏->可见的转换都会调用完整的窗口重绘。在慢速 CPU 上,这是非常明显的。我想让这个窗口即使在隐藏状态下也总是被绘制。那么我认为展示它需要很短的时间。

【问题讨论】:

  • 我希望我的窗口看起来非常快,就像它在后台一样,我只需调用 SetForegroundWindow。
  • 还有一件重要的事情是我需要在窗口隐藏上隐藏任务栏图标并在窗口显示上显示它
  • 我做了一些复杂棘手的解决方案。我很快就会在这里描述它。
  • 1.处理系统事件“活动窗口更改”以始终知道其句柄。让它成为变量lastActiveWindow。 2. 在 FormClosing 事件
     if (lastActiveWindow != null) lastActSet = SetForegroundWindow(lastActiveWindow); if (!lastActSet) SetActiveWindow(IntPtr.Zero); this.Top = -this.Height; e.Cancel = true;code
  • 我真的试图信守承诺并在之前的评论中描述解决方案。但是难以克服的标记、5 分钟的版本评论时间和最大长度太难以克服。所以非常简短的解决方案是将窗口移到屏幕外而不是关闭并在激活时将其移回。调试起来很困难,但它工作得非常快。负面影响是窗口需要始终显示在任务栏中,否则它将随着任务栏图标的出现而重新绘制。您可以在 Main form sourceforge.net/p/clip-angel/code 的源代码中找到它

标签: c# window hidden repaint


【解决方案1】:

更新

我不确定你看到了什么。我看到并觉得烦人的是,当 ClipAngel 的表单显示在与隐藏的不同的位置时(根据您的定位逻辑),我可以在旧位置看到表单的“闪烁”。 AFAIU 这是由您的应用程序本身完成的,但由 DWM(桌面窗口管理器)完成,根据 Raymond Chen,您可以使用 DwmSetWindowAttributeDWMWA_TRANSITIONS_FORCEDISABLED 为您禁用它

    private const int DWMWA_TRANSITIONS_FORCEDISABLED = 3;
    private const int S_OK = 0;

    [DllImport("dwmapi", PreserveSig = true)]
    static extern int DwmSetWindowAttribute(IntPtr hWnd, int attr, ref int value, int attrLen);

    private void ShowForPaste()
    {
        if (Environment.OSVersion.Version.Major >= 6)
        {
            int boolForceDisable = 1;
            int hresult = DwmSetWindowAttribute(this.Handle, DWMWA_TRANSITIONS_FORCEDISABLED, ref boolForceDisable, Marshal.SizeOf(boolForceDisable));

            if (S_OK != hresult)
            {
                // log somewhere?
            }
        }
        ...

另请注意,当我在配置了 16 位颜色的机器上尝试此 hack 时,由于某种原因它没有帮助,DwmIsCompositionEnabled 总是返回 false。


旧答案

为什么你有很多“隐藏->可见的过渡”?另外我认为双缓冲可能会对您有所帮助,请参阅Winforms Double Buffering

【讨论】:

  • 用户在某些情况下按下全局热键。通常在它之前窗口是隐藏的,所以调用 Show() 方法,这就是我所说的“隐藏->可见转换”。 “Winforms 双缓冲”我试过了,但在 hide() show() 之后没有永远绘制窗口内容。
  • 我了解“隐藏->可见过渡”的来源,但您提到问题是其中有很多,因此一切都很慢。另外我想提一下,在引用的答案中使用了WS_EX_COMPOSITED,它不能直接从 WinForms 访问,所以你可能还没有尝试过。
  • 每次显示窗口时,只有一个“隐藏->可见过渡”发生,即使在快速 CPU 上,我也可以看到一点延迟和绘画。关于 WS_EX_COMPOSITED。我添加到我的表单类受保护的覆盖 CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= 0x02000000; // 开启 WS_EX_COMPOSITED return cp; } }
  • 那么您可能需要向我们展示一些代码并创建 Minimal, Complete, and Verifiable example 。也许你只是在你的 UI 线程上做了一些需要太长时间的坏事。或者你的表格可能很大。或者你太细心了。
  • 使用源代码sourceforge.net/p/clip-angel/code/ci/master/tree VS 2015 编译、运行,同时(不相信){关闭窗口,按 ALT+V}。使用 exe sourceforge.net/projects/clip-angel 运行,同时(不相信){关闭窗口,按 ALT+V}
【解决方案2】:

我做了一些复杂棘手的解决方案。简而言之,解决方案是将窗口移到屏幕外(TOP = -10000),而不是关闭并最小化并在激活时将其移回。它的工作速度非常快。负面影响是窗口需要始终在任务栏中显示/隐藏,否则窗口将在每个隐藏的任务栏图标上重新绘制 - >显示更改。 您可以在 Main.WndProc、Main_Closing、Main_Activated、Main_Deactivate、ShowForPaste、RestoreWindowIfMinimized 方法的 Main form http://sourceforge.net/p/clip-angel/code 的源代码中找到它

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多