9

I made an on screen keyboard with c# Windows Forms. I use Sendkeys.Send() function to send the keystrokes. All letters but the letter i works fine. When I press the letter i on the keyboard when Microsoft Word is open, it sends Ctrl + Alt + I and opens the print dialog. It is same in Notepad++ as well. But it works fine when I try to type in notepad.

In my code I send the keys with SendKeys.Send(value); where value is the text of the button which is pressed. I get the text with the following code:

string s = ((Button)sender).Text;

Any comments about why it does not work properly?

Edit: I have created a new windows forms project with just a button and the whole code is below. Still not working. Any idea would be appreciated.

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

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

        // Prevent form being focused
        const int WS_EX_NOACTIVATE = 0x8000000;
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams ret = base.CreateParams;
                ret.ExStyle |= WS_EX_NOACTIVATE;
                return ret;
            }
        }  
    }

The overridden function is to prevent the form being focused. So that I can send the keystrokes to the other application which has the focus.

jezrael
  • 822,522
  • 95
  • 1,334
  • 1,252
Ozgur Dogus
  • 911
  • 3
  • 14
  • 38
  • Is it definately at this part of the code? What is `value`, this is not a keyword? You might in some cercumstance find that rather than casting with `((MyClass)object)` that casting using `(object as MyClass)`. The second will return null if obj isn't a MyClass, rather than throw a class cast exception. – MoonKnight Jan 26 '12 at 09:37
  • Im so sorry. it would be string s instead of value s.The result does not change even I do it like this: Sendkeys.Send("i"); – Ozgur Dogus Jan 26 '12 at 12:33
  • Did you use a debugger to check what value `s` is getting? This will help you narrow down the problem. – Kendall Frey Jan 26 '12 at 13:40
  • Yes, the value of the string is "i" in Sendkeys function in debugger. I created a button and added in onclick event did Sendkeys.Sends("i") but the result didn't change. – Ozgur Dogus Jan 26 '12 at 13:53
  • So it's not a dotless ı with a dot accent? – Mr Lister Jan 26 '12 at 14:57
  • @MrLister its just little I not dotless. Thanks – Ozgur Dogus Jan 26 '12 at 15:25
  • I tested this on Windows Server 2008 R2 using VS 2010. It seems to work fine with the letter i. You may be running into a timing issue or something along those lines. See http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx. See the fact that they implementation has changed in .NET 3.5. Have you tried SendWait or doing a Flush before doing a Send? – Dave Ferguson Jan 29 '12 at 17:03
  • 1
    @DaveFerguson I realised that the problem is cause I have a Turkish os. The code works well if i change the language to english. but doesnt work in Turkish. now first i detect the interface language of the current application and send the key depending on the language. i do it with Sendkeys.Send("+{I}") when the interface is English. I can send detailed answer if anyone needs it. Thanks for all the answers... – Ozgur Dogus Jan 31 '12 at 07:51

2 Answers2

1

Your aren't calling the "SetForegroundWindow" Win32 API method. Therefore, your "SendKeys" call is likely sending the keys to your app, not the target app as intended.

Here's an example on MSDN:

How to: Simulate Mouse and Keyboard Events in Code

Also, here's the code from the example:

using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;

namespace SimulateKeyPress
{
    class Form1 : Form
    {
        private Button button1 = new Button();

        [STAThread]
        public static void Main()
        {
            Application.EnableVisualStyles();
            Application.Run(new Form1());
        }

        public Form1()
        {
            button1.Location = new Point(10, 10);
            button1.TabIndex = 0;
            button1.Text = "Click to automate Calculator";
            button1.AutoSize = true;
            button1.Click += new EventHandler(button1_Click);

            this.DoubleClick += new EventHandler(Form1_DoubleClick);
            this.Controls.Add(button1);
        }

        // Get a handle to an application window.
        [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
        public static extern IntPtr FindWindow(string lpClassName,
            string lpWindowName);

        // Activate an application window.
        [DllImport("USER32.DLL")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        // Send a series of key presses to the Calculator application.
        private void button1_Click(object sender, EventArgs e)
        {
            // Get a handle to the Calculator application. The window class
            // and window name were obtained using the Spy++ tool.
            IntPtr calculatorHandle = FindWindow("CalcFrame","Calculator");

            // Verify that Calculator is a running process.
            if (calculatorHandle == IntPtr.Zero)
            {
                MessageBox.Show("Calculator is not running.");
                return;
            }

            // Make Calculator the foreground application and send it 
            // a set of calculations.
            SetForegroundWindow(calculatorHandle);
            SendKeys.SendWait("111");
            SendKeys.SendWait("*");
            SendKeys.SendWait("11");
            SendKeys.SendWait("=");
        }

        // Send a key to the button when the user double-clicks anywhere 
        // on the form.
        private void Form1_DoubleClick(object sender, EventArgs e)
        {
            // Send the enter key to the button, which raises the click 
            // event for the button. This works because the tab stop of 
            // the button is 0.
            SendKeys.Send("{ENTER}");
        }
    }
}
Chris Pietschmann
  • 29,502
  • 35
  • 121
  • 166
  • I just made my application nonfocusable. So always the last application is focused even after I click my button on my application. Is this approach wrong ? It works when i try it on notepad and wordpad but does not work on ms word and notepad++ – Ozgur Dogus Jan 26 '12 at 15:24
1

Two alternatives:

1- Simulates a keypress, see http://msdn2.microsoft.com/en-us/library/system.windows.forms.sendkeys(VS.71).aspx

Sample:

public static void ManagedSendKeys(string keys)
        {
            SendKeys.SendWait(keys);
            SendKeys.Flush();
        }

2- Sends a key to a window, pressing the button for x seconds

[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
public static void KeyboardEvent(Keys key, IntPtr windowHandler, int delay)
        {
            const int KEYEVENTF_EXTENDEDKEY = 0x1;
            const int KEYEVENTF_KEYUP = 0x2;
            keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY, (UIntPtr)0);
            Thread.Sleep(delay);
            keybd_event((byte)key, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, (UIntPtr)0);
        }
Marcos
  • 90
  • 6