| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1632 人关注过本帖
标题:[求助]短信输入框问题种种
只看楼主 加入收藏
cnliang
Rank: 1
等 级:新手上路
帖 子:62
专家分:0
注 册:2005-4-1
收藏
 问题点数:0 回复次数:10 
[求助]短信输入框问题种种
感谢Griefforyou提供的“单字符Undo/Redo代码”,通过引用,我在项目中已经基本能够实现撤消上一步操作的功能,但是又遇到了一个新问题: 由于我想实现的功能不是通过"点击按钮"等来触发"撤消上一步操作"的动作,而是在输入的英文字符数超过70的时候,如果在后面接着“输入中文”或“粘贴含有中文的字符串”,则自动撤消上一步操作(即回到输入中文的前一个状态),以满足“文本框中最多只有70个中文字符或160个英文字符”的原则。 现在的问题就是:虽然我在70个英文字符之后输入了中文,但是并不会主动触发撤消上一步操作的动作,而是在文本框中照常显示了我所输入的中文,一定要等我再按下任意键后才触发撤消动作,不知如何才能解决这个问题? 我所用的相关代码如下: Private Sub Text1_KeyPress(KeyAscii As Integer)

......

'当字符数大于70时,判断70->160个字符之间是否有中文,如有则删除之 If Len(Text1) > 70 And Len(Text1) <= 160 Then For j = 71 To Len(Text1) strtemp2 = Mid((Text1), j, 1) If Asc(strtemp2) < 0 Then '撤消上一步操作 Undo Text1 Exit Sub End If Next '当输入的英文字符超过70个字符时,如果在前70个字符之间插入了中文,则截取前70

个字符 For k = 1 To 70 strtemp3 = Mid((Text1), k, 1) If Asc(strtemp3) < 0 Then '截取前70个字符 Text1.Text = Mid((Text1), 1, 70 ) Exit Sub End If Next End If

...... 附: '单字符Undo/Redo代码 'By:Griefforyou

Option Explicit Dim OldText As String, OldSelStart As Long, OldSelLength As Long Dim UndoArray() As String, MyChangeFlag As Boolean Dim UndoStep As Long Private Sub Command1_Click() Undo Text1 End Sub Private Sub Command2_Click() Redo Text1 End Sub Private Sub Form_Load() Init Text1 Command1.Caption = "Undo" Command2.Caption = "Redo" End Sub Private Sub Init(Obj As TextBox) ReDim UndoArray(0) As String OldText = Obj.Text OldSelStart = Obj.SelStart OldSelLength = Obj.SelLength UndoArray(0) = OldText UndoStep = 0 End Sub Private Sub Change(Obj As TextBox) If MyChangeFlag = False Then ReDim Preserve UndoArray(UBound(UndoArray) + 1) As String UndoArray(UBound(UndoArray)) = Obj.Text UndoStep = UBound(UndoArray) Debug.Print UndoStep & " " & Text1.Text End If End Sub Private Sub Undo(Obj As TextBox) If UndoStep > 0 Then MyChangeFlag = True UndoStep = UndoStep - 1 Obj.Text = UndoArray(UndoStep) MyChangeFlag = False End If End Sub Private Sub Redo(Obj As TextBox) If UndoStep < UBound(UndoArray) Then MyChangeFlag = True UndoStep = UndoStep + 1 Obj.Text = UndoArray(UndoStep) MyChangeFlag = False End If End Sub Private Sub Text1_Change() Call Change(Text1) End Sub

[此贴子已经被作者于2005-4-13 15:41:52编辑过]

搜索更多相关主题的帖子: 短信 字符 中文 输入 
2005-04-08 08:34
griefforyou
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:3336
专家分:0
注 册:2004-4-15
收藏
得分:0 
晕。

天津网站建设 http://www./
2005-04-08 09:19
cnliang
Rank: 1
等 级:新手上路
帖 子:62
专家分:0
注 册:2005-4-1
收藏
得分:0 
你晕什么啊?我都晕好几天了,还是不会自动触发撤消,莫非在text1_keypress里是不能触发事件的

耐心和持久 胜过 激烈和狂热
2005-04-08 09:35
griefforyou
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:3336
专家分:0
注 册:2004-4-15
收藏
得分:0 

Dim OldSelStart As Long Dim OldText As String Dim MaxLength As Long Dim MyChangeFlag As Boolean

Private Sub Form_Load() MaxLength = 20 '最大字节长度 End Sub

