Thanks for your perspective jmc, it was a nudge in the right direction.
I still had to use the KeyUp event to check if a modifier key had been released before a digit/letter key was pressed, want to visually show that to the user as it's happening.

This seems to work the way that I would like it to:
vb Code:
  1. Public Class HotKeyTextBox
  2.     Inherits System.Windows.Forms.TextBox
  3.  
  4. #Region " Variables "
  5.  
  6.     Private m_IsCtrl, m_IsAlt, m_IsShift As Boolean
  7.     Private m_Char As Char = CChar(String.Empty)
  8.     Private m_HasChar As Boolean
  9.  
  10. #End Region
  11. #Region " Sub: New "
  12.  
  13.     Public Sub New()
  14.         MyBase.New()
  15.  
  16.         m_IsCtrl = False
  17.         m_IsAlt = False
  18.         m_IsShift = False
  19.         m_HasChar = False
  20.     End Sub
  21.  
  22. #End Region
  23. #Region " Overrides Subs: OnKeyDown, OnKeyUp "
  24.  
  25.     Protected Overrides Sub OnKeyDown(e As System.Windows.Forms.KeyEventArgs)
  26.         e.SuppressKeyPress = True
  27.  
  28.         m_IsAlt = e.Alt
  29.         m_IsCtrl = e.Control
  30.         m_IsShift = e.Shift
  31.  
  32.         Select Case e.KeyCode
  33.             Case Keys.ControlKey, Keys.ShiftKey, Keys.Menu
  34.                 'Ignore modifier keys alone.
  35.             Case Else
  36.                 Dim ch As Char = Convert.ToChar(e.KeyCode)
  37.                 If Char.IsLetterOrDigit(ch) Then
  38.                     m_Char = Char.ToUpper(ch)
  39.                     m_HasChar = True
  40.                 End If
  41.         End Select
  42.  
  43.         Call UpdateText()
  44.         MyBase.OnKeyDown(e)
  45.     End Sub
  46.  
  47.     Protected Overrides Sub OnKeyUp(e As System.Windows.Forms.KeyEventArgs)
  48.         If Not m_HasChar Then
  49.             m_IsAlt = e.Alt
  50.             m_IsCtrl = e.Control
  51.             m_IsShift = e.Shift
  52.         End If
  53.  
  54.         Call UpdateText()
  55.  
  56.         If Not e.Alt AndAlso Not e.Control AndAlso Not e.Shift Then
  57.             m_Char = CChar(String.Empty)
  58.             m_HasChar = False
  59.         End If
  60.  
  61.         MyBase.OnKeyDown(e)
  62.     End Sub
  63.  
  64.     Private Sub UpdateText()
  65.         Dim parts As New List(Of String)
  66.  
  67.         If m_IsCtrl Then parts.Add("Ctrl")
  68.         If m_IsShift Then parts.Add("Shift")
  69.         If m_IsAlt Then parts.Add("Alt")
  70.         If m_HasChar Then parts.Add(m_Char.ToString)
  71.  
  72.         Me.Text = String.Join(" + ", parts)
  73.     End Sub
  74.  
  75. #End Region
  76.  
  77. End Class