WPF在自定义文本框中实现输入法跟随光标

本文告诉大家在 WPF 写一个自定义的文本框,如何实现让输入法跟随光标

本文非小白向,本文适合想开发自定义的文本框,从底层开始开发的文本库的伙伴。在开始之前,期望了解了文本库开发的基础知识

本文实现的效果如下

实现

本文的方法参考了 WPF 官方仓库的逻辑,可以在WPF仓库的wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\System\Windows\Documents\ImmComposition.cs文件看到官方是如何让TextBox控件获取输入法焦点,和在输入光标变更时,修改输入法的输入框坐标

先了解一下输入法的相关知识。在 Windows 编程开发里,输入法框架有三套,其中用的最多的是第二套。第二套是采用 IMM 进行对接的。所谓 IMM 就是 Input Method Manager 也就是 输入法管理器

相关的另一个缩写词 IME 则是 Input Method Editor 或者是 Input Method Engine 的缩写,含义是输入法编辑器或输入法引擎

应用程序可以通过 IMM 对接输入法。所用的 win32 的 API 重点是如下几个

  • ImmGetContext 获取输入法上下文,用于后续所有的其他函数调用
  • ImmAssociateContext 关联输入法和对应的窗口,让输入法了解在哪个窗口输入
  • ImmSetCompositionWindow 用来设置输入法的窗口的坐标,也是本文最重要的函数

本文接下来将告诉大家如何一步步实现封装对 IME 输入法调用,在本文最后将会给出所有的源代码

这部分对输入法的逻辑可以封装为一个类,这样上层就可以不关注细节逻辑。如例子代码,放在 IMESupporter 类型里

为了方便文本框的接入,咱再定义一个接口,用于设置文本框需要实现一些方法,用来提供参数给 IMESupporter 使用才能进行接入

    /// <summary>
    /// 表示控件支持被输入法
    /// </summary>
    interface IIMETextEditor
    {
        /// <summary>
        /// 获取当前使用的字体名
        /// </summary>
        /// <returns></returns>
        string GetFontFamilyName();

        /// <summary>
        /// 获取字号大小,单位和 WPF 的 FontSize 相同
        /// </summary>
        /// <returns></returns>
        int GetFontSize();

        /// <summary>
        /// 获取输入框的左上角的点,用于设置输入法的左上角。此点相对于 <see cref="IIMETextEditor"/> 所在元素坐标。对大部分控件来说,都应该是 0,0 点
        /// </summary>
        /// <returns></returns>
        Point GetTextEditorLeftTop();

        /// <summary>
        /// 获取光标的输入左上角的点。此点相对于 <see cref="IIMETextEditor"/> 所在元素坐标
        /// </summary>
        /// <returns></returns>
        Point GetCaretLeftTop();
    }

对于如微软拼音等输入法,是支持设置输入法的文本大小和字体。因此就需要文本框提供 GetFontFamilyName 和 GetFontSize 方法

而 GetCaretLeftTop 自然就是用来让输入法跟随的。为了让文本框可以做更多的定制,也需要 GetTextEditorLeftTop 方法,这个方法的返回值对大部分自定义的文本框控件来说,都应该是 0,0 点

在 IMESupporter 类型构造函数,期望传入文本框控件,如此可以解决初始化值和监听的锅

    internal class IMESupporter<T> where T : UIElement, IIMETextEditor
    {
        // ReSharper disable InconsistentNaming
        public IMESupporter(T editor)
        {
            Editor = editor;
            // 忽略代码
        }
    }

为了同时约束传入的文本框控件继承 UIElement 和 IIMETextEditor 接口,用了泛形

在文本框控件 Editor 获取焦点的时候,将需要唤起输入法进行输入。在 Editor 失去焦点的时候,就应该告诉输入法当前不进行输入

        public IMESupporter(T editor)
        {
            Editor = editor;
            Editor.GotKeyboardFocus += Editor_GotKeyboardFocus;
            Editor.LostKeyboardFocus += Editor_LostKeyboardFocus;
        }

        private T Editor { get; }

根据 WPF 的约定,对自定义的支持输入法的控件,需要设置 IsInputMethodSuspendedProperty 附加属性,如下面代码

InputMethod.SetIsInputMethodSuspended(editor, true);

