0

I'm running a virtual keyboard when a textbox gets focus, but then keyboard app is focused and will not transfer keys to textbox. If I click on textbox to activate it, everything is fine, but I want my application to get activated after vKeyboard process runs. This is what I've tried so far:

        [DllImport("user32.dll")]
    static extern bool PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll")]
    static extern bool SetForegroundWindow(IntPtr hWnd);
    [DllImport("user32.dll")]
    internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

....

        vKeyboard = Process.Start(keyboardPath);
        SetFocusToApplication(handle);

....

        private static void SetFocusToApplication(IntPtr handle)
    {
        Process currentProcess = Process.GetCurrentProcess();
        IntPtr hWnd = currentProcess.MainWindowHandle;
        if (hWnd != IntPtr.Zero)
        {
            SetForegroundWindow(handle);
            ShowWindow(hWnd,3);
        }
    }

I also tried sending Alt + Tab to keyboard process, but it doesn't work:

        private static void AltTab(IntPtr handle)
    {
             vKeyboard.WaitForInputIdle(); 

       int WM_SYSCOMMAND = 0x0112;
        int SC_PREVWINDOW = 0xF050;
        PostMessage(vKeyboard.MainWindowHandle, WM_SYSCOMMAND, (IntPtr)SC_PREVWINDOW, (IntPtr)0);
    }

PS: I do have the source code for virtual keyboard if I can do anything from there to deactivate itself, still fine. let me know. Also keyboard top most property is set to true, not sure if that makes any different.

This is the code that I'm trying and doenst work in button click:

           Process vKeyboard;
      string keyboardPath = Application.StartupPath + "\\vKeyboard.exe";
        vKeyboard = Process.Start(keyboardPath);
user2495415
  • 3
  • 1
  • 6

4 Answers4

1

To bring your form to front, use:

this.Activate();

I tried the following code and every things works perfectly (I wrote this code in the Timer.Tick event):

System.Diagnostics.Process[] proc = System.Diagnostics.Process.GetProcessesByName("osk");
if (proc.Length > 0)
{
    this.Activate();
    textBox1.Focus(); //i focused it so i can write in it using on-screen keyboard
}
Shaharyar
  • 12,254
  • 4
  • 46
  • 66
  • This is not my form which loses the focus, its the whole application process. I want the application to get focus. – user2495415 Jul 05 '13 at 06:57
  • An application is a process. If you activate its one thread (e.g. Single form out of many forms) so the whole application will be in focus, then you can navigate through form to form. Try this, it will help. – Shaharyar Jul 05 '13 at 07:04
  • I DID call this method after the keyboard process is loaded, but its still not activating my application or main form. – user2495415 Jul 05 '13 at 07:20
  • Thanks, this will work this way but for some reason when I put it on a button click (which is how keyboard process starts in my app) it doesn't work anymore. Any Idea? – user2495415 Jul 05 '13 at 07:56
  • I start the timer when button is clicked and stop it when timer tick is run one time. This will work, thanks. But would have been nice if I could do it without a timer. – user2495415 Jul 05 '13 at 07:59
  • @user2495415 I couldn't understand one thing, when you are executing `On-Screen Keyboard` from the application, then why do you want it to activate it, cause it will already be in focus when you click on button – Shaharyar Jul 05 '13 at 08:07
  • check the update, i'm just simply running a process from button click event. This is another application that I wrote, its not windows on screen keyboard. – user2495415 Jul 05 '13 at 08:28
1

Change the source code for the onscreen keyboard so that the form has the WS_EX_NOACTIVATE flag:

public partial class OnScreenKeyboard : Form
{

    private const int WS_EX_NOACTIVATE = 0x08000000;

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

}

This will prevent the OSK from getting focus, thus allowing the keys to target the currently active application.

See my example in this previous question for more details.

Community
  • 1
  • 1
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
0
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);

private void ActivateWindow()
{
    SetForegroundWindow(this.Handle);
}

With this code, it is suposed you are at the main app window. If not, you will need to change "this.Handle" by the Handle of the main window.

David
  • 59
  • 4
0

For an easy, reliable option that doesn't require you to write P/Invoke code, you can call Microsoft.VisualBasic.Interaction.AppActivate(int processId) from C# code.

using System.Diagnostics;
using System.Linq;
using Microsoft.VisualBasic;
...

Process? process = Process.GetProcessesByName("TextBoxProcessName").FirstOrDefault();
if (process != null)
{
    Interaction.AppActivate(process.Id);
}

In legacy .NET Framework .csproj files, you need <Reference Include="Microsoft.VisualBasic" />. In modern .NET SDK .csproj files, you need to enable the Desktop SDK and set <UseWindowsForms>true</UseWindowsForms>.

Note: I discovered Interaction.AppActivate from this related answer, which may give you other ideas.

Bill Menees
  • 2,124
  • 24
  • 25