Consultor Eletrônico



Kbase P13173: How to define accelerator keys for SmartToolbar buttons?
Autor   Progress Software Corporation - Progress
Acesso   Público
Publicação   10/6/2008
Status: Verified

GOAL:

How to define accelerator keys for SmartToolbar buttons?

GOAL:

How to add shortcut keys to the ADM2 toolbar?

GOAL:

How to customize the SmartToolbar to respond to keyboard?

FACT(s) (Environment):

Progress 9.x
OpenEdge 10.x
Windows

FIX:

Follow the steps listed below to define accelerator keys for a toolbar object that does not use menus at all, just buttons:
This solution assumes there is only one smartToolbar instance on the window. If there are more then more work will have to be done to identify the context of where the event was applied.
1- Copy src/adm2/custom/actioncustom.i locally and uncomment the statement that starts the actioncustom.p program in the main-block section.
2- Make a local copy of the ADM2's actioncustom.p program and create an initAction procedure that looks like as follows:

PROCEDURE initAction :
/*------------------------------------------------------------------------------
Purpose: Defines all default actions for the adm when running without a
repository.
Parameters: <none>
Notes: The actions defined here are class actions and are available for all
objects (toolbars) that inherits from this class.
This procedure is called from initializeObject, but ONLY the first
time it's been called.
------------------------------------------------------------------------------*/
DEFINE VARIABLE cActionGroups AS CHARACTER NO-UNDO.
DEFINE VARIABLE cAction AS CHARACTER NO-UNDO.
DEFINE VARIABLE iCounter AS INTEGER NO-UNDO.
DEFINE VARIABLE iCounter2 AS INTEGER NO-UNDO.
DEFINE VARIABLE cOptionsList AS CHARACTER NO-UNDO.
DEFINE VARIABLE cOption AS CHARACTER NO-UNDO.

RUN SUPER.

{get ActionGroups cActionGroups}.
DO iCounter = 1 TO NUM-ENTRIES(cActionGroups):
ASSIGN cAction = ENTRY(iCounter,cActionGroups).
IF LOOKUP(cAction,'RULE,SKIP') > 0 THEN
NEXT.

ASSIGN cOptionsList = {fnarg actionChildren cAction}.
DO iCounter2 = 1 TO NUM-ENTRIES(cOptionsList):
ASSIGN cOption = ENTRY(iCounter2,cOptionsList).
DYNAMIC-FUNCTION('assignActionAccelerator':U IN TARGET-PROCEDURE,
INPUT cOption,
INPUT "ALT-":U +
(IF cOption = "Add":U THEN
"A":U
ELSE
IF cOption = "Update":U THEN
"U":U
. ELSE
IF cOption = "Copy":U THEN
"C":U
ELSE
IF cOption = "Delete":U THEN
"D":U
ELSE
IF cOption = "Save":U THEN
"S":U
ELSE
IF cOption = "Reset":U THEN
"R":U
ELSE
IF cOption = "Cancel":U THEN
"E":U
ELSE
IF cOption = "Undo":U THEN
"O":U
&nbs.p; ELSE
IF cOption = "Commit":U THEN
"T":U
ELSE
IF cOption = "First":U THEN
"F":U
ELSE
IF cOption = "Next":U THEN
"N":U
ELSE
IF cOption = "Prev":U THEN
"P":U
ELSE
IF cOption = "Last":U THEN
"L":U
ELSE
IF cOption = "Exit":U THEN
"X":U
&nbs.p; ELSE
"I":U)).
END.
END.
END PROCEDURE.

3- Copy src/adm2/custom/toolbarcustom.i locally and uncomment the statement that starts the toolbarcustom.p program in the main-block section.

4- In the local toolbarcustom.i's main-block section, define a trigger for all the desired accelerator keys. e.g.:

ON "ALT-A":U,"ALT-B":U,"ALT-C":U,"ALT-D":U,"ALT-E":U,"ALT-F":U,"ALT-G":U,"ALT-H":U,"ALT-I":U,"ALT-J":U,"ALT-K":U,"ALT-L":U,"ALT-M":U,"ALT-N":U,"ALT-O":U,"ALT-P":U,"ALT-Q":U,"ALT-R":U,"ALT-S":U,"ALT-T":U,"ALT-U":U,"ALT-W":U,"ALT-X":U,"ALT-Y":U,"ALT-Z":U,"RETURN":U OF CURRENT-WINDOW ANYWHERE
RUN applyButton IN TARGET-PROCEDURE (KEY-LABEL(LASTKEY)).

5- Make a local copy of the ADM2's toolbarcustom.p program and create a procedure in it named applyButton. The procedure should look like as follows:

PROCEDURE applyButton :
/*------------------------------------------------------------------------------
Purpose:
Parameters: <none>
Notes:
------------------------------------------------------------------------------*/
DEFINE INPUT PARAMETER pcAcelerator AS CHARACTER NO-UNDO.

DEFINE VARIABLE cActionGroups AS CHARACTER NO-UNDO.
DEFINE VARIABLE cAction AS CHARACTER NO-UNDO.
DEFINE VARIABLE iCounter AS INTEGER NO-UNDO.
DEFINE VARIABLE iCounter2 AS INTEGER NO-UNDO.
DEFINE VARIABLE cOptionsList AS CHARACTER NO-UNDO.
DEFINE VARIABLE cOption AS CHARACTER NO-UNDO.

{get ActionGroups cActionGroups}.
DO iCounter = 1 TO NUM-ENTRIES(cActionGroups):
ASSIGN cAction = ENTRY(iCounter,cActionGroups).
IF LOOKUP(cAction,'RULE,SKIP') > 0 THEN
NEXT.
ASSIGN cOptionsList = {fnarg actionChildren cAction}.
DO iCounter2 = 1 TO NUM-ENTRIES(cOptionsList):
ASSIGN cOption = ENTRY(iCounter2,cOptionsList).
IF { fnarg actionAccelerator cOption } = pcAcelerator AND
{ fnarg isActionAvailable cOption } THEN
RUN onChoose IN TARGET-PROCEDURE (INPUT cOption).
END.
END.
END PROCEDURE.

6- From the AppBuilder's File => New option, create a new method library file and save it locally as src/adm2/custom/toolpropcustom.i. In the definitions section, insert the following code:

&IF "{&ADMSuper}":U NE "toolbar.p":U &THEN
&SCOPED-DEFINE EXCLUDE-isActionAvailable YES
&ENDIF

7- Create the isActionAvailable function in the created toolpropcustom.i. It should look like as follows:

FUNCTION isActionAvailable RETURNS LOGICAL
( INPUT pcAction AS CHAR ) :
/*----------------------------------------------------
Purpose:
Notes:
-----------------------------------.-----------------*/
FIND tButton WHERE tButton.Name = pcAction AND
tButton.hTarget = TARGET-PROCEDURE NO-ERROR.
IF AVAILABLE tButton THEN
RETURN tButton.hdl:SENSITIVE.
ELSE
RETURN FALSE. /* Function return value. */
END FUNCTION.

8- Recompile the ADM2's toolbar.p and dyntoolbar.w programs so that their compiled code contain all the changes described above.

9- Create a Smart Objects Application that contains a SmartToolBar object defined with no menu. Run the created Application and test the accelerator keys on the toolbar buttons..