在 Editor_GotKeyboardFocus 需要实现的逻辑是调起输入法和设置初始的输入框的坐标。如上文,开始之前,需要先拿到输入法上下文。在拿到输入法上下文之前,可以先获取默认的 IME 类窗口句柄。先获取默认的 IME 类窗口句柄是为了在多进程嵌入窗口时,让微软拼音输入法的输入框跟随输入光标而不是在左上角

_defaultImeWnd = IMENative.ImmGetDefaultIMEWnd(IntPtr.Zero);

以上的 _defaultImeWnd 是一个字段,在 IMESupporter 里定义如下字段和属性

private T Editor { get; }

private IntPtr _defaultImeWnd;
private IntPtr _currentContext;
private IntPtr _previousContext;
private HwndSource? _hwndSource;

private bool _isUpdatingCompositionWindow;

这里有一个细节是 ImmGetDefaultIMEWnd 也许会返回 0x00 空值。什么时候会返回空值?如打开一个 Win32Dialog 窗口,如 OpenFileDialog 或 SaveFileDialog 等,之后关闭,那么此时也许 ImmGetDefaultIMEWnd 将会返回空值

拿到空值,需要重新绑定输入法,告诉输入法当前的窗口获取输入焦点,可以使用如下代码,通过修改附加属性的值,通过附加属性变更调用到 WPF 框架的逻辑,从而修复此问题

            if (_defaultImeWnd == IntPtr.Zero)
            {
                // 如果拿到了空的默认 IME 窗口了,那么此时也许是作为嵌套窗口放入到另一个进程的窗口
                // 拿不到就需要刷新一下。否则微软拼音输入法将在屏幕的左上角上
                RefreshInputMethodEditors();

                // 忽略代码
            }

        /// <summary>
        /// 刷新 IME 的 ITfThreadMgr 状态,用于修复打开 Win32Dialog 之后关闭,输入法无法输入中文问题
        /// </summary>
        /// 原因是在打开 Win32Dialog 之后,将会让 ITfThreadMgr 失去焦点。因此需要使用本方法刷新,通过 InputMethod 的 IsInputMethodEnabledProperty 属性调用到 InputMethod 的 EnableOrDisableInputMethod 方法,在这里面调用到 TextServicesContext.DispatcherCurrent.SetFocusOnDefaultTextStore 方法,从而调用到 SetFocusOnDim(DefaultTextStore.Current.DocumentManager) 的代码,将 DefaultTextStore.Current.DocumentManager 设置为 ITfThreadMgr 的焦点,重新绑定 IME 输入法
        /// 但是即使如此,依然拿不到 <see cref="_defaultImeWnd"/> 的初始值。依然需要重新打开和关闭 WPF 窗口才能拿到
        /// [Can we public the `DefaultTextStore.Current.DocumentManager` property to create custom TextEditor with IME · Issue #6139 · dotnet/wpf](https://github.com/dotnet/wpf/issues/6139 )
        private void RefreshInputMethodEditors()
        {
            if (InputMethod.GetIsInputMethodEnabled(Editor))
            {
                InputMethod.SetIsInputMethodEnabled(Editor, false);
            }

            if (InputMethod.GetIsInputMethodSuspended(Editor))
            {
                InputMethod.SetIsInputMethodSuspended(Editor, false);
            }

            InputMethod.SetIsInputMethodEnabled(Editor, true);
            InputMethod.SetIsInputMethodSuspended(Editor, true);
        }

除了给 ImmGetDefaultIMEWnd 传入 IntPtr.Zero 可以获取之外,还可以传入当前的 Editor 所在的 HwndSource 进行获取,这里的 HwndSource 就相当于或者说大多数时候是等于 Editor 所在的窗口

            _hwndSource = (HwndSource) (PresentationSource.FromVisual(Editor) ??
                                       throw new ArgumentNullException(nameof(Editor)));

            if (_defaultImeWnd == IntPtr.Zero)
            {
                // 如果拿到了空的默认 IME 窗口了,那么此时也许是作为嵌套窗口放入到另一个进程的窗口
                // 拿不到就需要刷新一下。否则微软拼音输入法将在屏幕的左上角上
                RefreshInputMethodEditors();

                // 尝试通过 _hwndSource 也就是文本所在的窗口去获取
                _defaultImeWnd = IMENative.ImmGetDefaultIMEWnd(_hwndSource.Handle);

                // 忽略代码
            }

