2014-06-12 226 views
0

我想通过Process.Start()开始为资源管理器窗口复制Aero捕捉功能。我使用MoveWindow作为那个,而当浏览器启动时,我无法调整大小与任何应用程序一起使用。该函数本身返回false,并且Marshal.GetLastWin32Error()返回1400(无效窗口句柄)。MoveWindow返回“无效的窗口句柄”

的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(); 
} 
} 

虽然这看起来不会造成错误,左/顶/宽/高值仅仅停留在旧的价值观念。如果这是相关的,我在Windows 8.1 x64和.Net 4.0上。

+0

你在正确的轨道上。你不能使用'explorer.Handle',因为它给你一个进程句柄,而不是一个窗口句柄。当您使用calc.exe或notepad.exe进行尝试时,可以使用'explorer.MainWindowHandle'。但资源管理器有点特别,恐怕你不得不诉诸[枚举所有窗口](http://stackoverflow.com/a/79205/1029287)。 – void

+0

可能无关紧要,但是当我运行代码时,在任务管理器中看到的Explorer的进程句柄与我在Process.Handle上运行“GetProcessId”时获得的进程句柄不匹配。有时候句柄是32,并且在任务管理器中出现名为“COM Surrogate”的pid 32。有时候,句柄与任务管理器中看到的很接近,但略有不同。在explorer.Start'大约一秒钟内,即使浏览器窗口仍处于打开状态,explorer.HasExited也会返回true。 Explorer能否产生一个临时的中间进程来启动实际的Explorer进程? – pmcoltrane

+0

@pmcoltrane的确如此。在资源管理器中的一个选项是运行所有浏览器窗口出相同的过程。 –

回答

2

首先,您将Process.Handle视为窗口句柄。不是这样。它是一个流程句柄。无论如何,我认为你不会采用这种方法。无法保证您开始的流程将拥有新窗口。

我认为你需要使用SetWindowsHookEx挂钩WH_SHELLRegisterShellHookWindow。这两者中的任何一个都会告诉您何时创建顶级shell窗口以及它的句柄是什么。此时你可以移动窗口,因为你实际上有它的手柄。

另外,让我评论一下,如果文档告诉你,你应该只检查最后一个错误。而对于MoveWindowMoveWindow返回false。请不要忽略Win32 API函数的返回值。

+0

+1对'请不要忽略Win32 API函数的返回值 – gustavodidomenico