论坛上一位朋友发贴想实现这样功能:在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);
}
}
}
}
}