2014-06-12 2 views
0

Я пытаюсь реплицировать функциональность 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, если это актуально.

+0

Вы были на правильном пути. Вы не можете использовать 'explorer.Handle', потому что он дает вам дескриптор процесса, а не дескриптор окна. 'explorer.MainWindowHandle' работает, когда вы пытаетесь использовать его с помощью calc.exe или notepad.exe. Но исследователь несколько особенный, боюсь, вам придётся прибегать к [перечислению всех окон] (http://stackoverflow.com/a/79205/1029287). – void

+0

Возможно, не имеет значения, но когда я запускаю код, дескриптор процесса для Explorer, увиденный в диспетчере задач, не соответствует дескриптору процесса, который я получаю при запуске 'GetProcessId' на Process.Handle. Иногда дескриптор 32, а в диспетчере задач появляется pid 32 с именем COM Surrogate. Иногда дескриптор близок, но немного отличается от того, что видно в диспетчере задач. В течение примерно одной секунды из 'explorer.Start'' explorer.HasExited' возвращает true, хотя окно Explorer все еще открыто. Может ли explorer создать временный промежуточный процесс, чтобы запустить фактический процесс Explorer? – pmcoltrane

+0

@pmcoltrane Действительно так. Один из вариантов в проводнике - запустить все окна проводника из одного и того же процесса. –

ответ

2

Для начала вы обрабатываете Process.Handle, как если бы это была ручка окна. Это не. Это дескриптор процесса. В любом случае, я не думаю, что вы очень далеко продвинетесь с этим подходом. Нет никакой гарантии, что процесс, который вы начнете, будет принадлежать новому окну.

Я думаю, вам нужно использовать SetWindowsHookEx крючок с WH_SHELL или RegisterShellHookWindow. Любой из них Это даст вам уведомление о том, когда создается окно оболочки верхнего уровня и каков его дескриптор. В этот момент вы можете перемещать окно вокруг, потому что у вас на самом деле есть его ручка.

В качестве комментария, позвольте мне прокомментировать, что вы должны только когда-либо проверять последнюю ошибку, если в документации вам сообщается. И для MoveWindow, то есть когда MoveWindow возвращает false. Не игнорируйте возвращаемые значения функций API Win32.

+0

+1 для 'Пожалуйста, не игнорируйте возвращаемые значения функций API Win32' – gustavodidomenico

Смежные вопросы