I have a VCL form with many tframes
(referred to as tcellFrame) containing components arranged in a grid. I am using mouse clicks and arrow keys for the user to navigate between them. The mouse clicks work fine, but I had trouble with the arrow keys until I discovered this question thread: Delphi XE and Trapping Arrow Key with OnKeyDown
. The solution in Sertac Akyuz's answer does handle getting the arrow key messages to the form using
procedure TForm1.DialogKey(var Msg: TWMKey);
begin
case Msg.CharCode of
VK_DOWN, VK_UP, VK_RIGHT, VK_LEFT:
if Assigned(onKeyDown) then
onKeyDown(Self, Msg.CharCode, KeyDataToShiftState(Msg.KeyData));
else
inherited
end;
end;
but acts upon the form twice for each key stroke. Instead of moving to the left one cellframe, it moves two. Tracing the thread using the debugger demonstrates that the onkeydown event is called twice.
My onKeyDown
event is structured as follows:
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
i : integer;
g, r, c, str : string;
tmpFrame : tcellFrame; //frame component containing tlabels
begin
...
case key of
VK_UP:
begin
//calc new cell location values for g,r,c
str := ('Cell'+g+r+c);
picklist.Clear; // picklist is a form-wide tstringlist variable containing currently selected cellframes.
picklist.add (str);
TmpFrame := FindComponent(picklist [0]) as TCellFrame;
tmpframe.Color := pickClr;
end;
//VK_DOWN, VK_LEFT, VK_RIGHT: defined similarly to VK_UP
end;
end;
There is more code in Formkeydown
, but it is all internal calculations to determine the proper tcellframe name to place in the picklist.
My questions are:
- What is causing this repeat to occur?
- How do I terminate the message implementation after its first instance?
KeyDown
: Either KeyDown or the OnKeyDown event handler it calls can suppress further processing of a key by setting the Key parameter to zero. – Tom Brunberg