zoukankan      html  css  js  c++  java
  • 开贴说说文本编辑器的那些事情捕获输入内容

    原本应该先给大家说明一下程序框架的,不过,现在程序框架还没有定下来,所以暂时再给大家介绍一些具体的技术。这篇随笔告诉大家怎么获得输入的内容。

        输入内容,随便Google一下的话,大概会出现以下解决方法:

        KeyPress事件的 KeyPressEventArgs 参数 的 e.KeyChar 就是输入的内容(包括直接输入和使用IME输入。)

        KeyPress这个事件没有什么问题,的确程序是需要这个事件来捕获输入内容的,但是还是有2个注意点,请大家牢记。

        第一:输入法输入 和 .Net版本问题

            如果是通过输入法来输入文字的话(中文,日本语等输入法),.Net1.x 和.Net2.0以上有一个明显的区别:

           Net1.x只触发一次KeyPress事件,Net2.0以上将触发两次KeyPress事件!!

           Net2.0以上IME输入时两次触发KeyPress事件原因:

           KeyPress事件的源头是WM_CHAR消息和WM_IME_CHAR消息。当非IME输入的时候,只引发了WM_CHAR消息,   KeyPress只触发一次。但是,当内容文字是通过IME输入的时候,在引发WM_CHAR消息的同时,还将引发WM_IME_CHAR消息。这样的 话,通过IME输入文字的时候,我们将两次得到KeyPress事件。不知道Net1.x的KeyPress为什么没有这个问题,可能Net1.x的时 候,KeyPress只对WM_CHAR作出反应吧。

           知道了原因的话,那对策也很容易就找到了。在WndProc里面进行预先判断。如果是由WM_IME_CHAR消息引发的KeyPress,则在 KeyPress事件里什么都不做,不然的话,在KeyPress里绘制字符。(所有的输入,均有WM_CHAR消息)

        第二个问题:是不是可以绘制的字符

        KeyPress事件的 KeyPressEventArgs 参数 的 e.KeyChar ,这里并没有保证所有的字符均是可以绘制的字符,如果你按下一些特殊键和组合键的时候,也会产生e.KeyChar。由于可能涉及到不同的字符集,还不能 用简单的方法过滤掉他们呢。

    我的做法是在PreviewKeyDown事件里面做筛选,PreviewKeyDown事件在 KeyPress事件之前发生,我是在KeyPress里面做绘制字符的操作的,如果PreviewKeyDown事件里面判断出按下的键是一些功能键和 控制键,怎在KeyPress里面什么都不做。至于为什么在PreviewKeyDown里做判断,而不是在KeyDown事件里呢,原因是 PreviewKeyDown能捕获一些KeyDown事件不能捕获的KeyCode!

       综上所述,在KeyPress事件里面是否绘制字符串,有两个前提条件,第一,通过WndProc截获的消息,判断是不是由于WM_IME_CHAR造成 的两次触发;第二,通过PreviewKeyDown事件来判断是不是控制系的键或操作系的键引发的KeyPress事件。如果是WM_IME_CHAR 触发的KeyPress或控制系的键或操作系的键引发的KeyPress,则不做绘图操作。

    <以下代码只是节选,并非完整代码!!>

    'IsDrawString如果为假的话,不将字符绘制到窗体
    Private IsDrawString As Boolean
    '这个内容是否从IME传递过来
    Private CharFormIME As Boolean
    '*************************************************************************
    '*      VS2003中,从输入法输入的字符只表示一次,VS2003以后,表示两次
    '*      原因据说和两个消息有关,一个是0x286,一个是0x102
    '*************************************************************************
    Private Sub TextBoxEx_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles Me.KeyPress
        '如果不是操作系的按键,不是从IME发出的重复信息,则绘制文字
        If IsDrawString And CharFormIME = False Then
           。。。。。。。。。。。。。。 

            DrawLine(mDocument.InputPosition.Y)

          。。。。。。。。。。。。。。。
        End If
    End Sub

    ''' <summary>
    ''' 捕获系统消息
    ''' </summary>
    ''' <param name="m">系统消息</param>
    ''' <remarks></remarks>
    Protected Overrides Sub WndProc(ByRef m As Message)
        Select Case m.Msg
            '所有需要画的字符都来自语WM_CHAR,中文,日语的话,还回发生WM_IME_CHAR,造成KeyPress里2次同样的事件
            '基于这个原因,我们吧WM_IME_CHAR产生的KeyPress过滤掉
            Case WM_IME_CHAR
                CharFormIME = True
            Case WM_CHAR
                CharFormIME = False
        End Select
        MyBase.WndProc(m)
    End Sub

    ****************************************************
    关于箭头等无法在KeyDown里面捕获的键只能在PreViewKeyDown里截获了         
    ****************************************************
    Private Sub TextBoxEx_PreviewKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles Me.PreviewKeyDown
        '先假设不能绘制,如果没有被过滤掉的话,则能绘制
        IsDrawString = False
        '如果Shift被按下,则现在的位置做为选中内容开始位置
        Select Case e.KeyCode
            Case Keys.ShiftKey

            。。。。。。。。
            Case Keys.Enter

            。。。。。。。。

            Case Keys.Back

            。。。。。。。。

            Case Else
                IsDrawString = True
    End Select

    End Sub

  • 相关阅读:
    Linux各目录的意义
    LinuxVIM编辑器用法
    Linux自动同步时间
    bash的基本特性
    shell-homeworkone
    shell
    笔记
    Python-1-Day
    Linux使用BIND提供域名解析服务
    Linuxautofs自动挂载服务
  • 原文地址:https://www.cnblogs.com/TextEditor/p/2095190.html
Copyright © 2011-2022 走看看