如果继续获取不到,那么可以尝试使用 GetForegroundWindow 获取。使用 GetForegroundWindow 获取到的也许不是正确的,但是能进入此分支,也好过没有输入法

                _defaultImeWnd = IMENative.ImmGetDefaultIMEWnd(_hwndSource.Handle);

                if (_defaultImeWnd == IntPtr.Zero)
                {
                    // 如果依然获取不到,那么使用当前激活的窗口,在准备输入的时候
                    // 当前的窗口大部分都是对的
                    // 进入这里,是尽可能恢复输入法,拿到的 GetForegroundWindow 虽然预计是不对的
                    // 也好过没有输入法
                    _defaultImeWnd = IMENative.ImmGetDefaultIMEWnd(Win32.User32.GetForegroundWindow());
                }

接下来通过 _defaultImeWnd 获取输入法上下文,如下面代码

// 使用 DefaultIMEWnd 可以比较好解决微软拼音的输入法到屏幕左上角的问题
_currentContext = IMENative.ImmGetContext(_defaultImeWnd);

如果从 _defaultImeWnd 拿不到,则使用 _hwndSource.Handle 获取

_currentContext = IMENative.ImmGetContext(_defaultImeWnd);
if (_currentContext == IntPtr.Zero)
{
   _currentContext = IMENative.ImmGetContext(_hwndSource.Handle);
}

获取上下文之后,将输入法上下文和当前窗口关联起来。对于只实现第二套输入法框架的输入法,应用程序调用 ImmAssociateContext 关联,即可调起此输入法在关联的窗口输入

// 对 Win32 使用第二套输入法框架的输入法,可以采用 ImmAssociateContext 关联
// 但是对实现 TSF 第三套输入法框架的输入法,在应用程序对接第三套输入法框架
// 就需要调用 ITfThreadMgr 的 SetFocus 方法。刚好 WPF 对接了
_previousContext = IMENative.ImmAssociateContext(_hwndSource.Handle, _currentContext);

输入法在输入过程中,将会通过 Windows 消息和当前窗口进行通讯,如获取输入框所需的坐标和输入文本等。因此咱需要加上 Hook 消息,用于告诉输入法坐标。但不需要处理输入的文本的逻辑,因为输入文本的逻辑等在 WPF 已有处理

_previousContext = IMENative.ImmAssociateContext(_hwndSource.Handle, _currentContext);
_hwndSource.AddHook(WndProc);

关于 WndProc 的函数逻辑,咱放在后面

在 WPF 框架里,会对第三套输入法有进行支持,于是就需要调用 ITfThreadMgr 这个 COM 组件进行关联焦点,如下面代码

// 尽管文档说传递null是无效的,但这似乎有助于在与WPF共享的默认输入上下文中激活IME输入法
// 这里需要了解的是,在 WPF 的逻辑,是需要传入 DefaultTextStore.Current.DocumentManager 才符合预期
IMENative.ITfThreadMgr? threadMgr = IMENative.GetTextFrameworkThreadManager();
threadMgr?.SetFocus(IntPtr.Zero);

初始化的过程还需要给输入法的输入框一个初始化的坐标,可使用 Win32 的 ImmSetCompositionWindow 进行设置。在进行设置之前,需要获取到文本框的输入光标相对于窗口的坐标,用于给输入法使用

下面代码从文本框获取文本框实现接口的获取光标和输入框左上角

var textEditorLeftTop = Editor.GetTextEditorLeftTop();
var caretLeftTop = Editor.GetCaretLeftTop();

接下来使用如下代码将坐标转换为相对于窗口的

var hIMC = _currentContext;
HwndSource source = _hwndSource;

var textEditorLeftTop = Editor.GetTextEditorLeftTop();
var caretLeftTop = Editor.GetCaretLeftTop();

var transformToAncestor = Editor.TransformToAncestor(source.RootVisual);

var textEditorLeftTopForRootVisual = transformToAncestor.Transform(textEditorLeftTop);
var caretLeftTopForRootVisual = transformToAncestor.Transform(caretLeftTop);

对 surface 设备来说,需要进行更多的处理

