Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Make control "not focusable"

Status
Not open for further replies.

MangroBongacello

Programmer
Mar 20, 2001
189
SI
Hi!

I created a control that I will use as keys for keyboard for touch screen. The problem I have is how not to take focus away from for instance textbox, when this control is clicked (like label control).

Thank you
Mangro
 
Look at it diferently.
Give focus back to the control that had the focus.

Christiaan Baes
Belgium

My Blog
 
Without really understanding what you are trying to accomplish, you could disable the textbox while the user is interacting with the label control. This would remove the cursor from the textbox.

You could also change the focus to another object in the Label1.Click event.
 
Most controls have a TabStop property. Simply set this to false.
 
I would like to act it like a keyboard. For example if in the textbox there is currently a word "TEST" and the caret is at position 2 (before letter E), then if the user touches this control that sends letter X, the text in the text box would be "TXEST" and the caret would be positioned again before letter E (really just like using keyboard).
 
Well this works for me.

Code:
Private Sub Buttons_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnA.Click, btnB.Click, btnC.Click, btnD.Click, btnE.Click, btnF.Click
        Me.TextBox1.AppendText(sender.name.ToString.Remove(0, 3))
        Me.TextBox1.Focus()
    End Sub


Christiaan Baes
Belgium

My Blog
 
Thank you, Christiaan, but the problem with this is, that this appends text at end and not at the current position, plus other controls (like ComboBox) do not have the AppendText methods. Plus, I might be sending also other characters (like BackSpace). The functionality, that I will like to achieve, is like calling a SendKey from Label_Click event, where the key is sent to whichever control, that has focus at that moment.
 
If you want to send a key after a user clicks on a label control then System.Windows.Forms.SendKeys class seems to be your best bet, especially if you are planning on sending control keys.
 
I've actually built an on-screen keyboard. It has a few form focus issues left but it works the way you are describing.

I used Checkboxes for the buttons (styled as buttons) because of the Shift keys - has to stay shift until pressed again.

Here is the relevant code I used to trigger a keypress:
Code:
Private Sub cmd_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles cmd_A.MouseDown, cmd_B.MouseDown
    Dim ky As Keys = GetKey(CType(sender, CheckBox))
    doKeyDown(ky)
End Sub

Private Sub cmd_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles cmd_A.MouseUp, cmd_B.MouseUp
    Dim ky As Keys = GetKey(CType(sender, CheckBox))
    doKeyUp(ky)
End Sub
Those handles events actually go on much longer, but don't cover every button on the keyboard - I have different handlers for Shift keys, NumLock, etc.

The GetKey function just returns a Keys object depicting the key that was pressed based on the button that was clicked.

To actually trigger the keyboard keypress you have to simulate the Key Down and Key Up with the API.

Here is the relevant API functions:
Code:
    <DllImport("user32.dll")> _
    Private Function SendInput(ByVal cInputs As Integer, ByRef pInputs As INPUT, ByVal cbSize As Integer) As Integer
    End Function

    <StructLayout(LayoutKind.Explicit)> _
    Private Structure INPUT
        <FieldOffset(0)> Dim dwType As Integer
        <FieldOffset(4)> Dim mouseInput As MOUSEINPUT
        <FieldOffset(4)> Dim keyboardInput As KEYBDINPUT
        <FieldOffset(4)> Dim hardwareInput As HARDWAREINPUT
    End Structure

    <StructLayout(LayoutKind.Explicit)> _
    Private Structure KEYBDINPUT
        <FieldOffset(0)> Public wVk As Short
        <FieldOffset(2)> Public wScan As Short
        <FieldOffset(4)> Public dwFlags As Integer
        <FieldOffset(8)> Public time As Integer
        <FieldOffset(12)> Public dwExtraInfo As IntPtr
    End Structure

    <Flags()> _
    Friend Enum KEYEVENTF As Integer
        EXTENDEDKEY = 1
        KEYUP = 2
        [UNICODE] = 4
        SCANCODE = 8
    End Enum

    Public Function doKeyDown(ByVal key As Keys) As Integer
        Dim flags As KEYEVENTF = 0
        Return DoKey(flags, key)
    End Function

    Public Function doKeyUp(ByVal key As Keys) As Integer
        Dim flags As KEYEVENTF = KEYEVENTF.KEYUP
        Return DoKey(flags, key)
    End Function

    Private Function DoKey(ByVal flags As KEYEVENTF, ByVal key As Keys) As Integer
        Dim input As New INPUT
        Dim ki As New KEYBDINPUT
        input.dwType = InputType.Keyboard
        input.keyboardInput = ki
        input.keyboardInput.wVk = Convert.ToInt16(key)
        input.keyboardInput.wScan = 0
        input.keyboardInput.time = 0
        input.keyboardInput.dwFlags = flags
        input.keyboardInput.dwExtraInfo = IntPtr.Zero
        Dim cbSize As Integer = Marshal.SizeOf(GetType(INPUT))
        Return SendInput(1, input, cbSize)
    End Function

The trick is in ignoring focus. I don't know if the "keyboard" you are going to be providing is going to be in its own separate form or not (separate from the input controls - textbox, combobox...). If it's going to be on the same form - then I would go with the suggestion of tracking which input has focus and switching back. If it's going to be it's own form - like the MS On-screen Keyboard - then you'll need to override the CreateParams property of the form to provide parameters that will keep it from stealing focus like so:

Code:
    Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
        Get
            'Return MyBase.CreateParams
            ' This sets the window up as not "stealing" focus (NOACTIVATE)
            ' Unfortunately, the dropdown lists force activation!!
            Const WS_EX_NOACTIVATE As Integer = &H8000000
            Const WS_CLIPCHILDREN As Integer = &H2000000
            Const WS_THICKFRAME As Integer = &H40000
            Const WS_EX_CONTROLPARENT As Integer = &H10000
            Dim Result As CreateParams
            Result = MyBase.CreateParams
            Result.Style = Result.Style And Not WS_CLIPCHILDREN And Not WS_THICKFRAME
            Result.ExStyle = (Result.ExStyle Or WS_EX_NOACTIVATE) And Not WS_EX_CONTROLPARENT
            'Result.ClassStyle = &H14CA0000
            'Result.ExStyle = &H8040108
            Return Result
        End Get
    End Property

I hope that helps you out.
 
Thanks everybody for your replies. I found the solution that best suits my needs. For thos who might be interrested:

I overrided the WndProc procedure to ignore the "left mouse button down" message.

Code:
    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If m.Msg <> &H201 Then 'process message, unless it's left button down
            MyBase.WndProc(m)
        Else
            'send the assigned key sequence
            Dim K As New Microsoft.VisualBasic.Devices.Keyboard
            K.SendKeys(Me.SendKeySequence, True)
        End If
    End Sub

This way, when the user clicks my button, the focus remains on whichever controls it is at that moment, and the focused control receives the keystroke, just like from keyboard.

Mangro
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top