Asaf Shazar
Asaf Shazar

Reputation: 1065

Click on button and that will click on Key

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.

Upvotes: 1

Views: 1573

Answers (1)

Idle_Mind
Idle_Mind

Reputation: 39142

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);
    }

}

Upvotes: 3

Related Questions