1

In C# I want to have a button clicked. I don't want to use a button event like button.click+=... I want to click on the button in Form Application, and any key of my computer will be clicked. I tried SendKeys but it doesn't work well.

I need more ideas how to do it. I tried:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication1
{
public partial class Form5 : Form
{
    Button[,] b;
    List<char> chrlist = new List<char>();
    public Form5()
    {
        InitializeComponent();
        start();
    }

    public void start()
    {
        panel1.Controls.Clear();
        int m = 13;
        int n = 2;
        b = new Button[n, m];
        int x = 0;
        int i, j;
        int y = 0;
        // int count = 0;
        int chr1=(int)'A';
        for (i = 0; i < n; i++)
        {
            for (j = 0; j < m; j++)
            {
                //  count++;
                b[i, j] = new Button();
                b[i, j].SetBounds(x, y, panel1.Size.Width / m, panel1.Size.Height / n);
                b[i, j].Name = i + "," + j;
                b[i, j].Text = ((char)chr1).ToString();
                   b[i, j].Click += new EventHandler(ButtonClick);
                panel1.Controls.Add(b[i, j]);
                x = x + panel1.Size.Width / m;
                chr1++;
            }
            y = y + panel1.Size.Height / n;
            x = 0;
        }
    }

    public void ButtonClick(Object sender, EventArgs e)
    {
        Button a = (Button)sender;
        MessageBox.Show(a.Text);

    }
    public void started()
    {
        while (true)
        {
            int sec = 1000;
            Thread.Sleep(sec * 3);
            SendKeys.SendWait("{TAB}");
        }

    }


    private void button1_Click(object sender, EventArgs e)
    {
        Thread workerThread = new Thread(started);
        workerThread.Start();

    }
}

}

And that didn't work in my other application.

svick
  • 236,525
  • 50
  • 385
  • 514
Asaf Shazar
  • 1,065
  • 1
  • 11
  • 33
  • Can you please edit your question and explain step by step what your program should do in what event, because currently it is quite unclear what you want to happen when what is clicked or pressed. – CodeCaster Jun 08 '13 at 14:16
  • 2
    Pretty classic usability complaint. The keyboard doesn't have an "Any key" key. You can't click it in your code either. Doing this right requires pinvoke to use SendInput(). You might want to leave that one on the shelf until you've gained some experience. Things that might *seem* to be easy to do are not always easy. Messing with another program you didn't write is certainly in the "not easy" category. – Hans Passant Jun 08 '13 at 14:27

1 Answers1

3

It looks to me like you're attempting to build an onscreen keyboard.

Premise: Use SendKeys to send a letter to the active application.

Question: When you click the button in your Form to send a letter, what application has focus?

Answer: Yours. Therefore the key will be sent to your application, not the last application that was focused.

Solution: Prevent your application from getting focused.

This can be accomplished by setting the WS_EX_NOACTIVATE flag in your extended window styles via CreateParams()

    private const int WS_EX_NOACTIVATE = 0x08000000;

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams p = base.CreateParams;
            p.ExStyle |= WS_EX_NOACTIVATE;
            return p;
        }
    }

    public void ButtonClick(Object sender, EventArgs e)
    {
        SendKeys.Send(((Control)sender).Text);
    }

Now when you click a button in your OSK, the currently focused application will STAY focused (because your application cannot receive focus) and SendKeys() will correctly target it.

*Caveats: This only works if the onscreen keyboard is a different application. In other words, the OSK cannot target other forms in your own application...it's a weird focus thing. To target your own app you'd have to manually track the last form in your application and give it focus again before sending the keys.

Here's your OSK sending keys to Notepad: Onscreen Keyboard Example

This is ALL of the code in my test app:

public partial class Form1 : Form
{
    private Button[,] b;

    private const int WS_EX_NOACTIVATE = 0x08000000;

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams p = base.CreateParams;
            p.ExStyle |= WS_EX_NOACTIVATE;
            return p;
        }
    }

    public Form1()
    {
        InitializeComponent();
        start();
    }

    public void start()
    {
        panel1.Controls.Clear();
        int m = 13;
        int n = 2;
        b = new Button[n, m];
        int x = 0;
        int i, j;
        int y = 0;
        // int count = 0;
        int chr1 = (int)'A';
        for (i = 0; i < n; i++)
        {
            for (j = 0; j < m; j++)
            {
                //  count++;
                b[i, j] = new Button();
                b[i, j].SetBounds(x, y, panel1.Size.Width / m, panel1.Size.Height / n);
                b[i, j].Name = i + "," + j;
                b[i, j].Text = ((char)chr1).ToString();
                b[i, j].Click += new EventHandler(ButtonClick);
                panel1.Controls.Add(b[i, j]);
                x = x + panel1.Size.Width / m;
                chr1++;
            }
            y = y + panel1.Size.Height / n;
            x = 0;
        }
    }

    public void ButtonClick(Object sender, EventArgs e)
    {
        SendKeys.Send(((Control)sender).Text);
    }

}
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
  • but what is it do: private const int WS_EX_NOACTIVATE = 0x08000000; protected override CreateParams CreateParams { get { CreateParams p = base.CreateParams; p.ExStyle |= WS_EX_NOACTIVATE; return p; } } public void ButtonClick(Object sender, EventArgs e) { SendKeys.Send(((Control)sender).Text); } – Asaf Shazar Jun 08 '13 at 18:56
  • It adds the WS_EX_NOACTIVATE flag to the extended window styles for your form. See [Extended Window Styles](http://msdn.microsoft.com/en-us/library/windows/desktop/ff700543(v=vs.85).aspx) for more information. – Idle_Mind Jun 08 '13 at 19:04
  • "WS_EX_NOACTIVATE - A top-level window created with this style does not become the foreground window when the user clicks it." – Idle_Mind Jun 08 '13 at 19:05
  • Awesome. Click that up arrow and/or the checkmark so others know your problem is solved... – Idle_Mind Jun 08 '13 at 23:24