監聽webbrowser內容改變
阿新 • • 發佈:2018-11-22
論壇上一位朋友發貼想實現這樣功能:在webbrowser(編輯狀態)中輸入@,然後能捕獲隨後輸入的幾個字元。貼子見:
https://bbs.csdn.net/topics/390995682?page=1#post-403542646
監聽鍵盤事件有兩個缺陷:
1.它只能監聽到ASCII字元,如果輸入漢字則不響應。
2.事件發生時,字元還未真正出現在webbrowser中。
解決方法首先是實現IHTMLChangeSink介面,這樣webbrowser中內容一發生改變,我們立刻就能收到通知。
需要引用mshtml,引用該dll的方法及注意事項:
https://blog.csdn.net/drupe/article/details/45845181
主要程式碼:
using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApplication1 { public class Monitor : mshtml.IHTMLChangeSink { // for monitor htmleditor textchanged private Guid IMarkupContainer2GUID = typeof(mshtml.IMarkupContainer2).GUID; private uint cookie = 0; private mshtml.IMarkupContainer2 markupContainer; private WebBrowser webBrowser; // Event public event EventHandler HtmlEditorEvent; public Monitor(WebBrowser webControl) { this.webBrowser= webControl; } #region For HtmlEditor TextChanged // always monitor private mshtml.IMarkupContainer2 GetMarkupContainer() { object oDocument = this.webBrowser.Document.DomDocument; IntPtr pDocument = Marshal.GetIUnknownForObject(oDocument); IntPtr pMarkupContainer = IntPtr.Zero; // pMarkupContainer is different after a call to Navigate or designMode Marshal.QueryInterface(pDocument, ref IMarkupContainer2GUID, out pMarkupContainer); //object oMarkupContainer = Marshal.GetObjectForIUnknown(pMarkupContainer); // This does not work object oMarkupContainer = Marshal.GetUniqueObjectForIUnknown(pMarkupContainer); Marshal.Release(pDocument); Marshal.Release(pMarkupContainer); return (mshtml.IMarkupContainer2)oMarkupContainer; } // only one monitor private mshtml.IMarkupContainer2 GetMarkupContainer2() { return (mshtml.IMarkupContainer2)this.webBrowser.Document.DomDocument; } public void MonitorTextChangedAlways() { this.markupContainer = GetMarkupContainer(); this.markupContainer.RegisterForDirtyRange((mshtml.IHTMLChangeSink)this, out this.cookie); } public void StopMonitorTextChanged() { if (this.markupContainer != null) { this.markupContainer.UnRegisterForDirtyRange(this.cookie); } } #endregion #region Implement Interface public void Notify() { //觸發改變事件外界去接受 if (this.HtmlEditorEvent != null) { this.HtmlEditorEvent(this,new EventArgs()); } } #endregion } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using mshtml; namespace WindowsFormsApplication1 { public partial class Form1 : Form { IHTMLDocument2 document; Monitor m = null; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { webBrowser1.DocumentText = string.Empty; webBrowser1.Document.ExecCommand("EditMode", false, null); webBrowser1.Document.ExecCommand("LiveResize", false, null); this.FormClosing += Form1_FormClosing; document = (IHTMLDocument2)webBrowser1.Document.DomDocument; m = new Monitor(webBrowser1); m.HtmlEditorEvent += m_HtmlEditorEvent; m.MonitorTextChangedAlways(); } void Form1_FormClosing(object sender, FormClosingEventArgs e) { m.StopMonitorTextChanged(); } void m_HtmlEditorEvent(object sender, EventArgs e) { IHTMLTxtRange searchRange = (IHTMLTxtRange)document.selection.createRange(); searchRange.collapse(true); searchRange.moveStart("character", -5);//長度可調整 String t = searchRange.text; if (t != null) { int i = t.IndexOf('@'); if (i >= 0) { this.textBox1.Text = t.Substring(i + 1); } } } } }