2

I added an option to move a control at runtime with the mouse, based on this and it's working well.

But I was trying to find some code to do the same trick but with the keyboard -- pretty much like moving a component at design time (only moving).

How can this be achieved?

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
O-Zamzam
  • 21
  • 2

1 Answers1

4

This is very easy if you know how to do the different parts of it.

  1. Create a new VCL application.

  2. Drop a TShape on the form.

  3. Add the following OnKeyDown event handler to the form:

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
const
  D = 2;
begin
  case Key of
    VK_UP:
      Shape1.Top := Shape1.Top - D;
    VK_DOWN:
      Shape1.Top := Shape1.Top + D;
    VK_LEFT:
      Shape1.Left := Shape1.Left - D;
    VK_RIGHT:
      Shape1.Left := Shape1.Left + D;
  end;
end;
  1. Run the application.

This being said, however:

Creating animations by moving controls on a form is wrong.

Instead, if you want to create animations, the right thing to do is to draw them manually using GDI, GDI+, OpenGL, or DirectX/Direct2D. Here is my standard example of how to do this.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • Your example will work only if there are no other components that are capable of handling keyboard input on their own. In order to allow Form to handle keyboard input in such scenarios you should also set `KeyPreview` property of the said form to True. – SilverWarior Nov 26 '20 at 17:03
  • @SilverWarior: Correct. But typically, when a form handles the arrow keys, it is used without any controls at all: it's merely a drawing canvas. I almost consider `KeyPreview = True` to be an indication that you aren't doing things in the most appropriate way. – Andreas Rejbrand Nov 26 '20 at 17:23
  • Well title of the question is `How can I move a control in Delphi at runtime using the keyboard?` therefore I assume OP has multiple controls on the form already. – SilverWarior Nov 27 '20 at 01:41
  • @SilverWarior: They might very well be non-windowed controls (`TLabel`, `TShape`, `TImage`, ...) in which case everything is OK. On the other hand, if the form contains controls of classes `TButton`, `TRadioButton`, `TCheckbox` etc., stealing the arrow keys is very much undesirable in the first place because they are used to move focus. Even worse, if you have `TEdit`, `TListBox`, `TComboBox`, `TMemo`, `TRichEdit`, `TListView` etc., arrow keys are integral to their own UI. In this case, you mustn't steal the arrows. In between, there is a small region where `KeyPreview` would indeed be useful. – Andreas Rejbrand Nov 27 '20 at 07:31
  • The point is that the OP contains too little information for us to know exactly what the solution is. – Andreas Rejbrand Nov 27 '20 at 07:31
  • (So it might have been wrong of me to post an answer instead of a comment requesting such additional details.) – Andreas Rejbrand Nov 27 '20 at 07:47
  • really appreciate your concern, my application have many forms and I use the code I provided in the link to make user able to change labels, buttons, combos.. most of the component actually using mouse after they use specific keyboard shortcut. – O-Zamzam Nov 29 '20 at 08:18
  • Then all of these new top and lefts are saved on ini file used then to place this component on screen while painting it. – O-Zamzam Nov 29 '20 at 08:20
  • What i want instead of moving this component with mouse (not easy and lose accuracy) i want to move it with keyboard like moving them in design time. arrows move between components and ctrl+arrows move them. – O-Zamzam Nov 29 '20 at 08:23
  • O-Zamzam: I think that is probably a bad idea. For instance, in an edit control, Left and Right move the caret one character left and right, Shift+Left and Shift+Right extend the selection one character left and right, Ctrl+Left and Ctrl+Right move the caret one word left and right, and Shift+Ctrl+Left and Shift+Ctrl+Right extend the selection one word left and right. So the form shouldn't steal those keyboard commands. As a user, I'd immediately abandon a Windows application (and the entire company making it!) if Ctrl+arrows (say) don't work in edit controls! – Andreas Rejbrand Nov 29 '20 at 12:13
  • Good point there but moving controls only triggered with special keyboard short cut (Ctrl + M) – O-Zamzam Nov 30 '20 at 10:05
  • @O-Zamzam: Then I have no objections! – Andreas Rejbrand Nov 30 '20 at 10:12
  • I manage to right some code for moving, got the idea from your first answer but problem i am facing i cant move on all controls by keyboard for instance labels. – O-Zamzam Nov 30 '20 at 10:53
  • `TLabel` controls are not windowed controls (no HWNDs, so they are not windows in the Win32 sense), but graphic controls. That might be the crucial difference. But since I don't have access your code, I cannot possibly tell what the problem is. `TLabel` controls certainly can be moved within their parent control (which *is* a window) by adjusting their `Top` and `Left` properties. But the control intercepting the keystrokes must be the parent (or some other control), since a graphic control cannot respond to keystrokes. – Andreas Rejbrand Nov 30 '20 at 10:57
  • I am afraid you have to create a new question with a complete, minimal (as small as possible), reproducible example of the particular issue. – Andreas Rejbrand Nov 30 '20 at 10:59