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

  • 相关阅读:
    【面积并】 Atlantis
    【动态前k大 贪心】 Gone Fishing
    【复杂枚举】 library
    【双端队列bfs 网格图建图】拯救大兵瑞恩
    【奇偶传递关系 边带权】 奇偶游戏
    【权值并查集】 supermarket
    CF w4d3 A. Pythagorean Theorem II
    CF w4d2 C. Purification
    CF w4d2 B. Road Construction
    CF w4d2 A. Cakeminator
  • 原文地址:https://www.cnblogs.com/TextEditor/p/2095190.html
Copyright © 2011-2022 走看看