项目中要实现一个功能,就是qq的@功能,在获取文本上遇到一些问题,希望各位恩那个帮忙给些思路:下面是qq的效果:
技术背景:
这是一个WinForm客户端项目
输入框是使用WebBrowser,直接让wb控件处于编辑状态然后进行编辑,然后当用户输入@的时候弹出一个用户列表控件,我现在需要对用户列表进行模糊搜索,需要得到用户在输入@之后用户输入的文本内容。本人不才遇到以下问题:
不知如何能获取当用户输入@之后的文本内容,而且可能完成了一个@之后还有@其他人的情况
wb控件里面直接编辑得到的html大概是<font>文本内容</font> 并没有标签id之类的内容
上面忘记说我是在wb控件的PreviewKeyDown事件里面处理的
想请教下各位大侠,我如何在获得@之后输入的内容呢,不管是用win32的钩子还是html js之类的方案都可以接受,
如上图,如果只有一个@ 基本没有问题,我是直接获取整个wb控件的所有内容,然后去掉html标签与@文字但如图如果已经存在了文本 我再输入@然后使用上图的方法获取文本就不对了
大家帮帮忙给点建议,我需要获取wb控件中每次输入@之后紧跟着的文本内容
谢谢

解决方案 »

  1.   

    试试在内容change事件里触发,找到光标位置(可能部需要),判断新输入内容(之前输入的词组),然后以此为基础弹出你的匹配列表,或变换列表的匹配内容。
      

  2.   

    监听键盘事件有两个缺陷: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 upContainer;      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.upContainer = GetMarkupContainer();            this.upContainer.RegisterForDirtyRange((mshtml.IHTMLChangeSink)this, out this.cookie);
            }
            public void StopMonitorTextChanged()
            {
                if (this.upContainer != null)
                {
                    this.upContainer.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);
                    }
                }
            }
        }
    }在任何情况下,只要你输入的字符跟在@后面,立刻就能显示出来。剩下的就好办了吧。