为什么在屏幕保护程序运行时无法呈现弹出窗口?

时间:2017-06-19 07:16:18

标签: c# .net wpf windows

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

我的意思是当屏幕保护程序运行时,弹出窗口会出现查看问题。如果屏幕保护程序没有运行,弹出窗口将正常工作。 enter image description here

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

我想出了一条直接解决的途径,即在ShowDialog窗口之前中断屏幕保护程序。这些方法包括如下,

  • 一个。移动鼠标(使用user32的mouse_event api)
  • 湾发送密钥(也使用user32的api)
  • ℃。杀死屏幕保护程序。
  • d。升级到Framework to 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

我放弃了这种中断屏幕保护的方式,我希望看看另一个关键点来解决这个问题,但我不知道应该关注哪部分代码。对我有什么建议吗?提前谢谢。我根据原始项目的这部分逻辑写了一个如下的演示,

主窗口代码

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();
        }
    }
}

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

1 个答案:

答案 0 :(得分:0)

您可以通过使用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