1

the title doesn't say a lot of things, so let me explain:

I have made an application form in which i put 1 image and 4 buttons. Whenever i press the keys: up, down, left, right, to move the image, it selects me the buttons, insteed of moving the image. For example, if i press the down key, it will select me the button2, if i press up, it will select me the button1....

I am sry, i cannot really describe it how exactly it looks like, try it at your form and you will see what i mean, the code is this:

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
    VK_UP:
      image1.Top := image1.Top - 10;
    VK_DOWN:
      image1.Top := image1.Top + 10;
    VK_LEFT:
      image1.Left := image1.Left - 10;
    VK_RIGHT:
      image1.Left := image1.Left + 10;
   end;
end;
user2296565
  • 243
  • 1
  • 7
  • 18
  • Use buttons (and all other controls) that can't get focus, like `TSpeedButton` for instance. – TLama Apr 19 '13 at 14:02
  • 2
    @LURD: That doesn't matter. – Andreas Rejbrand Apr 19 '13 at 14:06
  • See [`Delphi XE and Trapping Arrow Key with OnKeyDown`](http://stackoverflow.com/q/8620703/576719). – LU RD Apr 19 '13 at 14:11
  • @AndreasRejbrand, yes I realized that, removed comment and added possible duplicate. – LU RD Apr 19 '13 at 14:12
  • @LURD: I don't think it is a perfect duplicate, because the best solution in this case isn't to actually trap the arrow keys, but to put the image in a separate control. – Andreas Rejbrand Apr 19 '13 at 14:14
  • @AndreasRejbrand, question is a bit unclear. Does the OP want to know why the arrow keys is moving the selection instead of the image, or a solution how to move the image with arrow keys. – LU RD Apr 19 '13 at 14:19

1 Answers1

6

The best solution is to put your control (the image) into a window (control) that handles the dialog keys, and then to make sure that this control receives keyboard focus at the appropriate times.

Well, honestly, you seem to draw/animate things by moving graphic controls. The very best way is to create a custom control (descending from TCustomControl) and draw things manually (or, possibly, to have graphic child controls). Then you can easily make this control respond to the arrow keys.

This control does it:

unit WindowContainer;

interface

uses
  SysUtils, Windows, Messages, Classes, Controls;

type
  TWindowContainer = class(TCustomControl)
  private
  protected
    procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property OnStartDrag;
    property OnStartDock;
    property OnUnDock;
    property OnClick;
    property OnCanResize;
    property OnAlignPosition;
    property OnAlignInsertBefore;
    property OnResize;
    property OnMouseWheel;
    property OnMouseWheelDown;
    property OnMouseWheelUp;
    property OnMouseUp;
    property OnMouseMove;
    property OnMouseLeave;
    property OnMouseEnter;
    property OnMouseDown;
    property OnMouseActivate;
    property OnKeyUp;
    property OnKeyPress;
    property OnKeyDown;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Rejbrand 2009', [TWindowContainer]);
end;

{ TWindowContainer }

constructor TWindowContainer.Create(AOwner: TComponent);
begin
  inherited;
  ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents,
    csSetCaption, csDoubleClicks, csReplicatable, csPannable,
    csFramed];
end;

procedure TWindowContainer.WMGetDlgCode(var Message: TWMGetDlgCode);
begin
  inherited;
  Message.Result := Message.Result or DLGC_WANTCHARS or DLGC_WANTARROWS
    or DLGC_WANTTAB or DLGC_WANTALLKEYS;
end;

end.

Screenshot

Sample demo EXE

To try this control, simply put the shape/image in it, and use the OnKeyDown event of this control. Also, make sure to set focus to this control, e.g. when the user clicks it:

procedure TForm1.WindowContainer1Click(Sender: TObject);
begin
  WindowContainer1.SetFocus;
end;

Now, doing animations by moving controls is bad. Instead, you should draw manually. Combine this answer with the code in this answer and you're done.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384