Mega Search
23.2 Million


Sign Up

Make a donation  
DXE2: ShortCuts, ActionList and Multiple Page Instances  
News Group: embarcadero.public.delphi.vcl.components.using

Hi,

My basic problem is that when a shortcut key, that is defined in an
actionlist, is pressed the action Execute method always invokes the
action on the first instance of the page(form) rather than the
page(form) that has the focus.

DETAILS:

0. Running DXE2, with all updates and patches, to create a 32-bit app
on Windows 8.1/64.

1. A form(page), named PgRefTbl, of type TPgRef is defined and contains:

(a) An actionlist with an action named actDelete. The actDeleteExecute
method toggles a flag on the form between true and false.

(b) A FlowPanel with several TButtons on it. One button, the delete
button, has its action set to the delete action that is defined in the
actionlist.

(c) The form(page) is defined in such a way that it can be
programmatically  created and placed on a tabsheet of a pagecontrol.

(d) When the form(page) is created appropriate data is passed to its
create method so the the tabsheet's caption will be unique and the data
displayed on the form is appropriate. For example, some of the captions
are "Categories", "Locations" and "Owners".

2. A dialog box that contains a pagecontrol is used to host and display
multiple instances of the PgRefTbl page.

3. When the dialog is run, multiple instances of PgRefTbl are created
and displayed on separate tabs. For example on the "Categories",
'Locations" and "Owners" tabs.

4. When switching from tab to tab and clicking the Delete Button, the
*flag on the appropriate page* is toggled. BUT

5. When switching from tab to tab and pressing the Shortcut key, Del,
the *flag on the first instance of TPgRef* is always toggled!
THIS IS THE PROBLEM!

6. When debugging and setting a break point at the beginning of the
actDeleteExecute method the address of the self identifier and its name
is always the same when the shortcut key is pressed no matter which tab
is active, BUT the address and name of the self identifier differ when
the Delete Button is clicked.

6(b) When the first tab is active the address and name of the self
identifier are the same when either the shortcut key is pressed or the
Delete Button is clicked.

MY QUESTIONS:

1. Am I missing something obvious?

2. Is the above behaviour a bug?

3. Is there a work-around or patch available?

TIA

Regards,
John

Vote for best question.
Score: 0  # Vote:  0
Date Posted: 5-Jan-2015, at 11:06 PM EST
From: John Raycheba
 
Re: DXE2: ShortCuts, ActionList and Multiple Page Instances  
News Group: embarcadero.public.delphi.vcl.components.using
Peter Below wrote:

> John Raycheba wrote:
> 
> > Peter, Thanks, but....
> > 
> 
> As far as I can make out you are assuming that the form's
> Activecontrol will be a control on the active tabsheet of the
> pagecontrol. If you click on the tabs to switch pages that will not
> be the case, the pagecontrol itself has the focus and is the active
> control in this scenario.
> 
> I would just get the pagecontrol.ActivePage as a starting point and
> look for an actionlist in its Components array. If you find one, pass
> the shortcut to it first, and if it is not processed fall back to the
> inherited IsShortcut method.

THANKS AGAIN Peter,

I've made a more thorough investigation (tracing) of what the code does
and as a result have decided to take a different approach.

Just so you and others know what I found here's a brief summary:

1. With a main form (or dialog) that has an actionlist, a pagecontrol
on it AND the IsShortCut method override on it (and each of the
tabsheets on the pagecontrol may or may not have an actionlist on it),
the following appears to happen when a shortcut key is pressed:

(a) The shortcut is activated with the focused control on the active
tabsheet.

(b) The IsShortCut method traces back to the tabsheet or TForm that is
on the tabsheet that contains the focused control.

(c) The IsShortCut method searches of an actionlist.

(d) If an actionlist is found it is tested to see if it contains the
shortcut key.

(e) If the shortcut key is found its execute method is run and a value
of True is returned, otherwise False is returned.

(f) At this point, depending on how the IsShortCut method's code is
written (or modified) there are two possible actions:

(fi) Further processing of the shortcut can be terminated by exiting
the procedure.

(fii) The inherited (standard) shortcut processing can continue. --
This may or may not be desirable depending, for example, if the main
form's (diaog's) actionlist is expected to respond to the particular
shortcut key, if it has not been processed by the active tabsheet's
actionlist.

(g) If shortcut processing is terminated by exiting the IsShortCut
procedure we're done. NOTE: If the focused tabsheet does not have an
actionlist on it this will never happen and the standard (inherited)
processing will continue. -- This may be problematic, if, for example,
one wants the shortcut key processed by the actionlist that is on the
main form (dialog).

