So since I'm using a Label as the handle that the SFML Render Window (just "SFML" for short) draws on. So I'm no longer using any of SFML's own events. Instead, I'm using the C++/CLI Winforms interface. However there are times when I want key presses and mouse clicks to be directed to SFML (or rather, certain key presses and mouse clicks should activate code that does something to SFML).
Since I'm using a Label, which cannot gain focus, I need to handle key presses globally (within the form at least). In other words, I need hot keys. Here are some simple examples of what kind of hot keys I'd like (please don't worry about how I make things happen in the SFML, the point is catching the hot keys).
1) When I press 'R', the graphics should reset.
2) When I press 'L', new graphics should be loaded.
3) If I hold Ctrl and click on the SFML, something will happen at the location I clicked.
4) If I hold the Spacebar and mouse drag on the SFML, things will be moved around.
5) If some TextBox control has focus, then key presses should go to the text box and not activate the hot keys.
6) If I MouseClick on some Button control and then start clicking on the SFML and at some point press the Spacebar, the Button should not be clicked again. (Remember, this SFML cannot have focus, so the button I pressed before still has focus.)
So that's what I'd like to do. Here is what I've tried so far:
A) To catch all hot keys, I set the form's KeyPreview property to true. This makes all key presses go to the form before any other controls. Then I simply handle KeyDown, KeyUp, or KeyPress events for the form.
B) To make sure typing in text boxes doesn't activate hot keys, in the KeyDown, KeyUp, or KeyPress events for the form, I check if any text boxes have focus before doing anything with the event, e.g.:
if (ActiveControl->Name != "textBox1" && ActiveControl->Name != "textBox2")
{ handleHotKey(e); }
TextBoxes actually have a PreviewKeyDown event that fires before the Form's KeyPreview, but I'm not sure how I would use it. It fires even before the text enters the TextBox, so setting the event.handled to true actually prevents the text from appearing.
C) To prevent buttons from being activated by the Spacebar, I used the MouseClick event for the buttons instead of the Click event, so only an actual MouseClick on the button will make anything happen. While this works, the Spacebar still activates the button's clicking animation.
Instead of a Label, I've also considered using a TextBox as the handle given to the SFML Render Window. But there are a few problems with this as well. When the TextBox gains or loses focus, it redraws itself, causing a flicker in SFML. When it has focus, even with no text and read only, it still shows the typing/selection caret blinking (disabling the TextBox fixes that, but then it can no longer gain focus). If there was a way to prevent the TextBox from repainting, that could fix the problem. However, even if those problems were fixed, the idea that the TextBox could lose focus by clicking on Buttons and other things seems bad. If I click on some Button (giving it focus), and then hit some hot key, it should still fire off the event.
Basically, it should be assumed that all keyboard events could be doing something to the SFML Render Window, where the exceptions are things like text boxes having focus. Another way to think of it is that the SFML Render Window should always have focus (again, except for TextBoxes, etc).
So far, my methods with the Label all seems to work, but they just feel a bit clumsy. Any suggestions on how to improve this would be appreciated.
Edit: Someone on Stack Overflow had this to say: "Well, don't pick a Label. And definitely not a TextBox. Just make your own Control derived class." Not so sure about that.