edit ... October 14 ...
Code I posted on the C# forum after I wrote this response that will allow you to handle arrow-keys, keeping a Control inside the borders of a specific ContainerControl: [
^]
... end edit ...
It is not clear to me exactly what you wish to move in response to arrow-key Events if a Button has been clicked (or, did you mean while a Button is pressed ?), but your code to handle arrow-key Events has to know which Control on the Form to move.
If you define a KeyDown EventHandler for a Button, it will only handle arrow-keys if a modifier key, like <Control>, is held down. A KeyPress EventHandler will not handle arrow-key events.
To get arrow-key Events in WinForms without a modifier key held down, you'll need to use an over-ride of the ProcessCmdKey method, and that will apply to the Form as a whole. Or, you can get into using PInvoke and the Windows API to get those key Events at a "lower level."
The idea of using a Button as the "sink" for key Events is very unusual, and I think not a good design decision.
Here's a solution idea which could move any Control on the Form that has Focus, but it does
require a modifier key, like <Control> held down to work.
1. set the 'KeyPreview property of the Form in the design-time Property Grid to 'true.
2. write a KeyDown Event Handler:
private void FormTemplate_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Control) return;
Control controlToMove = ActiveControl;
switch (e.KeyCode)
{
case Keys.Left:
controlToMove.Left -= 1;
break;
case Keys.Right:
controlToMove.Left += 1;
break;
case Keys.Up:
controlToMove.Top -= 1;
break;
case Keys.Down:
controlToMove.Top += 1;
break;
}
}</control>
Now, if you use this you may be surprised: some of the Controls on a Form that it might be most desirable to move are Container Controls, like Panels. A Panel never becomes the ActiveControl on a Form.
So, if you want to make this solution more "robust," and handle moving something like a Panel, you are going to have to come up with a way for the Form scoped KeyDown EventHandler to "know" which Panel, or other Container Control, it needs to move.
You might think you can simply use the 'GetChildAtPoint method of the Form:
Control controlToMove;
private void FormTemplate_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Control || ActiveControl == null) return;
controlToMove = this.GetChildAtPoint(this.PointToClient(MousePosition));
if (controlToMove == null) return;
switch (e.KeyCode)
{
case Keys.Left:
controlToMove.Left -= 1;
break;
case Keys.Right:
controlToMove.Left += 1;
break;
case Keys.Up:
controlToMove.Top -= 1;
break;
case Keys.Down:
controlToMove.Top += 1;
break;
}
}
Well, now you can move Panels, but you have another problem: Controls inside Panels that you click on and select will not move, but their containing Panel will. This is an artifact of the way that 'GetChildAtPoint works (or, from my point of view, doesn't work).
So, to really make this a robust solution, you need to find a way to get any Control or Container Control inside any arbitrary number of Container Controls set as the "target" of your Form scoped arrow-key EventHandler.
A cheap way to get around this is: at design-time is to select all Controls on the Form, and define a Click EventHandler they all share:
private void AllControls_Click(object sender, EventArgs e)
{
controlToMove = sender as Control;
}
And, make sure that a click on the Form "resets" arrow-key event handling:
private void SomeForm_Click(object sender, EventArgs e)
{
controlToMove = null;
}
. Well, "cheap" does not equal "elegant," but, it works.
And now, after all this, the question remains in my mind: is it really a
good thing to have run-time moving of Controls in this way. My "gut" says: "no," unless it's some very special circumstance. imho, what's demonstrated here is too much work :)
There are, after all, other standard ways of enabling Controls to move at run-time, via MouseDown, MouseMove, MouseUp; you can even put up a PropertyGrid Control at run-time and let the user edit the pixel locations of Controls.
How often do you really need to move
every Control on a Form at run-time ?