(h) If shortcut key processing is allowed to continue not only will all
of the controls owned by the main form (dialog) be searched for the
presence of an actionlist, BUT ALSO all of the tabsheets that are on
the pagecontrol. -- This was a surprise to me. -- Creates all kinds of
problems; for example, trying to execute the shortcut key's execute
method on a tabsheet that is disabled or invisible!

2. My alternate approach is to:
(a) Not have any actionlists or shortcutkeys defined on the tabsheets.
(b) SEND or POST and appropriate user defined message from the main
form's (dialog's) actionlist to the pagecontrol's active page/tabsheet.
(c) If SEND message is used it will be possible to determine whether
the message was processed by the active tabsheet and whether or not the
shortcut should also be processed by the main form (dialog) in some
other way.

I hope the above is reasonably clear and of at least mild interest to
you and others.

Peter, thanks again for your help. It is much appreciated.

Regards,

John

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 9-Jan-2015, at 12:59 PM EST
From: John Raycheba
 
Re: DXE2: ShortCuts, ActionList and Multiple Page Instances  
News Group: embarcadero.public.delphi.vcl.components.using
John Raycheba wrote:

> Peter, Thanks, but....
> 
> I have, in fact, been using your code to intercept the IsShortCut
> function.
> 
> Also, although the app's main form contains an actionlist, the dialog
> contains only one action list.
> 
> Finally, I get the same results whether the IsShortCut is or is not
> intercepted.
> 
> My version of your code is included in the ancestor of the form that
> is placed on the pagecontrol. You can see from the commented out lines
> that I've tried several variation.

As far as I can make out you are assuming that the form's Activecontrol
will be a control on the active tabsheet of the pagecontrol. If you
click on the tabs to switch pages that will not be the case, the
pagecontrol itself has the focus and is the active control in this
scenario.

I would just get the pagecontrol.ActivePage as a starting point and
look for an actionlist in its Components array. If you find one, pass
the shortcut to it first, and if it is not processed fall back to the
inherited IsShortcut method.



-- 
Peter Below (TeamB)

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 7-Jan-2015, at 10:16 AM EST
From: Peter Below
 
Re: DXE2: ShortCuts, ActionList and Multiple Page Instances  
News Group: embarcadero.public.delphi.vcl.components.using
Peter Below wrote:

> John Raycheba wrote:
> 
> > Hi,
> > 
> > My basic problem is that when a shortcut key, that is defined in an
> > actionlist, is pressed the action Execute method always invokes the
> > action on the first instance of the page(form) rather than the
> > page(form) that has the focus.
> > 
> > DETAILS:
> > 
> > 0. Running DXE2, with all updates and patches, to create a 32-bit
> > app on Windows 8.1/64.
> > 
> > 1. A form(page), named PgRefTbl, of type TPgRef is defined and
> > contains:
> > 
> > (a) An actionlist with an action named actDelete. The
> > actDeleteExecute method toggles a flag on the form between true and
> > false.
> > 
> > (b) A FlowPanel with several TButtons on it. One button, the delete
> > button, has its action set to the delete action that is defined in
> > the actionlist.
> > 
> > (c) The form(page) is defined in such a way that it can be
> > programmatically  created and placed on a tabsheet of a pagecontrol.
> > 
> > (d) When the form(page) is created appropriate data is passed to its
> > create method so the the tabsheet's caption will be unique and the
> > data displayed on the form is appropriate. For example, some of the
> > captions are "Categories", "Locations" and "Owners".
> > 
> > 2. A dialog box that contains a pagecontrol is used to host and
> > display multiple instances of the PgRefTbl page.
> > 
> > 3. When the dialog is run, multiple instances of PgRefTbl are
> > created and displayed on separate tabs. For example on the
> > "Categories", 'Locations" and "Owners" tabs.
> > 
> > 4. When switching from tab to tab and clicking the Delete Button,
> > the *flag on the appropriate page* is toggled. BUT
> > 
> > 5. When switching from tab to tab and pressing the Shortcut key,
> > Del, the *flag on the first instance of TPgRef* is always toggled!
> > THIS IS THE PROBLEM!
> > 
> > MY QUESTIONS:
> > 
> > 1. Am I missing something obvious?
> 
> No, what you are seeing is due to the way the VCL handles shortcuts.
> See http://edn.embarcadero.com/article/38447 especially chapter 5.2.2.
> 
> > 2. Is the above behaviour a bug?
> 
> No, it is working as designed. You are not supposed to have multiple
> actions/controls using the same shortcut on a form, but it cannot be
> avoided in a scenario like yours.
> > 
> > 3. Is there a work-around or patch available?
> 
> Yes. See http://tinyurl.com/62l8rq. Basically you have to intercept
> the shortcut on the form level and hand it to the active page for
> processing first, before letting the default processing get it. That
> is fairly easy to do, fortunately.


