有没有办法刷新/更新Win Forms应用程序中的Screen对象?

问题描述 投票:0回答:1

有没有办法更新

Screen
对象?备注:屏幕对象如
(Screen s in Screen.AllScreens)

如果缩放或其他属性改变,对象不会改变。非常详细的分析可以在这里找到:Windows Screens.AllScreens在切换主显示后不更新

在评论中,看起来发送广播

PostMessage((IntPtr)HWND_BROADCAST, WM_DISPLAYCHANGE, UIntPtr.Zero, IntPtr.Zero)
会导致屏幕对象更新。

我已经尝试过,但我的屏幕对象没有更新。有没有办法强制更新?

问题是缓存静态字段在所有情况下都不能正确“清空”。

public unsafe static Screen[] AllScreens
{
  get
      {
        if (s_screens is null)
           {
              if (s_multiMonitorSupport)

实际上发送请求应该清空缓存

private static void OnDisplaySettingsChanging(object? sender, EventArgs e)
{
    // Now that we've responded to this event, we don't need it again until
    // someone re-queries. We will re-add the event at that time.
    SystemEvents.DisplaySettingsChanging -= new EventHandler(OnDisplaySettingsChanging);

    // Display settings changed, so the set of screens we have is invalid.
    s_screens = null;
}
c# winforms winapi
1个回答
0
投票

感谢几个人的帮助(评论),我有一个(当前)有效的解决方案。

对我来说最有效的是调用 screen 的 private(!) 方法,该方法在事件发生时调用(但不会在所有真正需要更新的事件中调用)。不用说这是一个黑客。

MethodInfo? method = typeof(Screen).GetMethod("OnDisplaySettingsChanging", BindingFlags.Static | BindingFlags.NonPublic);
Debug.Assert(method != null, "Method OnDisplaySettingsChanging not found");
method.Invoke(obj: null, parameters: new object[] { "dummy object", EventArgs.Empty });

发送

WM_DISPLAYCHANGE
的广播也可以,但对我来说不太可靠。它是异步的,我必须等到更改首先发生。此外,我还强制其他应用程序中的许多 Screen 对象进行更新(副作用???)。

SM的完整示例在这里:https://pastebin.com/raw/4DBXthUS

在另一个问题中Windows Screens.AllScreens在切换主显示器后不会更新它也有这个评论,所以如果继续

PostMessage(HWND_BROADCAST, WM_DISPLAYCHANGE, IntPtr.Zero, IntPtr.Zero);
               

使用可能会更好

SendMessageTimeout()

它是发送消息,这使得使用 SendMessageTimeout() 而不是 PostMessage() 合适。 – 汉斯·帕桑特

再次感谢您的帮助。

© www.soinside.com 2019 - 2024. All rights reserved.