Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Action List (mis)behavior.

150 views
Skip to first unread message

Tom Alexander

unread,
Jun 9, 2000, 3:00:00 AM6/9/00
to
Does anyone understand when and how action lists fire?

An application I'm working on (developed by others, so my intimate knowledge
is limited) uses action lists as a methodology of invoking Fx key actions on
various frames. This app has only the main form descending from the Tform
class, everything else is something of the frame variety. Each module of
the app has it's own frame on which one or more other frames and panels
live. Each module (frame) has an action list, a pop-up menu list and/or a
number of toolbuttons.

The problem arises when I want to do something different for, say.. the 'F6'
key, in one module than in another. If I start in one of the inner modules
and press F6, the proper event fires most of the time. If I start in
another module and press F6, the proper thing for that frame happens again.
If I go back to the first module I tried and press F6 again, the action from
the other module fires. This behavior occurs usually, but not all the time.
Sometimes after a series of the above errors, the behavior starts acting as
I would expect. The pop-up menus, and toolbuttons (all attached to the same
action and referencing the same function key) almost always give the proper
behavior. Only the function key itself acts strangely.

I realize actions are something relatively new (4.0 I believe) for Delphi.
Is it possible that you really shouldn't reassign function keys from module
to module, or is there something glaring so brightly that I can't see the
necessary detail?

I hope this long winded question doesn't offend, I just wanted to provide as
much info as I could.

TIA!
Tom.

Peter Below (TeamB)

unread,
Jun 10, 2000, 3:00:00 AM6/10/00
to
In article <3941b308@dnews>, Tom Alexander wrote:
> Does anyone understand when and how action lists fire?
> An application I'm working on (developed by others, so my intimate knowledge
> is limited) uses action lists as a methodology of invoking Fx key actions on
> various frames. This app has only the main form descending from the Tform
> class, everything else is something of the frame variety. Each module of
> the app has it's own frame on which one or more other frames and panels
> live. Each module (frame) has an action list, a pop-up menu list and/or a
> number of toolbuttons.
> The problem arises when I want to do something different for, say.. the 'F6'
> key, in one module than in another. If I start in one of the inner modules
> and press F6, the proper event fires most of the time. If I start in
> another module and press F6, the proper thing for that frame happens again.
> If I go back to the first module I tried and press F6 again, the action from
> the other module fires. This behavior occurs usually, but not all the time.
> Sometimes after a series of the above errors, the behavior starts acting as
> I would expect.

Tom,

key handling in Delphi is fairly complex. The sequence of events as they
relate to your question are:

- user hits a key, a keydown message is placed into the message queue
- Application.ProcessMessage gets it from the queue, feeds it through a
number of Application methods, one of these is IsKeyMsg.
- IsKeyMsg sends the key down as a CN_KEYDOWN message to the control
with focus.
- TwinControl.CNKeyDown calls TwinControl.IsMenuKey
- after checking the popup menu of the control (if any) for the shortcut
without success IsMenuKey locates the controls parent form and calls its
IsShortcut method.
- Tcustomform.IsShortcut first checks the forms menu, if any. If not
finding a matching shortcut it then walks over the action lists registered
with the form and calls each lists IsShortcut method, which in turn walks
over the actions in the list looking for a shortcut.
- If nobody wanted the key as shortcut yet a CM_APPKEYDOWN message is send to
the Application window for the key, TApplication.WndProc handles this by
calling the main forms IsShortCut (if the window is enabled only, not when
a modal form is up). Note that this means that the main forms IsShortcut
will be called twice if the active control is on the main form and the
key is not a shortcut!

The critical part for you is the sequence in which TCustomform.IsShortcut
walks over the action lists. A TFrame will add its TActionlist to the parent
forms actionlists list when the parent is assigned to its Parent property (see
TCustomFrame.SetParent) and remove it when the Parent changes or the
actionlist is destroyed. As far as i see the sequence of the actionlists does
not change afterwards. So if you have several enabled frames on your form
their action lists will be queried in the sequence the frames were added to
the form, so the form containing the active control may not be the first to be
queried.

What this boils down to is this: if you have colliding shortcuts that may act
differently on different frames on your form then you need to override the
forms IsShortcut method and take steps there to make sure the frame the active
control is on gets first crack at the shortcut. Something like this:

Function TMyform.IsShortcut( var Message: TWMKey): Boolean; { override }
Var
ctrl: TWinControl;
comp: TComponent;
i: Integer;
Begin
ctrl := ActiveControl;
If ctrl <> Nil Then Begin
Repeat
ctrl := ctrl.Parent
Until (ctrl = nil) or (ctrl Is TCustomframe);
If ctrl <> nil Then Begin
For i:= 0 To ctrl.componentcount-1 Do Begin
comp:= ctrl.Components[i];
If comp Is TCustomActionList Then Begin
result := TCustomActionList(comp).IsShortcut( message );
If result Then
Exit;
End;
End;
End;
End;
inherited;
End;

Untested!

For performance reason you may want to make sure the actionlist on each frame
is the first item created (set it to first in the designers createorder menu)
and you may also want to assume only one action list will be on a frame and
Exit the for loop once you found it, regardless of Result.

Peter Below (TeamB) 10011...@compuserve.com)
No e-mail responses, please, unless explicitly requested!


Tom Alexander

unread,
Jun 12, 2000, 3:00:00 AM6/12/00
to
Peter,

Thanks! I tried this and it didn't work (well, did and didn't). I
discovered that our frames were showing before they fire this IsShortcut
event. The reason appeared to be that, even though they were displayed on
the screen, they didn't have an object the system recognized as having
focus. This was true even when the grid had a highlighted row showing.

I added a procedure to the FrameEnter event that set the focus to the
appropriate grid for each frame, and everything started working properly. I
then pulled out the code you provided and it still works correctly. Go
figure!

Thanks!
Tom.

"Peter Below (TeamB)" <10011...@compuXXserve.com> wrote in message
news:VA.0000535...@antispam.compuserve.com...

0 new messages