【问题标题】:assigning onmouseover event to my htmldocument is not working将 onmouseover 事件分配给我的 htmldocument 不起作用
【发布时间】:2011-08-28 16:41:50
【问题描述】:

我正在开发一个项目,我正在编写一个 c# windows 应用程序,它希望从正在运行的 Internet Explorer 实例中获取光标下的当前元素。

我可以获得正在运行的 IE 实例的 IHtmlDocument2 的句柄,我想给它分配 onmouseover 事件,如下所示:

 DHTMLEventHandler myHandler = new DHTMLEventHandler(htmlDocument);
 myHandler.Handler += new DHTMLEvent(this.BrowserEventHandler);
 htmlDocument.onmouseover = myHandler;

因为我不希望 IE 吃掉其他事件(一个著名但已解决的问题),我应该创建一个这样的 DHTMLEventHandler 类:

public delegate void DHTMLEvent(IHTMLEventObj obj);

[ComVisible(true)]
public class DHTMLEventHandler
{
    public DHTMLEvent Handler;

    private IHTMLDocument2 Document;

    public DHTMLEventHandler(IHTMLDocument2 doc)
    {
        Document = doc;
    }

    [DispId(0)]
    public void Call()
    {
        Handler(Document.parentWindow.@event);
    }
}

而我的 BrowserEventHandler 方法是这样的:

public void BrowserEventHandler(IHTMLEventObj e)
    {
    }

仍然是空的(但我想获取光标下元素的innerHtml),但这个方法仍然是空的,我得到了:

FindText.exe 中出现“System.InvalidCastException”类型的第一次机会异常

每当我移动鼠标时。

问题:

  1. 为什么会出现此异常?
  2. 是否可以在变量中获取 e.srcElement.innerhtml 并在我的 c# 应用程序中使用?

如果有不清楚和模棱两可的地方,请告诉我。提前感谢您的任何帮助和想法。我非常感谢任何 cmets 和帮助。

更新:

要回答我的第二个问题,似乎可以得到IHTMLEventObj ee.srcElement.innerHTML,但我真的不知道为什么永远不会调用BrowserEventHandler 方法。有什么想法或提示吗?

更新2:

好的,我发现了问题。首先,我更改了项目的一些设置,以获取首先发生异常的行(因为这是第一次机会异常),如下所示:

在 Visual Studio 中:菜单 >> 调试 >> 异常 >> CLR 异常 >> 系统并检查 SystemInvalidCastException 的 throw 选项。

我发现问题出在DHTMLEventHandler 类的这一行:

Handler(Document.parentWindow.@event); 

它抛出Invalid Cast Exception,根据我最近的搜索,我认为它与Threads 相关。

我想我应该将 ApartmentState 设置为 ApartmentState.STA。但我不知道怎么做。有什么想法吗?

【问题讨论】:

    标签: c# ihtmldocument2


    【解决方案1】:

    好的,我找到了解决方案! :)

    我需要像这样更改DHTMLEventHandler 类:

    public delegate void DHTMLEvent(IHTMLEventObj obj);
    
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.AutoDispatch)]
    public class DHTMLEventHandler
    {
        private Thread currentThread;
        public DHTMLEvent Handler;
    
        private IHTMLDocument2 Document;
    
        public DHTMLEventHandler(IHTMLDocument2 doc)
        {
            Document = doc;
        }
    
        [DispId(0)]
         [STAThread]
        public void Call()
        {
            currentThread = Thread.CurrentThread;
           Thread parentWin = new Thread(new ThreadStart(pWindowHandler));
            parentWin.SetApartmentState(ApartmentState.STA);
            parentWin.Start();
            currentThread.Suspend();
           // Handler(Document.parentWindow.@event);
    
        }
        public void pWindowHandler()
        {
            Handler(Document.parentWindow.@event);
            currentThread.Resume();
        }
    }
    

    但是如果其他人尝试使用我的解决方案,我不知道它在其他情况下是否有任何副作用。至少它对我来说很好用! :)

    【讨论】:

    • 感谢卢克发布答案。我试图让它在 VB.NET 中工作并且遇到各种问题。 Call 中使用的线程是 MTA 线程,因此对 VB.NET 无用。我很惊讶它在 C# 中工作。但是我在自动化 IE 的同时进行了这个设置,如果事件是由于我在其他地方的代码而触发的,那么一切都会锁定。我也尝试了你的代码并停止了调用线程,但这是 IE 的线程,所以什么都做不了。
    【解决方案2】:

    【讨论】:

    • 感谢您发布链接(它有一些我以前从未关心过的优点)。但是对于我的问题,我在call 方法中创建了一个新线程,然后将ApartmentState 设置为ApartmentState.STA。当我这样做时,异常消失了,但是对于BrowserEventHandler 中的IHTMLEventObj e,我得到了null(e 为null)。我想我在线程中犯了一个错误,知道吗? (再次感谢您的链接):)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2017-08-13
    • 1970-01-01
    • 2018-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多