'计算字节长度 Function ByteLen(Str) Dim Length Length = 0 For i = 1 To Len(Str) If (Asc(Mid(Str, i, 1)) < 0) Then Length = Length + 2 Else Length = Length + 1 End If ByteLen = Length Next End Function '按字节取得字符串左边部分字符(这里如果超过长度是恢复上次的,也可用此函数截取一下) Function LeftByte(Str, Lens) Dim Length Length = 0 For i = 1 To Len(Str) If (Asc(Mid(Str, i, 1)) < 0) Then Length = Length + 2 Else Length = Length + 1 End If If Length = Lens Then LeftByte = Left(Str, i) Exit Function ElseIf Length > Lens Then LeftByte = Left(Str, i - 1) Exit Function End If Next End Function

'粘帖时防止超长 Private Sub Text1_Change() If MyChangeFlag Then Exit Sub If ByteLen(Text1.Text) > MaxLength Then MyChangeFlag = True Text1.Text = OldText Text1.SelStart = OldSelStart MyChangeFlag = False Else OldSelStart = Text1.SelStart OldText = Text1.Text End If End Sub

'无法容下更多字符时,禁止输入。 Private Sub Text1_KeyPress(KeyAscii As Integer) Debug.Print KeyAscii If KeyAscii <> vbKeyBack Then If ByteLen(Text1.Text) >= MaxLength Then '英文 KeyAscii = 0 ElseIf ByteLen(Text1.Text) > MaxLength - 2 And KeyAscii < 0 Then '汉字 KeyAscii = 0 End If End If End Sub


天津网站建设 http://www./
2005-04-08 09:43
cnliang
Rank: 1
等 级:新手上路
帖 子:62
专家分:0
注 册:2005-4-1
收藏
得分:0 

也许是我太笨了,这些天来在实际运用中还是未能完全参透版主介绍的按字节来处理的方法 其实我现在试图做的是一个手机短信平台的发送文本框,由于最终的短信内容的长度是 “我做的这个文本框中所输入文本的长度” + “另一块可选择添加的文本长度”,如果我这边的文本超出约定的长度,则另一块在选择添加时有可能出现死循环,为了避免这种循环的出现,我这边必须严格限制输入字符的长度。 由于短信内容中“有中文字符”和“无中文字符”在发送时用的是不同编码 :因为手机短消息的发送是以PDU串的形式发送出去的,中文字符以Unicode码来表示,所以在发送中文短消息之前必须首先将中文字符转换为Unicode码(其中英文字符亦用双字节表示);而在发送不含中文的短信时用的是“7位码”。 因此发送含中文的短信时最多可发送70个字符;而在发送不含中文的短信时最多可发送160个字符(注意:比发送中文短信时的2倍还要!)。

我的最初想法是:发送前只判断短信内容中“有无中文”及“字符的长度”,发送时再统一编码,这样就只有两个极限:70和160。而如果用字节来处理似乎要更复杂得多。

所以存在的问题就是:

1、 如果我在输入69个中文或159个英文时按回车,虽然我在代码中限制了文本在有中文字符时的最大长度是70和无中文字符时的最大长度是160,但这个回车还是会被输入,即字符数还是会达到71或161,以至超标

2、 如果我输入的“非中文字符”已经超过70个字符,此时我再在后面输入一个中文(或粘贴一段含中文的字符串),原则上是不被允许的,但结果却是如同上面的那个回车一样,还是被输进去(或粘贴上去)了 ,以至超标。

3、 如果我输入的“非中文字符”已经超过70个字符,此时在这前70个“非中文字符”中间随便输入一个中文(或粘贴一段含中文的字符串),这样必然导致字符数超标(为解决这个问题,我的最初想法是简单地截取前70个字符,这样总不至于超标)

