Я пытаюсь реплицировать функциональность Aero Snap для окна проводника. Я начинаю с Process.Start()
. Для этого я использую MoveWindow
, и, хотя проводник запускается, я не могу получить изменение размера для работы с любым приложением. Сама функция возвращает false, а Marshal.GetLastWin32Error()
возвращает 1400 (Invalid Window Handle).MoveWindow возвращает «Invalid Window Handle»
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();
Я уже пробовал отливать параметры х/у/ширина/высота для UInt32
, потому что я читал на pinvoke.net там могут быть ошибки с (например, деление, которое я делаю), но это тоже не помогло. explorer.Handle
представляется действительным, а explorer.MainWindowHandle
всегда 0. Есть ли что-то не так с моим кодом? Я также попробовал SetWindowPos
, но имеет ту же проблему (дескриптор Invalid Window).
Другой способ, которым я попытался было с 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();
}
}
Хотя это, кажется, не вызывает ошибки, значения для левого/Top/ширина/высота, просто остаться на старых ценностей. Я в Windows 8.1 x64 и .Net 4.0, если это актуально.
Вы были на правильном пути. Вы не можете использовать 'explorer.Handle', потому что он дает вам дескриптор процесса, а не дескриптор окна. 'explorer.MainWindowHandle' работает, когда вы пытаетесь использовать его с помощью calc.exe или notepad.exe. Но исследователь несколько особенный, боюсь, вам придётся прибегать к [перечислению всех окон] (http://stackoverflow.com/a/79205/1029287). – void
Возможно, не имеет значения, но когда я запускаю код, дескриптор процесса для Explorer, увиденный в диспетчере задач, не соответствует дескриптору процесса, который я получаю при запуске 'GetProcessId' на Process.Handle. Иногда дескриптор 32, а в диспетчере задач появляется pid 32 с именем COM Surrogate. Иногда дескриптор близок, но немного отличается от того, что видно в диспетчере задач. В течение примерно одной секунды из 'explorer.Start'' explorer.HasExited' возвращает true, хотя окно Explorer все еще открыто. Может ли explorer создать временный промежуточный процесс, чтобы запустить фактический процесс Explorer? – pmcoltrane
@pmcoltrane Действительно так. Один из вариантов в проводнике - запустить все окна проводника из одного и того же процесса. –