Virtual number pad

Daniel Hoover 30 Reputation points
2023-01-19T22:09:57.4+00:00

Hello, I'm quite new and i wanna have a winforms ui for a industrial machine and im pretty much done. it will have a touch screen and i want the user to be able to use a virtual keyboard. that virtual keyboard is on a separate form and i use the "send.keys" to type the number into the main form.

when i click the input textbox on the main form the numpad form pops up, All Good

My problem is that as soon as i click a number on the numpad, the numpad form highlights/focuses and the number goes nowhere.

i want the number that i click going to the main form textbox

Very simple fix but im green yet lol :)

Developer technologies | Windows Forms
Developer technologies | C#
{count} vote

Accepted answer
  1. Reza Aghaei 4,986 Reputation points MVP Volunteer Moderator
    2023-01-19T22:33:16.1233333+00:00

    If you show the numpad buttons in the same form

    I've answered a similar questions here: How to create a Button that can send keys to a control without stealing the focus - Virtual Keyboard

    You need to makes the buttons non-selectable, then clicking on it will not steal the focus:

    public class ExButton:Button
    {
        public ExButton()
        {
            SetStyle(ControlStyles.Selectable, false);
        }
    }
    

    Then handle click event and send key:

    private void exButton1_Click(object sender, EventArgs e)
    {
        SendKeys.SendWait("A");
    }
    

    You can just easily replace all your button controls with MyButton (in the designer.cs), or at design time. But if for any reason you do not want to replace the buttons, you can rely on the following extension method:

    public static class Extensions
    {
        public static void SetStyle(this Control control, ControlStyles flags, bool value)
        {
            Type type = control.GetType();
            BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
            MethodInfo method = type.GetMethod("SetStyle", bindingFlags);
            if (method != null)
            {
                object[] param = { flags, value };
                method.Invoke(control, param);
            }
        }
    }
    

    And use it like this:

    this.button1.SetStyle(ControlStyles.Selectable, false);
    

1 additional answer

Sort by: Most helpful
  1. Reza Aghaei 4,986 Reputation points MVP Volunteer Moderator
    2023-01-22T21:23:59.6733333+00:00

    If you show another form as numpad

    If you show another form as numpad, then you need to make sure the form is not focusable and will not activate when showing:

    using System;
    using System.ComponentModel;
    using System.Windows.Forms;
    public partial class VirtualNumPadForm : Form
    {
        public VirtualNumPadForm()
        {
            InitializeComponent();
            this.StartPosition = FormStartPosition.Manual;
            this.BackColor = System.Drawing.Color.Black;
        }
        private const int WS_CHILD = 0x40000000;
        private const int WS_EX_NOACTIVATE = 0x08000000;
        private const int WS_EX_TOPMOST = 0x00000008;
        protected override bool ShowWithoutActivation => true;
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams p = base.CreateParams;
                p.Style = WS_CHILD;
                p.ExStyle |= WS_EX_NOACTIVATE | WS_EX_TOPMOST;
                return p;
            }
        }
        protected override void OnClosing(CancelEventArgs e)
        {
            e.Cancel = true;
            this.Hide();
            base.OnClosing(e);
        }
    }
    

    Note: If you are using this as a separate exe, then do not set p.Style = WS_CHILD but if it's inside the same process, set it.

    Then handle click event of the numpad buttons like this:

    private void button1_Click(object sender, EventArgs e)
    {
        SendKeys.SendWait("1");
    }
    

    Now, let's say you want to show the form, when textBox1 gets focus and hid it when it lose focus:

    VirtualNumPadForm vnumPadForm = new VirtualNumPadForm();
    private void textBox1_Enter(object sender, EventArgs e)
    {
        vnumPadForm.Location = PointToScreen(new Point(textBox1.Right, textBox1.Top));
        vnumPadForm.Show();
    }
    private void textBox1_Leave(object sender, EventArgs e)
    {
        vnumPadForm.Hide();
    }
    
    1 person found this answer helpful.
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.