如何在不存储 IntPtr 的情况下获得通过 SetWindowVisualState 最小化的 Process.MainWindowHandle?

问题描述

我正在尝试制作一个检测其他窗口的程序,将窗口最小化一小段时间,然后从另一个程序中使同一窗口正常。

最小化很容易(为了让代码简洁,我没有错误处理):

var p = Process.GetProcessesByName("MyTargetwindow").GetFirstOrDefault();
var elem = AutomationElement.FromHandle(p.MainWindowHandle);
var pattern = elem.GetCurrentPattern(WindowPattern.Pattern) as WindowPattern;
pattern.SetwindowVisualState(WindowVisualState.Minimized);

现在我想通过另一个程序再次使窗口正常大小。

此时,如果我存储 p.MainWindowHandle 并重新使用它,我没有任何问题。

但是,如果我不这样做,并且如果我尝试按照类似的代码运行以使窗口正常,则在调用 GetCurrentPattern 时我将收到 InvalidOperationException。 (我了解新手柄不支持Pattern)

var p = Process.GetProcessesByName("MyTargetwindow").GetFirstOrDefault();
var elem = AutomationElement.FromHandle(p.MainWindowHandle);
var pattern = elem.GetCurrentPattern(WindowPattern.Pattern) as WindowPattern; // InvalidOperationException
pattern.SetwindowVisualState(WindowVisualState.normal);

原因很简单,第二个代码中的p.MainWindowHandle与原来的窗口不同。

问题是为什么 p.MainWindowHandle 不同?

最终,如何在不将句柄存储在变量中的情况下重新检索相同的句柄

编辑:

如果 IntPtr 存储是强制性的,我别无选择,只能将它作为字符串存储在磁盘上,然后通过 new IntPtr(Convert.ToInt32) 重新检索它,我希望会有其他解决方案。

编辑2:

存储 IntPtr 对我来说仍然有问题。最终,我可以将它存储到注册表并读取它,但我还必须跟踪句柄何时存储到注册表。它变得比我想要的更复杂。

我真的很希望有一种方法可以不存储 IntPtr 并且仍然找到正确的句柄。

解决方法

“主窗口是当前具有焦点的进程打开的窗口(TopLevel 窗体)。”但是最小化的窗口不再具有焦点。

在其上保存 IntPtr 和 P/Invoke ShowWindow()。一个简单得多的提议;当你已经可以做到这一点时,没有必要搞乱自动化等。

我不建议在本机代码中重新实现整个“查找窗口句柄”之类的东西的原因是它不会稳定,因为其他进程可以在两次之间创建/销毁窗口,因此您不会无论您做什么,都能可靠地再次抓取同一个窗口。