Короткая версия: я не совсем уверен, что вы можете делать то, что пытаетесь сделать.
У меня есть некоторый код, который фактически получает указатель на HTML-документ внутриОкно WLW, и это работает, но я обнаружил, что не могу получить ссылку на родительское окно документа.Я не являюсь родным парнем Windows, но я сделал несколько PInvoke в свое время.Возможно, из-за недостатка собственных знаний Windows я не смогу преодолеть этот последний пробел.
Из того, что я собрал, общий процесс получения ссылки на окно IE выглядит так:
- Получить ссылку на окно верхнего уровня.
- Найти там окно, содержащее документ HTML (рекурсивный поиск).
- Получить объект документа HTML из этого окна.
- Получите родительское окно документа HTML (которое является окном IE).
Как только у вас будет это родительское окно, вы можете вызвать метод IWebBrowser2.ExecWB для запуска вашегоКоманда масштабирования OLE.
Проблема состоит в том, что свойство IHTMLDocument2.parentWindow всегда вызывает InvalidCastException при попытке доступа к нему.С что у меня прочитано , вот в чем дело, когда вы пытаетесь получить родительское окно из потока, отличного от того, в котором работает документ.
Такв любом случае, я оставлю на вас код, который получает ссылку на HTML-документ, и если вы сможете преодолеть этот крошечный последний шаг, у вас будет свой ответ.Я просто не мог понять это сам.
Это консольное приложение.Вам понадобится ссылка на Microsoft.mshtml для интерфейса IHTMLDocument2.
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.
}
}
}