2015-04-17 93 views
3

我的項目是模擬Enigma機器,我需要一些幫助處理視覺界面。VB.NET - 如何讓文本框只接受每個按鍵一個字符?

在我的程序中,我需要一個文本框,用戶可以在其中輸入無限數量的字母。但是,該程序還根據輸入的文本更新其他組件,並顯示用戶的可視化表示。

例如,當我按下字母'A'時,程序將其編碼爲字母'S',並在界面中顯示圖像。但是,每次字母編碼時,該編碼都是唯一的。如你所知,當你長時間在鍵盤上按下一個字母時,它會一直寫下那封信。例如,如果我按住'A',在我的文本框中,我會以'AAAAAAAAAAAAAAAAAAAAAA'結尾,並且會在圖像顯示屏上對每一個'A'進行編碼。

我的問題是:如何限制文本框每個按鍵只能接受一個字母,但仍允許雙字母或三字母?所以我可以有一個相同字符的子字符串,只要我通過在鍵盤上反覆按鍵來輸入它們。

我需要這個,只要輸入字母被按下,編碼的字母就會亮起來。

+0

是否需要支持或移除對控制字符的支持(例如箭頭鍵,退格鍵,刪除鍵)? –

+0

它需要支持它們 – Jad

+0

對於大多數情況下,簡單的'KeyUp'處理程序,如下面的答案中所示,就足夠了。然而,從技術上講,'KeyUp'事件並不保證在任何情況下都會觸發。例如,如果另一個窗口在按住鍵的同時接收到焦點,則「KeyUp」事件不會觸發。在那種情況下,下一個合法的按鍵最終會被忽略。如果這是一個問題,請看看[其他問答](http://stackoverflow.com/questions/4420981/stopping-keys-from-repeating-c),它有更徹底的解決方案。 –

回答

2

如果您在KeyEventArgs內使用SuppressKeyPress,你可以控制按鍵何時完成。在我的例子中,我使用一個文本框作爲輸入的控件。但是,這將與其他控件以及工作...

Dim keyIsDown As Boolean 'marked to give status of keyboard key 

Private Sub TextBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBox1.KeyDown 
    If keyIsDown Then 'if key is already down abort 
     e.SuppressKeyPress = True 
     Exit Sub 
    End If 
    keyIsDown = True 'if key was not already down mark it as down now 
End Sub 

Private Sub TextBox1_KeyUp(sender As Object, e As KeyEventArgs) Handles TextBox1.KeyUp 
    keyIsDown = False 'key has traveled up clear the marker 
End Sub 
+1

感謝您的解決方案。我只想添加其他誰可能想要使用您的代碼添加下面的行在'TextBox1_KeyDown'子'中的'如果keyIsDown然後'行之前。這將使您仍然可以長按箭頭鍵和退格鍵進行文本索引選擇和刪除。 '如果e.KeyCode = Keys.Back或e.KeyCode = Keys.Left或e.KeyCode = Keys.Right或e.KeyCode = Keys.Delete然後退出Sub' – Jad

2

您可以使用布爾標誌來確定是否觸發第一個keypress事件,然後取消任何下一個keypress,直到觸發KeyUp事件。

Private isKeyHandled As Boolean = False 

Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs) _ 
Handles TextBox1.KeyPress 

    e.Handled = Me.isKeyHandled 
    Me.isKeyHandled = True 

End Sub 

Private Sub TextBox1_KeyUp(ByVal sender As Object, ByVal e As KeyEventArgs) _ 
Handles TextBox1.KeyUp 

    Me.isKeyHandled = False 

End Sub 

另外,以適應您可以添加邏輯到一個子類文本框:

Public Class TextBoxEx : Inherits TextBox 

    Public Property DisableKeyRepetition As Boolean = False 

    Private isKeyHandled As Boolean = False 

    Protected Overrides Sub OnKeyPress(ByVal e As KeyPressEventArgs) 

     MyBase.OnKeyPress(e) 

     If Me.DisableKeyRepetition Then 
      e.Handled = Me.isKeyHandled 
      Me.isKeyHandled = True 
     End If 

    End Sub 

    Protected Overrides Sub OnKeyUp(ByVal e As KeyEventArgs) 

     MyBase.OnKeyUp(e) 
     Me.isKeyHandled = False 

    End Sub 

End Class 

然後:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 

    Me.TextBoxEx1.DisableKeyRepetition = True 

End Sub 
3

它是否是重複關鍵不是你能在關鍵事件一探究竟。但是它可以在底層的WM_KEYDOWN message中找到,lparam參數的第30位將被設置爲1.到目前爲止,查看該消息最簡單的方法是重寫表單的ProcessCmdKey()方法。將此代碼粘貼到您的表單類中:

Private repeatedKey As Boolean 

Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean 
    repeatedKey = (msg.LParam.ToInt32 And (1 << 30)) <> 0 
    Return MyBase.ProcessCmdKey(msg, keyData) 
End Function 

您現在可以在KeyPressed事件處理程序中檢查此變量。我想像你想要做這樣的事情:

Private Sub TextBox1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TextBox1.KeyPress 
    If repeatedKey Then e.Handled = True 
    If e.KeyChar = ChrW(22) Then e.Handled = True '' Disable paste 
    If e.KeyChar = ChrW(8) Then e.Handled = False '' Allow repeating backspace 
End Sub 

第1行防止重複鍵被看到。第二行禁用複製/粘貼,不太可能在您的應用程序中有用。第三行仍允許重複使用退格鍵,以便用戶可以輕鬆糾正錯誤。請記住,我只是猜測你想在這裏做什麼,這只是一個例子,你可能想要改變它。

+0

偉大的信息,但我認爲你的意思是'( msg.LParam.ToInt32和(1 << 30)) <> 0'而不是VB#混合... –

+0

謝謝,我在C#中編寫並測試了它。 –

相關問題