//解决surface上输入法光标位置不正确
//现象是surface上光标的位置需要乘以2才能正确,普通电脑上没有这个问题
//且此问题与DPI无关,目前用CaretWidth可以有效判断
caretLeftTopForRootVisual = new Point(caretLeftTopForRootVisual.X / SystemParameters.CaretWidth,
 caretLeftTopForRootVisual.Y / SystemParameters.CaretWidth);

获取到的坐标传入到 ImmSetCompositionWindow 方法

            //const int CFS_DEFAULT = 0x0000;
            //const int CFS_RECT = 0x0001;
            const int CFS_POINT = 0x0002;
            //const int CFS_FORCE_POSITION = 0x0020;
            //const int CFS_EXCLUDE = 0x0080;
            //const int CFS_CANDIDATEPOS = 0x0040;

            var form = new IMENative.CompositionForm();
            form.dwStyle = CFS_POINT;
            form.ptCurrentPos.x = (int) Math.Max(caretLeftTopForRootVisual.X, textEditorLeftTopForRootVisual.X);
            form.ptCurrentPos.y = (int) Math.Max(caretLeftTopForRootVisual.Y, textEditorLeftTopForRootVisual.Y);
            //if (_isSoftwarePinYinOverWin7)
            //{
            //    form.ptCurrentPos.y += (int) characterBounds.Height;
            //}

            IMENative.ImmSetCompositionWindow(hIMC, ref form);

以上注释的 _isSoftwarePinYinOverWin7 的逻辑是判断在系统版本大于 Win7 的系统,如 Win10 系统上,使用微软拼音输入法,微软拼音输入法在几个版本,需要修改 Y 坐标,加上输入的行高才可以。但是在一些 Win10 版本,通过补丁又修了这个问题

以上就完成了输入法的初始化逻辑

接下来就是需要处理 Windows 消息了,如在收到 WM_INPUTLANGCHANGE 消息时,需要重新获取输入法上下文

        private IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg)
            {
            	// 忽略代码
                case IMENative.WM_INPUTLANGCHANGE:
                    if (_hwndSource != null)
                    {
                        CreateContext();
                    }

            	// 忽略代码
                    break;
            }

            return IntPtr.Zero;
        }

以上获取输入法上下文 CreateContext 方法是获取 _currentContext 的逻辑

在收到 WM_IME_COMPOSITION 消息,需要更新输入法的输入框的坐标

        private IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg)
            {
            	// 忽略代码
                case IMENative.WM_IME_COMPOSITION:
                    UpdateCompositionWindow();
                    break;
            	// 忽略代码
            }

            return IntPtr.Zero;
        }

以上的 UpdateCompositionWindow 方法是调用 ImmSetCompositionWindow 方法设置坐标的方法

关于此 IMESupporter 类型的所有代码,可以从下文获取

接下来是对接 IMESupporter 和具体的文本框

先在自定义的文本框 TextEditor 控件上继承 IIMETextEditor 接口。为了方便调试,咱先写测试逻辑,获取的输入光标就是上次鼠标点击的点以及固定的字体字号

    public partial class TextEditor : FrameworkElement, IIMETextEditor
    {
        // 忽略代码

        protected override void OnRender(DrawingContext drawingContext)
        {
            drawingContext.DrawRectangle(Brushes.Black,null,new Rect(MouseDownPoint,new Size(3,30)));
            base.OnRender(drawingContext);
        }

        protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
        {
        	// 让控件接收点击
            return new PointHitTestResult(this, hitTestParameters.HitPoint);
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            MouseDownPoint = e.GetPosition(this);
            Focus();
            InvalidateVisual();
        }

        private Point MouseDownPoint { get; set; }

        string IIMETextEditor.GetFontFamilyName()
        {
            return "微软雅黑";
        }

        int IIMETextEditor.GetFontSize()
        {
            return 30;
        }

        Point IIMETextEditor.GetTextEditorLeftTop()
        {
            // 相对于当前输入框的坐标
            return new Point(0, 0);
        }

        Point IIMETextEditor.GetCaretLeftTop()
        {
            return MouseDownPoint;
        }
    }

在 OnMouseDown 方法里面,需要调用 Focus 获取焦点,同时更新一下模拟的光标。模拟的光标是在 OnRender 方法里面,使用画出一个矩形模拟的,没有做闪烁

