&HC0 'Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key ' C1D7 Reserved ' D8DA Unassigned VK_OEM_4 = &HDB 'Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key VK_OEM_5 = &HDC 'Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key VK_OEM_6 = &HDD 'Used for miscellaneous characters; it can vary by keyboard Windows 2000/XP: For the US standard keyboard, the ']}' key VK_OEM_7 = &HDE ' Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key VK_OEM_8 = &HDF 'Used for miscellaneous characters; it can vary by keyboard. E0 Reserved '- E1 OEM specific VK_OEM_102 = &HE2 'Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard ' E3E4 OEM specific VK_PROCESSKEY = &HE5 'Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key ' E6 OEM specific VK_PACKET = &HE7 'Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP ' E8 Unassigned ' E9F5 OEM specific VK_ATTN = &HF6 'Attn key VK_CRSEL = &HF7 'CrSel key VK_EXSEL = &HF8 'ExSel key VK_EREOF = &HF9 'Erase EOF key VK_PLAY = &HFA 'Play key VK_ZOOM = &HFB 'Zoom key VK_NONAME = &HFC 'Reserved for future use VK_PA1 = &HFD 'PA1 key VK_OEM_CLEAR = &HFE 'Clear key End Enum Private m_colKeyMap As New Collection Private Declare Sub keybd_event Lib "user32" ( _ ByVal bVk As Byte, ByVal bScan As Byte, _ ByVal dwFlags As Long, ByVal dwExtraInfo As Long) Private Const KEYEVENTF_EXTENDEDKEY = &H1 Private Const KEYEVENTF_KEYUP = &H2 Private Declare Function GetVersion Lib "kernel32" () As Long Private Declare Function VkKeyScan Lib "user32" Alias "VkKeyScanA" ( _ ByVal cChar As Byte) As Integer Private Declare Function VkKeyScanW Lib "user32" ( _ ByVal cChar As Integer) As Integer Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _ lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long) Private Function nextChar(ByRef sString As String, ByVal iPos As Long, Optional ByVal lLen As Long = 0) As String If (lLen = 0) Then lLen = Len(sString) If (iPos + 1 <= lLen) Then nextChar = Mid$(sString, iPos + 1, 1) End If End Function Public Sub SendKeys(ByVal sKeys As String, Optional ByVal Wait As Boolean) ' The plus sign (+), caret (^), percent sign (%), ' tilde (~), and parentheses ( ) have special ' meanings to SendKeys ' Brackets ([ ]) have no special meaning to SendKeys, ' but you must enclose them in braces. ' To specify brace characters, use {{} and {}}. ' Repeating keys: {LEFT 42} do left 42 times. ' + = Shift ' ^ = Ctrl ' % = Alt ' ~ = enter ' ( = start sub expression. +(EC) = Shift then E then C On Error GoTo errorHandler Dim sMsg As String Dim lErr As Long Dim iPos As Long Dim iNextPos As Long Dim iLen As Long Dim sChar As String Dim colBrace As New Collection Dim sContent As String Dim sKey As String Dim sCount As String Dim lCount As Long iPos = 1 iLen = Len(sKeys) Do While iPos <= iLen sChar = Mid$(sKeys, iPos, 1) Select Case sChar Case "+", "~", "%" If nextChar(sKeys, iPos, iLen) = "(" Then ' Add to brace stack: colBrace.Add sChar ' send key down Select Case sChar Case "+" KeyDown vbKeyShift Case "~" KeyDown vbKeyControl Case "%" KeyDown vbKeyMenu End Select iPos = iPos + 2 Else ' Key press the key (probably not what you wanted) Select Case sChar Case "+" KeyDown vbKeyShift KeyUp vbKeyShift Case "~" KeyDown vbKeyControl KeyUp vbKeyControl Case "%" KeyDown vbKeyMenu KeyUp vbKeyMenu End Select iPos = iPos + 1 End If Case "~" ' Enter key: KeyDown vbKeyReturn KeyUp vbKeyReturn iPos = iPos + 1 Case ")" If (colBrace.Count > 0) Then sChar = colBrace(colBrace.Count) ' send key up Select Case sChar Case "+" KeyUp vbKeyShift Case "~" KeyUp vb