【问题标题】:Why can't rendering for pop-up window when screen-saver running?为什么屏幕保护程序运行时无法渲染弹出窗口?
【发布时间】:2017-06-19 07:16:18
【问题描述】:

我维护了一个使用WPF框架编写的系统,出现了一个很奇怪的场景,当屏幕保护程序运行时,一个窗口使用ShowDialog通过定时器对象弹出一个窗口,这个弹出窗口不会出现任何文本、按钮和另一个控件,它的整个视图都是空白的。但如果屏幕保护程序不运行,弹出窗口将起作用。

我的意思是当屏幕保护程序运行时弹出窗口会有视图问题。如果屏幕保护程序没有运行,弹出窗口将正常工作。

这个问题在我的本地开发环境中无法重现。它针对特定的 PC(Windows 8.1 嵌入式版本)运行

我想出了一个直接解决的途径,就是在ShowDialog窗口之前中断屏保。这些方法包括如下,

  • 一个。移动鼠标(使用 user32 的 mouse_event api)
  • 乙。发送密钥(也使用了user32的api)
  • c。终止屏幕保护程序。
  • d.升级到 Framework 到 4.6.2

以上方式参考以上链接,所有这些方式都可以在我的本地(Windows 10)上运行良好,但确实不适用于该特定PC(Windows 8.1嵌入式版本)。 https://www.codeproject.com/Articles/17067/Controlling-The-Screen-Saver-With-C

https://support.microsoft.com/en-us/help/140723/how-to-force-a-screen-saver-to-close-once-started-in-windows-nt,-windows-2000,-and-windows-server-2003

How to interrupt Screen-saver under windows 8

我已经放弃了这种中断屏保的方式,希望再看一个关键点来解决这个问题,但是不知道应该把重点放在代码的哪一部分。对我有什么建议吗?提前致谢。我按照原项目这部分的逻辑写了一个demo如下,

主窗口代码

using OutdoorCentral.WPF.UI;
using System;
using System.Configuration;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Input;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private static object inactivityLockObject = "InactivityLockObject";
        protected delegate void func();
        private static Timer checkActivityTimer;
        public MessageDialog msg = new MessageDialog();

        public enum MessageWindowType
        {
            OK,
            OKCancel,
            YesNo,
            YesNoCancel
        }

        public MainWindow()
        {
            InitializeComponent();
            this.Title = "test";
            AutoResetEvent autoResetEvent = new AutoResetEvent(false);
            checkActivityTimer = new Timer(CheckActivityCallback, autoResetEvent, new TimeSpan(0, 2, 0), new TimeSpan(0, 2, 0));
        }

        private void CheckActivityCallback(object stateInfo)
        {
            CheckActivity();
        }

        private void CheckActivity()
        {
            lock (inactivityLockObject)
            {
                InvokeOnUiThread(ForceLogout);
            }
        }

        protected void InvokeOnUiThread(func method)
        {
            Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, method);
        }

        private void ForceLogout()
        {
            checkActivityTimer.Dispose();
            msg.TitleLabel.Content = Title;
            msg.Topmost = true;
            msg.Message = "test focus on message missed";
            msg.MessageWindowType = MessageWindowType.OK;
            msg.ShowDialog();
        }
    }
}

弹窗代码如下

using System.Diagnostics;
using Microsoft.Win32;
using System.Windows;
using System;
using System.Threading;
using System.Runtime.InteropServices;
using WpfApplication1;
using static WpfApplication1.MainWindow;

namespace OutdoorCentral.WPF.UI
{
    /// <summary>
    /// Interaction logic for MessageDialog.xaml
    /// </summary>
    public partial class MessageDialog : Window
    {
        public MessageDialog()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(MessageDialog_Loaded);
        }

        public bool? MessageResult { get; set; }

        void MessageDialog_Loaded(object sender, RoutedEventArgs e)
        {
            SetWindowType();
        }

        new string Title
        {
            get { return TitleLabel.Content.ToString(); }
            set { TitleLabel.Content = value; }
        }

        public string Message
        {
            get { return MessageText.Text; }
            set { MessageText.Text = value; }
        }

        private MessageWindowType messageWindowType;
        public MessageWindowType MessageWindowType
        {
            get { return messageWindowType; }
            set
            {
                messageWindowType = value;
                SetWindowType();
            }
        }

        private void SetWindowType()
        {
            switch (MessageWindowType)
            {
                case MessageWindowType.OKCancel:
                    CancelButton.Visibility = Visibility.Visible;
                    break;
                case MessageWindowType.YesNo:
                    OKButton.Content = "Yes";
                    NoButton.Visibility = Visibility.Visible;
                    break;
                case MessageWindowType.YesNoCancel:
                    OKButton.Content = "Yes";
                    CancelButton.Visibility = Visibility.Visible;
                    NoButton.Visibility = Visibility.Visible;
                    break;
            }
        }

        private void Done(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
            MessageResult = true;
        }

        private void NoSelection(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
            MessageResult = false;
        }

        public void Canceled(object sender, RoutedEventArgs e)
        {
            MessageResult = null;
            this.Close();
        }

        private void Window_LostFocus(object sender, RoutedEventArgs e)
        {
            this.Focus();
        }
    }
}

实际上,下面的代码很简单,请给我一些建议。提前致谢。

【问题讨论】:

  • 你用过谷歌翻译吗?我发现您的问题几乎无法阅读。
  • 谢谢你的回复,我又修改了描述,你能再看看吗?
  • 看到这个,可能是相关的:codeproject.com/Answers/187206/…
  • 我看过这个链接,它主要关注 PowerModeChanged 事件,但不适用于我的问题

标签: c# .net wpf windows


【解决方案1】:

您可以尝试通过使用 SPI_GETSCREENSAVERRUNNING 参数查询 SystemParametersInfo() 来检查屏幕保护程序是否正在运行(因为据我所知,没有任何类似“屏幕保护程序开/关”的事件)。因此,一旦您检测到屏幕保护程序处于活动状态,您就可以推迟任何弹出窗口,直到屏幕保护程序关闭。

[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int SystemParametersInfo(int uAction, int uParam, ref int lpvParam, int fuWinIni);

const int SPI_GETSCREENSAVERRUNNING = 114;
int screenSaverRunning = -1;

// is the screen saver running?

int ok = SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, ref screenSaverRunning, 0);

if (ok == 0)
{
    Console.WriteLine("Call to SystemParametersInfo failed.");
}

if (screenSaverRunning != 0)
{
    // screen saver is running
    ... do something ...
}
else
{
    // screen saver is NOT running
    ... do other thing ...
}

原文链接:https://bytes.com/topic/c-sharp/answers/261540-detecting-screensaver-state

【讨论】:

  • 首先谢谢。我也看到了这个链接,但不适用于 Windows 10
  • 希望有更多高手解答这个问题,需要各位大神帮忙,谢谢
  • 有人回答我吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-29
  • 2018-07-02
  • 1970-01-01
相关资源
最近更新 更多