Peter, Thanks, but....

I have, in fact, been using your code to intercept the IsShortCut
function.

Also, although the app's main form contains an actionlist, the dialog
contains only one action list.

Finally, I get the same results whether the IsShortCut is or is not
intercepted.

My version of your code is included in the ancestor of the form that is
placed on the pagecontrol. You can see from the commented out lines
that I've tried several variation.

{code}
Function {$IFDEF FPC}
          TPgCtrlBaseChildFrm
          {$ELSE}
          TPgCtrlBaseChildForm
          {$ENDIF}
          .IsShortcut( var Message: TWMKey): Boolean; { override }
Var
 ctrl :TWinControl;
 comp :TComponent;
 i    :Integer;
Begin
ctrl := ActiveControl;
If ctrl <> Nil Then
  Begin
  Repeat
//    if ctrl is TCustomVirtualDrawTree then
//      begin
//      if TCustomVirtualDrawTree(ctrl).IsEditing then
//        begin
//        inherited;
//        Exit;
//        end;
//      end;
    ctrl := ctrl.Parent;
    Until (ctrl = nil) or (ctrl Is TForm);
//    Until (ctrl = nil) or (ctrl Is TPgCtrlBaseChildForm);
  // Note: replace TCustomFrame with TForm, check if the found form is
  // self, if not, execute the following block of code.
  If (ctrl <> nil) and (ctrl <> Self) then
    Begin
    For i:= 0 To ctrl.componentcount-1 Do
      Begin
      comp:= ctrl.Components[i];
      If comp Is TCustomActionList Then
        Begin
        {Assume only one ActionList on a form.}
        {If shortcut found then exit else break out of loop and do
inherited}
        result := TCustomActionList(comp).IsShortcut( message );
        If result
          then Exit
          else Break;
        End;
      End;
    End;
  End;
inherited;
End;
{code}

Any additional observations or comments?

TIA

Regards,
John

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 6-Jan-2015, at 12:23 PM EST
From: John Raycheba
 
Re: DXE2: ShortCuts, ActionList and Multiple Page Instances  
News Group: embarcadero.public.delphi.vcl.components.using
John Raycheba wrote:

> Hi,
> 
> My basic problem is that when a shortcut key, that is defined in an
> actionlist, is pressed the action Execute method always invokes the
> action on the first instance of the page(form) rather than the
> page(form) that has the focus.
> 
> DETAILS:
> 
> 0. Running DXE2, with all updates and patches, to create a 32-bit app
> on Windows 8.1/64.
> 
> 1. A form(page), named PgRefTbl, of type TPgRef is defined and
> contains:
> 
> (a) An actionlist with an action named actDelete. The actDeleteExecute
> method toggles a flag on the form between true and false.
> 
> (b) A FlowPanel with several TButtons on it. One button, the delete
> button, has its action set to the delete action that is defined in the
> actionlist.
> 
> (c) The form(page) is defined in such a way that it can be
> programmatically  created and placed on a tabsheet of a pagecontrol.
> 
> (d) When the form(page) is created appropriate data is passed to its
> create method so the the tabsheet's caption will be unique and the
> data displayed on the form is appropriate. For example, some of the
> captions are "Categories", "Locations" and "Owners".
> 
> 2. A dialog box that contains a pagecontrol is used to host and
> display multiple instances of the PgRefTbl page.
> 
> 3. When the dialog is run, multiple instances of PgRefTbl are created
> and displayed on separate tabs. For example on the "Categories",
> 'Locations" and "Owners" tabs.
> 
> 4. When switching from tab to tab and clicking the Delete Button, the
> *flag on the appropriate page* is toggled. BUT
> 
> 5. When switching from tab to tab and pressing the Shortcut key, Del,
> the *flag on the first instance of TPgRef* is always toggled!
> THIS IS THE PROBLEM!
> 
> MY QUESTIONS:
> 
> 1. Am I missing something obvious?

No, what you are seeing is due to the way the VCL handles shortcuts.
See http://edn.embarcadero.com/article/38447 especially chapter 5.2.2.

> 2. Is the above behaviour a bug?

No, it is working as designed. You are not supposed to have multiple
actions/controls using the same shortcut on a form, but it cannot be
avoided in a scenario like yours.
> 
> 3. Is there a work-around or patch available?

Yes. See http://tinyurl.com/62l8rq. Basically you have to intercept the
shortcut on the form level and hand it to the active page for
processing first, before letting the default processing get it. That is
fairly easy to do, fortunately.



-- 
Peter Below (TeamB)

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 6-Jan-2015, at 10:36 AM EST
From: Peter Below