我正在尝试复制我通过Process.Start()
启动的资源管理器窗口的Aero Snap功能。我使用MoveWindow
,当资源管理器启动时,我无法调整大小以使用任何应用程序。函数本身返回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。
答案 0 :(得分:2)
首先,您将Process.Handle
视为窗口句柄。它不是。这是一个流程句柄。无论如何,我不认为你会用这种方法走得很远。我们无法保证您启动的流程将拥有新窗口。
我认为您需要使用SetWindowsHookEx
或WH_SHELL
RegisterShellHookWindow
。这些中的任何一个这将为您提供有关何时创建顶级shell窗口及其句柄的通知。此时你可以移动窗口,因为你实际上有它的句柄。
顺便说一句,让我评论一下,如果文档告诉你,你应该只检查最后一个错误。对于MoveWindow
,MoveWindow
返回false。请不要忽略Win32 API函数的返回值。