Reputation: 2068
Delphi 2010
I am using a OnFormKeyDown event on my main form, and I basically use the same event on a Dialog
//main form
procedure TfrmMain.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case Key of
VK_DOWN: btnLast.OnClick(Self);
VK_Up: btnFirst.OnClick(Self);
VK_Left: btnPrev.OnClick(Self);
VK_Right: btnNext.OnClick(Self);
end;
end;
procedure TfrmMain.mniShowOwnedClick(Sender: TObject);
var
I: Integer;
begin
frmMain.KeyPreview:= False;
frmOwned.KeyPreview:= True;
frmOwned.Owned2.Clear;
for I := 0 to Tags.Count - 1 do
if Owned.IndexOf(Tags.Names[I]) <> -1 then
frmOwned.Owned2.Add(Tags[I]);
if frmOwned.ShowModal = mrOK then
begin
frmMain.KeyPreview:= True;
frmOwned.KeyPreview:= False;
end;
end;
//Dialog
procedure TfrmOwned.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case Key of
VK_DOWN: btnLast.OnClick(Self);
VK_Up: btnFirst.OnClick(Self);
VK_Left: btnPrev.OnClick(Self);
VK_Right: btnNext.OnClick(Self);
end;
end;
The Form's OnKeyDown works fine, but I can't seem to get the dialogs to work
Upvotes: 2
Views: 2015
Reputation: 612854
The problem is that these keys are used as dialog navigation keys. And as such, they never make their way to the OnKeyDown
event.
To be honest I had a hard time understanding why they are firing for your main form's OnKeyDown
event. I could not make that happen in my test environment. That's because I had added a button to the form. That's enough to mean that the arrow keys are treated as navigation keys. Try creating a an app with a single form and adding a few buttons. Then run the app and use the arrow keys to move the focus between the buttons. That's what I mean when I say that the arrow keys are treated as navigation keys.
I expect that the difference between your two forms is that the main form has nothing that can be navigated around by arrow keys, but the modal form does.
Now, you could stop the arrow keys being treated as navigation keys. Like this:
type
TMyForm = class(TForm)
....
protected
procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY;
....
end;
....
procedure TMyForm.CMDialogKey(var Message: TCMDialogKey);
begin
case Message.CharCode of
VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN:
Message.Result := 0;
else
inherited;
end;
end;
However, a better solution, in my view, is to stop trying to implement shortcuts using OnKeyDown
events. That seems like the wrong solution. The right solution is to use actions. Create an action list. Add actions for first, last, previous and next actions. Give them the appropriate ShortCut
properties. Assign those actions to your buttons. And the job is done.
One of the benefits of this is that you can stop trying to fake button click events. For what it is worth, calling OnClick
is the wrong way to do that. Call the button's Click
method if ever your really need to do that. However, use an action and it's all taken care of.
Another benefit is that you'll no longer need to pfaff around with KeyPreview
. Simply put, if you want to implement short cuts, use TAction.ShortCut
.
Upvotes: 7