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,如果相关的话。

MoveWindow返回“无效窗口句柄”

首先,您将Process.Handle视为一个窗口句柄。事实并非如此。它是一个进程句柄。在任何情况下,我认为你用这种方法不会走得太远。不能保证您启动的进程将拥有新窗口。

我认为你需要使用SetWindowsHookEx钩子与WH_SHELLRegisterShellHookWindow。这两种方法中的任何一种都会通知您何时创建了顶级shell窗口,以及它的句柄是什么。此时,你可以移动窗口,因为你实际上有它的句柄。

作为题外话,让我注释一下,只有在文档告诉您检查最后一个错误时才应该检查。对于MoveWindow,这是MoveWindow返回false的时候。请不要忽略Win32 API函数的返回值