Reputation: 10333
I'm trying to replicate the Aero Snap functionality for an explorer window I'm starting via Process.Start()
. I use MoveWindow
for that and while the explorer starts, I'm unable to get the resizing to work with any application. The function itself returns false, and Marshal.GetLastWin32Error()
returns 1400 (Invalid Window Handle).
MoveWindow declaration:
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
Usage:
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();
I already tried casting the x/y/width/height parameters to UInt32
because I read on pinvoke.net there may be errors with computed values (like the division I do), but that didn't help either. The explorer.Handle
seems to be valid, while explorer.MainWindowHandle
is always 0. Is there anything wrong with my code? I also tried SetWindowPos
, but that has the same issue (Invalid Window handle).
Another way I tried was with 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();
}
}
While this seems not to cause errors, the values for Left/Top/Width/Height simply stay on the old values. I'm on Windows 8.1 x64 and .Net 4.0 if that's relevant.
Upvotes: 0
Views: 1908
Reputation: 612884
For a start, you are treating Process.Handle
as though it were a window handle. It is not. It is a process handle. In any case, I don't think you will get very far with this approach. There's no guarantee that the process you start will own the new window.
I think you need to use SetWindowsHookEx
hook with WH_SHELL
or RegisterShellHookWindow
. Either of these This will give you notification of when the top-level shell window is created, and what its handle is. At that point you can move the window around because you actually have its handle.
As an aside, let me comment that you should only ever check the last error if the documentation tells you to. And for MoveWindow
that is when MoveWindow
returns false. Please don't ignore the return values of Win32 API functions.
Upvotes: 2