Question

I'm wanting to write a virtual keyboard, like windows onscreen keyboard for touchscreen pcs. But I'm having problem with my virtual keyboard stealing the focus from the application being used. The windows onscreen keyboard mantains the focus on the current application even when the user clicks on it. Is there a way to do the same with windows forms in C#?

The only thing I can do for now is to send a keyboard event to an especific application, like notepad in the following code. If I could make the form not focusable, I could get the current focused window with GetForegroundWindow.

[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,string lpWindowName);


[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);

private void button1_Click(object sender, EventArgs e)
{
    IntPtr calculatorHandle = FindWindow("notepad", null);
    SetForegroundWindow(calculatorHandle);
    SendKeys.SendWait("111");
}

Is there a way this can be done? Any suggestions of a better way to have the form sending keyboard events to the application being used?

Thanks!!

Was it helpful?

Solution

Instead of trying to reset the active window after your one has been clicked, I would rather try to prevent your window from receiving focus/being activated.

Have a look at this article. At the end, the author briefly explains how this can be done:

How can I prevent my window from getting activation and focus when shown?

In Windows Forms 2.0 there is a new property called ShowWithoutActivation – which you would need to override on the Form. In native applications you can use SetWindowPos with the SWP_NOACTIVATE flag or the ShowWindow with the SW_SHOWNA flag.

Furthermore, in this article he provides a code example for Windows Forms:

If you want a full-on form, you can now override a property called ShowWithoutActivation:

public class NoActivateForm : Form {  
    protected override bool ShowWithoutActivation {  
        get {  
            return true;  
        }  
    }  
}

Keep in mind this does not “prevent” activation all the time – you can still activate by calling the Activate(), Focus()… etc methods. If you want to prevent clicks on the client area from activating the window, you can handle the WM_MOUSEACTIVATE message.

private const int WM_MOUSEACTIVATE = 0x0021, MA_NOACTIVATE = 0x0003;

protected override void WndProc(ref Message m) {
    if (m.Msg == WM_MOUSEACTIVATE) {
         m.Result = (IntPtr)MA_NOACTIVATE;
         return;
    }
    base.WndProc(ref m);
}

OTHER TIPS

Its solved!

I've tried the solution from gehho, but I also needed to override the CreateParams method:

private const int WS_EX_NOACTIVATE = 0x08000000;
protected override CreateParams CreateParams
    {
        get
        {
            CreateParams createParams = base.CreateParams;
            createParams.ExStyle |= WS_EX_NOACTIVATE;
            return createParams;
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top