I want to create a virtual numpad, similar to the on-screen keyboard. How do I prevent the form from ever being activated/focused, so that when I push a button on it, the SendKeys.Send call goes to the right form? I'm certain I have to use an unmanaged API for this, but besides that I'm not even sure where to begin. Thanks for any help!
A form that does not have focus generally does not receive keyboard input. So I am not sure how you would get this to work.
If the numpad only needs to work in apps that you write, you could just keep track of the last valid input control that had focus. That way you don't have to fret about something stealing focus. I recently did something similar by subscribing a bunch of TextBoxes' Enter event to the same event handler that set my focused control handle to the sender parameter. This exact method may not work for you, but the approach might make it easier.
With apps you write, consider the Observer pattern.
In the general case you can add a Subscribe method to your keypad that takes a delegate (also allow for Unsubscribing). For your key press event handling, loop through all the subscribed delegates sending it the character code.
Code (mostly from memory, snippets probably won't compile but should get you going)
delegate void KeyPadSubscription (char keyPressed);
List<KeyPadSubscription> subscriptions;
void KeyPress (object sender, KeyPressArgs e)
{
foreach (KeyPadSubscription sub in subscriptions)
sub (e.CharCode)
}
void Subscribe(KeyPadSubscription s)
{
subscriptions.Add(s);
}
void Unsubscribe(KeyPadSubscription s)
{
subscriptions.Remove(s);
}
In your case, you probably don't need the list of delegates and a property could suffice. Then as your forms change focus, the active form would set its method as the delegate for your keypad.
void MyForm_Activated(...)
{
//assumes keypad is global or static
KeyPad.Subsribe (this.HandleKeyPadPress)
}
You can control the way your form is created by overriding the protected CreateParams property:
protected override CreateParams CreateParams {
get {
var cp = base.CreateParams;
// Configure the CreateParams structure here
return cp;
}
}
I suggest trying the following style:
int WS_EX_NOACTIVATE = 0x08000000;
cp.ExStyle = cp.ExStyle | WS_EX_NOACTIVATE;
The WS_EX_NOACTIVATE
style prevents mouse input from giving a window focus (you can use this to create tooltip-like windows, for example.)
You can combine this with other styles (like WS_EX_TOPMOST
) to get the behavior you're after.