Make a form not focusable in C#
Asked Answered
A

2

14

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!!

Apanage answered 11/3, 2010 at 7:22 Comment(0)
M
9

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 => 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);
}
Mosa answered 11/3, 2010 at 7:40 Comment(2)
Thanks! Its halfway done! That article solution prevents my form from gaining focus, but does not prevent the other app from losing focus. That is, when I click on my app I get to the situation where none apps has the focus.Apanage
In case the links become invalid, your answer contains basically no information at all. Please summarize the off-site resources, so that your answer continues to be valuable, even if the off-site resources die.Cistercian
A
16

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
    {
        var createParams = base.CreateParams;

        createParams.ExStyle |= WS_EX_NOACTIVATE;
        return createParams;
    }
}
Apanage answered 11/3, 2010 at 19:42 Comment(7)
Shouldn't you technically add to createParams.ExStyle, instead of replacing it entirely? (e.g., createParams.ExStyle |= WS_EX_NOA[...];)Huskamp
I edited the code in the answer to effect that changeBacteroid
@DavidHeffernan ok so you edited it to effect the change suggested by Jesse?Broomrape
@Broomrape Yes. You can see that clearly in the answer as it stands now, and you can see the edit history by clicking on the text "edited Apr ...."Bacteroid
@DavidHeffernan yeah I am not advanced enough to know what jesse meant about the .ExStyle I saw the edit with a pipe symbol added I wasn't sure that was all that jesse meant. Thanks for confirming.Broomrape
I find this code works on its own, and that I don't need to also use the code that gehho mentioned. Did you find any advantage in adding the code gehho mentioned? I find gehho's code doesn't work for me but this one does. Not as a supplement to it but just alone itself.Broomrape
This solution also worked for me by itself. Perfect for an on-screen keyboard.Tamatamable
M
9

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 => 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);
}
Mosa answered 11/3, 2010 at 7:40 Comment(2)
Thanks! Its halfway done! That article solution prevents my form from gaining focus, but does not prevent the other app from losing focus. That is, when I click on my app I get to the situation where none apps has the focus.Apanage
In case the links become invalid, your answer contains basically no information at all. Please summarize the off-site resources, so that your answer continues to be valuable, even if the off-site resources die.Cistercian

© 2022 - 2024 — McMap. All rights reserved.