为了让控件能接收键盘消息,需要设置 FocusableProperty 属性。为了接收 Tab 键,而不是被切到其他控件,需要设置 KeyboardNavigation 的 IsTabStopProperty 和 TabNavigationProperty 附加属性。因为这是作用在所有的自定义文本框 TextEditor 控件上的,因此可以在 TextEditor 的静态构造函数,进行更改默认值,代码如下

        static TextEditor()
        {
            // 用于接收 Tab 按键,而不是被切换焦点
            KeyboardNavigation.IsTabStopProperty.OverrideMetadata(typeof(TextEditor),
                new FrameworkPropertyMetadata(true));
            KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(TextEditor),
                new FrameworkPropertyMetadata(KeyboardNavigationMode.None));

            // 用于获取焦点逻辑
            FocusableProperty.OverrideMetadata(typeof(TextEditor),
                new FrameworkPropertyMetadata(true));
        }

完成 TextEditor 控件的配置,就可以对接 IMESupporter 类,对接方法是创建即可

        public TextEditor()
        {
            // 忽略代码

            _imeSupporter = new IMESupporter<TextEditor>(this);
        }

        private readonly IMESupporter<TextEditor> _imeSupporter;

这样就完成了文本框让输入法跟随输入的功能

代码

本文所有代码放在github 和 gitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin b3a1fffece8284d0b84407aa13d949de6a2f1536

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

获取代码之后,打开 LightTextEditorPlus.sln 文件

