我维护了一个使用WPF框架编写的系统,它出现了一个如此奇怪的场景,当屏幕保护程序运行时,一个窗口使用ShowDialog通过计时器对象弹出一个窗口,这个弹出窗口不会出现任何文本,按钮和另一个控件,其整个视图为空白。但是如果屏幕保护程序没有运行,弹出窗口将会起作用。
我的意思是当屏幕保护程序运行时,弹出窗口会出现查看问题。如果屏幕保护程序没有运行,弹出窗口将正常工作。
此问题无法在我的开发环境中本地重现。它是针对特定PC运行的(Windows 8.1嵌入式版本)
我想出了一条直接解决的途径,即在ShowDialog窗口之前中断屏幕保护程序。这些方法包括如下,
以上方式参考上面的链接,所有这些方法都可以在我的本地(Windows 10)中正常工作,但确实不适用于特定的PC(Windows 8.1嵌入式版本)。 https://www.codeproject.com/Articles/17067/Controlling-The-Screen-Saver-With-C
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();
}
}
}
实际上,下面的代码非常简单,请给我一些建议。提前谢谢。
答案 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