这几天我用版主教的方法解决了上述大部份问题,现在只剩下一个回车问题(即在输入69个字符后继续输入的那个回车)无法解决,因为我在代码中是截取前70个字符,而在第69个字符时回车,回车字符所占的两个字符会被截取一个,从而达到70个字符,虽然回车的这半个字符可能对程序影响不大,但总觉得是一个缺限,还望指导一条解决之道。 我用的相关代码如下: Private Sub text1_Change() On Error GoTo Doerrors Dim i As Long Dim strtemp As String '判断短信内容及附加信息中是否有中文字符 For i = 1 To (Len(text1.Text) + Len(text2.Text)) strtemp = Mid((text1.Text + text2.Text), i, 1) If Asc(strtemp) < 0 Then MaxLength = 70 - Len(text2.Text) Label1.Caption = "您可以输入70个中文字符,已输入" & (Len(text1.Text) + Len(text2.Text)) & "个字符,其中附加信息占用了" & Len(text2.Text) & "个字符,还可以输入" & (70 - Len(text1.Text) - Len(text2.Text)) & "个字符" If i <= 70 Then text1.Text = Left(text1.Text, (70 - Len(text2.Text))) Exit Sub End If '粘帖时防止超长 If MyChangeFlag Then Exit Sub If Len(text1.Text) > MaxLength Then MyChangeFlag = True text1.Text = OldText text1.SelStart = OldSelStart MyChangeFlag = False Else OldSelStart = text1.SelStart OldText = text1.Text End If

Exit Sub End If Next MaxLength = 160 - Len(text2.Text) Label1.Caption = "您可以输入160个英文字符,已输入" & (Len(text1.Text) + Len(text2.Text)) & "个字符,其中附加信息占用了" & Len(text2.Text) & "个字符,还可以输入" & (160 - Len(text1.Text) - Len(text2.Text)) & "个字符" '粘帖时防止超长 If MyChangeFlag Then Exit Sub If Len(text1.Text) > MaxLength Then MyChangeFlag = True text1.Text = OldText text1.SelStart = OldSelStart MyChangeFlag = False Else OldSelStart = text1.SelStart OldText = text1.Text End If Exit Sub Doerrors:...... End Sub

Private Sub text1_KeyPress(KeyAscii As Integer) Debug.Print KeyAscii If KeyAscii <> vbKeyBack Then If Len(Txt_dxrr.Text) >= MaxLength Then KeyAscii = 0 End If End If End Sub


耐心和持久 胜过 激烈和狂热
2005-04-12 13:35
griefforyou
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:3336
专家分:0
注 册:2004-4-15
收藏
得分:0 
分析一下:
全是英文时整个串占用位数为 160*7=1120
全是中文时整个串占用位数为 70*8*2=1120

那如果我知道整个串中有 N个英文 M个中文 ,我就能计算出是否占用位数超过1120,如果超过则截取或者提示超长,让用户减少字符数。

天津网站建设 http://www./
2005-04-12 14:16
griefforyou
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:3336
专家分:0
注 册:2004-4-15
收藏
得分:0 
Function BitLength(Str As String) As Long
    Dim Length
    Length = 0
    For i = 1 To Len(Str)
        If (Asc(Mid(Str, i, 1)) &lt; 0) Then
            Length = Length + 16
        Else
            Length = Length + 7
        End If
    Next
    BitLength = Length
End Function

天津网站建设 http://www./
2005-04-12 14:48
cnliang
Rank: 1
等 级:新手上路
帖 子:62
专家分:0
注 册:2005-4-1
收藏
得分:0 
嗯,利用总占用位数相同确实也是一个好主意! 只要每个字符逐个判断字符类型,然后分别累加。 不过我们现在所采用的按字符数来判断的方法也是可行的啊,更何况大部份功能都已实现,就差那一个回车了 另外:那个i是不是最好也要定义一下 Function BitLength(Str As String) As Long Dim i Dim Length Length = 0 For i = 1 To Len(Str) If (Asc(Mid(Str, i, 1)) < 0) Then Length = Length + 16 Else Length = Length + 7 End If Next BitLength = Length End Function

[此贴子已经被作者于2005-4-12 15:20:28编辑过]


耐心和持久 胜过 激烈和狂热
2005-04-12 15:15
griefforyou
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:3336
专家分:0
注 册:2004-4-15
收藏
得分:0 
回车管你什么事,你就提示超长,让用户自己删除。

天津网站建设 http://www./
2005-04-12 15:32
cnliang
Rank: 1
等 级:新手上路
帖 子:62
专家分:0
注 册:2005-4-1
收藏
得分:0 
      嗯,好办法! 只可惜原本简单的一个文本框,搞得到处都是弹出框就是了,真是有点于心不忍,但似乎也没有其它更好的办法了 。
      
      再次感谢版主一路的支持! 小弟这几日可是受益非浅啊,搞这个文本框花了大半个月,想想自己也真是够菜的,以后还请版主继续支持小弟的编程之路!

耐心和持久 胜过 激烈和狂热
2005-04-12 15:50
快速回复:[求助]短信输入框问题种种
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.044537 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved