如何在正在執行的“Internet Explorer_Server”實例中控制光學變焦?
Windows Live Writer 擁有一個用於編輯的 Internet Explorer 控制項,但沒有縮放控制項。我希望能夠向它發送縮放命令。由於其他應用程序託管 IE 瀏覽器,我認為可以向特定 IE 瀏覽器實例發送縮放命令的實用程序非常方便,但我還沒有找到。
我已經看到有一個命令OLECMDID_OPTICAL_ZOOM,但我不確定如何將該命令發送給它。理想情況下,我想從 C# 或 Powershell 執行此操作。
注意:問題是關於在我沒有創建的正在執行的應用程序中控制 Web 瀏覽器控制項的縮放,主要範例是 Windows Live Writer 中的編輯器表面。
簡短版本:我不完全確定你能做你想做的事。
我有一些程式碼實際上獲得了 WLW 視窗內 HTML 文件的句柄,並且可以正常工作,但我發現我實際上無法獲得對文件父視窗的引用。我不是 Windows 本地人,但我在我的時間裡做過一些 PInvoke。可能只是我缺乏本地 Windows 知識正在阻止我彌合最後的差距。
根據我的總結,獲取 IE 視窗引用的一般過程是:
- 獲取頂級視窗的參考。
- 在那裡找到包含 HTML 文件的視窗(遞歸搜尋)。
- 從該視窗獲取 HTML 文件對象。
- 獲取 HTML 文件的父視窗(即 IE 視窗)。
擁有該父視窗後,您可以呼叫 IWebBrowser2.ExecWB 方法來執行 OLE 縮放命令。
問題是當您嘗試訪問**IHTMLDocument2.parentWindow 屬性時,它似乎總是拋出 InvalidCastException 。**從我讀過的內容來看,當您嘗試從文件正在執行的執行緒之外的執行緒中獲取父視窗時,這就是交易。
所以,無論如何,我會把獲取 HTML 文件參考的程式碼放在你身上,如果你能在最後一步橋接,你就會得到答案。我只是無法弄清楚自己。
這是一個控制台應用程序。對於 IHTMLDocument2 介面,您需要對 Microsoft.mshtml 的引用。
using System; using System.Runtime.InteropServices; namespace ControlInternetExplorerServer { //////////////////////// // LOTS OF PINVOKE STUFF //////////////////////// [Flags] public enum SendMessageTimeoutFlags : uint { SMTO_NORMAL = 0x0, SMTO_BLOCK = 0x1, SMTO_ABORTIFHUNG = 0x2, SMTO_NOTIMEOUTIFNOTHUNG = 0x8 } public static class NativeMethods { [DllImport("user32.dll", CharSet = CharSet.Unicode)] public static extern IntPtr FindWindow( string lpClassName, string lpWindowName); [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr FindWindowEx( IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetWindow", SetLastError = true)] public static extern IntPtr GetNextWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.U4)] int wFlag); [DllImport("oleacc.dll", PreserveSig = false)] [return: MarshalAs(UnmanagedType.Interface)] public static extern object ObjectFromLresult( IntPtr lResult, [MarshalAs(UnmanagedType.LPStruct)] Guid refiid, IntPtr wParam); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern uint RegisterWindowMessage(string lpString); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern IntPtr SendMessageTimeout( IntPtr windowHandle, uint Msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags flags, uint timeout, out IntPtr result); public static IntPtr FindWindowRecursive(IntPtr parent, string windowClass, string windowCaption) { var found = FindWindowEx(parent, IntPtr.Zero, windowClass, windowCaption); if (found != IntPtr.Zero) { return found; } var child = FindWindowEx(parent, IntPtr.Zero, null, null); while (child != IntPtr.Zero) { found = FindWindowRecursive(child, windowClass, windowCaption); if (found != IntPtr.Zero) { return found; } child = GetNextWindow(child, 2); } return IntPtr.Zero; } } ////////////////////// // THE INTERESTING BIT ////////////////////// public class Program { public static void Main(string[] args) { // First parameter is the class name of the window type - retrieved from Spy++ // Second parameter is the title of the window, which you'll // probably want to take in via command line args or something. var wlwWindow = NativeMethods.FindWindow("WindowsForms10.Window.8.app.0.33c0d9d", "Untitled - Windows Live Writer"); if (wlwWindow == IntPtr.Zero) { Console.WriteLine("Unable to locate WLW window."); return; } // Since you don't know where in the tree it is, you have to recursively // search for the IE window. This will find the first one it comes to; // ostensibly there's only one, right? RIGHT? var ieWindow = NativeMethods.FindWindowRecursive(wlwWindow, "Internet Explorer_Server", null); if (ieWindow == IntPtr.Zero) { Console.WriteLine("Unable to locate IE window."); return; } // Get a handle on the document inside the IE window. IntPtr smResult; var message = NativeMethods.RegisterWindowMessage("WM_HTML_GETOBJECT"); NativeMethods.SendMessageTimeout(ieWindow, message, IntPtr.Zero, IntPtr.Zero, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 1000, out smResult); if (smResult== IntPtr.Zero) { Console.WriteLine("Unable to locate the HTML document object."); } // Cast the document to the appropriate interface. var htmlDoc = (mshtml.IHTMLDocument2)NativeMethods.ObjectFromLresult(smResult, typeof(mshtml.IHTMLDocument2).GUID, IntPtr.Zero); // Here's where you would normally get htmlDoc.parentWindow and call ExecWB // to execute the zoom operation, but htmlDoc.parentWindow throws an InvalidCastException. } } }