MoveWindow返回“无效窗口句柄”
本文关键字:窗口句柄 无效 返回 MoveWindow | 更新日期: 2023-09-27 18:08:31
我试图复制我通过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/宽度/高度参数转换为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,如果相关的话。
首先,您将Process.Handle
视为一个窗口句柄。事实并非如此。它是一个进程句柄。在任何情况下,我认为你用这种方法不会走得太远。不能保证您启动的进程将拥有新窗口。
我认为你需要使用SetWindowsHookEx
钩子与WH_SHELL
或RegisterShellHookWindow
。这两种方法中的任何一种都会通知您何时创建了顶级shell窗口,以及它的句柄是什么。此时,你可以移动窗口,因为你实际上有它的句柄。
作为题外话,让我注释一下,只有在文档告诉您检查最后一个错误时才应该检查。对于MoveWindow
,这是MoveWindow
返回false的时候。请不要忽略Win32 API函数的返回值