【发布时间】:2014-08-02 18:19:53
【问题描述】:
我正在尝试为通过Process.Start() 启动的资源管理器窗口复制 Aero Snap 功能。我为此使用MoveWindow,当资源管理器启动时,我无法调整大小以与 any 应用程序一起使用。函数本身返回 false,Marshal.GetLastWin32Error() 返回 1400(无效窗口句柄)。
MoveWindow 声明:
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
用法:
Process explorer = new Process
{
StartInfo =
{
FileName = "explorer.exe",
Arguments = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),
UseShellExecute = false
}
};
explorer.Start();
// returns false
var return = NativeDeclarations.MoveWindow(
explorer.Handle,
SystemParameters.WorkArea.Left.ToInt32(),
SystemParameters.WorkArea.Top.ToInt32(),
(SystemParameters.WorkArea.Width/2).ToInt32(),
SystemParameters.WorkArea.Height.ToInt32(),
true);
// returns 1400
var err = Marshal.GetLastWin32Error();
我已经尝试将 x/y/width/height 参数转换为UInt32,因为我在 pinvoke.net 上看到计算值可能存在错误(就像我做的除法一样),但这也没有帮助。 explorer.Handle 似乎有效,而 explorer.MainWindowHandle 始终为 0。我的代码有什么问题吗?我也试过SetWindowPos,但也有同样的问题(无效的窗口句柄)。
我尝试的另一种方法是使用 SHDocVw:
string filename;
foreach (SHDocVw.InternetExplorer window in new SHDocVw.ShellWindows())
{
filename = Path.GetFileNameWithoutExtension(window.FullName).ToLower();
if (filename.ToLowerInvariant() == "explorer")
{
window.Left = SystemParameters.WorkArea.Left.ToInt32();
window.Top = SystemParameters.WorkArea.Top.ToInt32();
window.Width = (SystemParameters.WorkArea.Width / 2).ToInt32();
window.Height = SystemParameters.WorkArea.Height.ToInt32();
}
}
虽然这似乎不会导致错误,但 Left/Top/Width/Height 的值只是保持旧值不变。如果相关,我使用的是 Windows 8.1 x64 和 .Net 4.0。
【问题讨论】:
-
你走在正确的轨道上。您不能使用
explorer.Handle,因为它为您提供了进程句柄,而不是窗口句柄。explorer.MainWindowHandle在您尝试使用 calc.exe 或 notepad.exe 时有效。不过explorer有点特殊,恐怕得求助enumerating all windows了。 -
可能无关紧要,但是当我运行代码时,在任务管理器中看到的 Explorer 的进程句柄与我在 Process.Handle 上运行
GetProcessId时得到的进程句柄不匹配。有时句柄是 32,任务管理器中会出现一个名为“COM Surrogate”的 pid 32。有时,句柄与任务管理器中的句柄很接近,但略有不同。在explorer.Start的大约一秒钟内,explorer.HasExited会返回 true,即使资源管理器窗口仍处于打开状态。 explorer 是否会产生一个临时的中间进程来启动实际的 Explorer 进程? -
@pmcoltrane 确实如此。资源管理器中的选项之一是在同一个进程中运行所有资源管理器窗口。