到此这篇关于WPF在自定义文本框中实现输入法跟随光标的文章就介绍到这了,更多相关WPF输入法跟随光标内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • WPF实现带全选复选框的列表控件

    本文将说明如何创建一个带全选复选框的列表控件.其效果如下图: 这个控件是由一个复选框(CheckBox)与一个 ListView 组合而成.它的操作逻辑: 当选中"全选"时,列表中所有的项目都会被选中:反之,取消选中"全选"时,所有项都会被取消勾选. 在列表中选中部分数据项目时,"全选"框会呈现不确定状态(Indetermine). 由此看出,"全选"复选框与列表项中的复选框达到了双向控制的效果. 其设计思路:首先,创建自定义

  • WPF自定义搜索框代码分享

    首先下载搜索图标: 控件中的搜索图标下载地址:http://www.easyicon.net/1183666-Search_icon.html 搜索框设计过程比较简单: 1.先定义一个Rectangle作为背景 2.然后中间放TextBox输入,可以重写其中的模板.提示语Label放在模板中,可以在模板的触发器中控制隐藏显示~ 3.搜索按钮-大家随便在网上下个就行了. UserControl界面: <UserControl x:Class="WpfApplication18.SearchC

  • WPF自动隐藏的消息框的实例代码

    (鼠标放上去将一直显示,移开动画继续),提供normal和error两种边框. 介绍:传统的确定,取消,OK,CANCAL之类的对话框太繁琐了,由于项目需要而诞生的仿手机式提示对话框.当然传统的对话框项目中也有,这里就不做介绍了. 出场和退场动画做得很简单,就用Blend随便鼓捣了一番,将就用吧. 预览效果如下: 思路其实很简单:将窗体透明化->布局和样式设计->后台传值调用. 准备工作:Microsoft.Expression.Interactions.dll和System.Windows.

  • C# WPF 建立无边框(标题栏)的登录窗口的示例

    前言:笔者最近用c#写WPF做了一个项目,此前未曾做过完整的WPF项目,算是一边学一边用,网上搜了不少资料,效率当然是不敢恭维的,有时会在一些很简单的问题上纠结很长时间,血与泪的教训可不少. 不过,正如电视剧某榜里的一句话:既然我活了下来,就不会白白活着!笔者怎么也算挣扎过了,有些经验与教训可以分享,趁着记忆深刻总结写下来.希望后来者少走弯路,提高工作效率.如果有写得不好的地方,希望读者能够指正,一起进步! --------------------------------- 今天先从登录窗口说起

  • WPF框架Prism中对话框Dialog用法介绍

    什么是Dialog? 对话框实际上是我们应用程序经常用到的一个功能, 类如: Show.ShowDialog. 可以弹出一个我们指定的窗口, 仅此而已, 那么在Prism当中, Dialog指的是什么? Prism提供了一组对话服务, 封装了常用的对话框组件的功能, 例如: RegisterDialog/IDialogService (注册对话及使用对话) 打开对话框传递参数/关闭对话框返回参数 回调通知对话结果 创建Dialog流程 创建对话框,通常是一组用户控件 ,并且实现 IDialogA

  • WPF在自定义文本框中实现输入法跟随光标

    本文告诉大家在 WPF 写一个自定义的文本框,如何实现让输入法跟随光标 本文非小白向,本文适合想开发自定义的文本框,从底层开始开发的文本库的伙伴.在开始之前,期望了解了文本库开发的基础知识 本文实现的效果如下 实现 本文的方法参考了 WPF 官方仓库的逻辑,可以在WPF仓库的wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\System\Windows\Documents\ImmComposition.cs文件看到官方是如何让TextB

  • 基于jQuery的Spin Button自定义文本框数值自增或自减

    有时候在设计表单时需要对文本框实现数值自增或自减功能,例如默认为1,点击向上按钮键则增加指定步长值,点击向下按钮键则减少指定步长值,使用jQuery插件jQuery Spin Button只需要几行代码就可实现该功能,效果如下图 使用说明 一,需要使用jQuery库文件和jQuery Spin Button库文件(目前版本1.1.1) 素材准备 上下按钮图片,默认路径为:/img/spin/,上下按钮图片命名为:spin-button.png,可进行自定义修改 实例代码 一,包含文件部分 复制代

  • JavaScript实现文本框中默认显示背景图片在获得焦点后消失的方法

    本文实例讲述了JavaScript实现文本框中默认显示背景图片在获得焦点后消失的方法.分享给大家供大家参考.具体如下: html代码: <form name="searchform" id="search-form"> <div> <b>Search</b> <input type="text" name="txtInput" title="Enter the t

  • js实现文本框中输入文字页面中div层同步获取文本框内容的方法

    本文实例讲述了js实现文本框中输入文字页面中div层同步获取文本框内容的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.o

  • 解决OneThink中无法异步提交kindeditor文本框中修改后的内容方法

    最近在使用OneThink中自带的kindeditor编辑器的时候,保存草稿的时候,输入的内容总是不能够保存到后台.如下图 通过分析URL,发现原来content值为空 明明有值,为什么是空呢?但是如果不采用异步方式提交表单的话,则可以获取到输入值.开始一直以kindeditor为是ajax的问题,最后,查阅资料才知道原来是kindeditor的问题.因为在异步提交数据的时候,并没有将kindeditor中输入的值,同步到对应的文本框上.正确的做法是,当kindeditor失去焦点的时候,就进行

  • jquery文本框中的事件应用以输入邮箱为例

    文本框中的事件应用:以输入邮箱为例,如图: 代码如下: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head

  • jQuery实现点击下拉框中的值累加到文本框中的方法示例

    本文实例讲述了jQuery实现点击下拉框中的值累加到文本框中的方法.分享给大家供大家参考,具体如下: 先来看看运行效果: 具体代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale

  • JavaScript实现焦点进入文本框内关闭输入法的核心代码

    js实现焦点进入文本框内关闭输入法:imeMode 要用到的东西: imeMode:xxx 有四个参数 active 代表输入法为中文 inactive 代表输入法为英文 auto 代表打开输入法 (默认) disable 代表关闭输入法 <INPUT onfocus=" this.style.imeMode='active' " /> <INPUT onfocus=" this.style.imeMode='inactive' " /> &

  • js实现文本框中焦点在最后位置

    在一般的程序中.程序员做输入框内容正确性检测时一般喜欢通过判断内容的合法性来确定焦点框. 如: 复制代码 代码如下: if(obj.value==""){   obj.focus();   return false;} 这样当哪一项输入框为空是就将焦点移动那一项输入框..这项功能使用起来非常方便..但是存在一个小小的问题... 那就是obj.focus()将焦点移动到输入框后,会将文字光标(就是一闪一闪的竖线)移动到这个输入框的第一个字符的位置...就上面的判断而言..如果文本框中没有

  • JS正则(RegExp)判断文本框中是否包含特殊符号

    前言 有时,我们希望判断文本框中用户输入的字符是否含有特殊符号(*/#$@),就像用户注册时密码框的填写. demo 利用 RegExp 对象,能很优雅的实现以上需求: // even(文本框内容) function (even) { // 规则对象(flag) var flag = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<><>/?~!@#¥--&*()--|{}[]'::""'.,.? ]&

随机推荐