2014-06-12 137 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