FMX: How to create a menu item shortcut for a single key? - firemonkey

I need this to create a shortcut for a single key in a TMainMenu and TMenuBar, like 'I' for example. Options for single keys are not selectable in the property editor for the shortcut property of a TMenuItem. I have also tried setting the shortcut for the menu item at run time using either of the methods below.
MenuItem.ShortCut := vkI;
MenuItem.ShortCut := TextToShortcut('I');
The shortcut character 'I' does show up in the menu, however, it doesn't work. I press the 'I' key and nothing happens. However, if I set the shortcut using the following then it does work correctly, so I assume the issue is just that it doesn't allow single key shortcuts.
MenuItem.ShortCut := TextToShortcut('Ctrl+I');
I have also tried linking the menu item to an action in a TActionList and setting the shortcut of the action in the same way, but the result is the same.
The solution I've found is to handle the key press in the FormKeyDown event to trigger the action, but this seems unnecessary. Why doesn't it work as expected?
I'm using Delphi 10.4 and building for Windows 32-bit.

Because your shortcut didn't contain a dialog key.
procedure TCommonCustomForm.IsDialogKey(const Key: Word; const KeyChar: WideChar; const Shift: TShiftState;
var IsDialog: boolean);
begin
IsDialog := (KeyChar < ' ') or ((Shift * [ssAlt, ssCtrl, ssCommand]) <> []);
end;
In TCommonCustomForm.KeyDown, the code start to check if your shortcut contain a dialog key, if yes it will check your menu and execute the action :
// 3. perform key in other Menus
for I := ChildrenCount - 1 downto 0 do
if Children[i] <> FocusPopup then
begin
if Children[I] is TMainMenu then
TMainMenu(Children[I]).DialogKey(Key, Shift)
else if Children[I] is TPopupMenu then
TPopupMenu(Children[I]).DialogKey(Key, Shift);
if Key = 0 then
Exit;
end;
You can override this method and return true for each key you press

Related

Apex Link builder value - item not displayed on the target page

I LOAD P70_NODE_ID from Javascript.
APEX 20.2
then run the following:
apex_util.set_session_state('P70_NODE_ID_OUT', :P70_NODE_ID);
When I show the session I see P70_NODE_ID_OUT and P70_NODE_ID. They both have the correct values
link to another page using the link builder
under item and value:
item P80_STEP_ID value :P70_NODE_ID_OUT
display p80_STEP_ID
I never see a value.
NOTE: The target page is a modal dialog built with the form wizard.
I have tried using a where statement P80_STEP_ID = :P70_NODE_ID_OUT
Still I don't see a value.
Is the problem related to inserting a value from Javascript?
How do I work around this?
Thanks
It turns out that when using redirect to another page in the same application, it uses the values that exist when the page is built and never looks at the values again. As a result, when values change after a page is loaded, the new values aren't used. The following allows you to use changed values when redirecting.
Used advice from the Apex community. This is what worked for me.
This uses apex_page.get_url and the technique you suggested. Tested good.
Javascript that runs when a node is selected in a flowchart:
$s('P72_NODE_ID', tagNum);
$s('P72_NODE_TYPE', selNode.getShape().getId());
$.event.trigger('submitNodeSel');
DynamicEvent
WHEN
event: custom
custom event: submitNodeSel
selectionType: javascriptexpression
javascript expression: document
True Action
Action: set value
set type: PL/SQL Function Body
DECLARE
STEP_DETAIL_URL varchar2(2000);
l_app number := v('APP_ID');
l_session number := v('APP_SESSION');
BEGIN
STEP_DETAIL_URL := apex_page.get_url(
p_page => '80'
, p_items => 'p80_step_id,p80_node_type'
, p_values => :p72_node_id || ',' || :p72_node_type
, p_plain_url => true);
RETURN STEP_DETAIL_URL;
END;
input: p72_node_id,p72_node_type
affected Elements
selection type: item(s)
item(s): P72_STEP_DETAIL_URL
BUTTON
Dynamic Action
execute javascript code
True Action
Javascript
makeDialogUrl( $v("P72_STEP_DETAIL_URL"));
Javascript Code
function makeDialogUrl (url) {
var i;
// replace unicode escapes
url = url.replace(/\\u(\d\d\d\d)/g, function(m,d) {
return String.fromCharCode(parseInt(d, 16));
});
apex.navigation.dialog(url,
{title:'Dialog In
Out',height:'auto',width:'720',maxWidth:'960',modal:true,dialog:null},
"t-Dialog-page--standard", "#STEP_DETAILS");
}
2 should be
under item and value: item P80_STEP_ID value &P70_NODE_ID_OUT.
Note leading ampersand & and trailing dot .
BTW, Apex would have done it for you if you picked columns from the LoV.

TShellListView Lazarus

Is it possible to set a item in a ShellListView to visible=false? I thought About something like ShelLlistView.Items.visible(false) but that does not exist and I have no idea for another solution so I hope someone can help me with this.
I can't post any Code for you yet because I don't have any ShellListView yet but I hope you can give me some advice how it could work.
Afaik, this is not possible because the ListItems shown in the TShellListView have no Visible property. However, according to Peter Below (TeamB), you can effectively "hide" an item by destroying it. See http://www.delphigroups.info/2/67/290279.html
Of course, if you wish to "unhide" an item hidden in this way, you would need to create & add a new node with the same Caption, etc.
This code works fine for me using the standard Lazarus TShellListView:
procedure TForm1.Button1Click(Sender: TObject);
var
Item : TListItem;
begin
Item := ShellListView1.Items[0];
Caption := Item.Caption;
Item.Free;
end;
and removes the first item in the list.
The following removes all the items in the ShellListView. THe downto is to account for the fact that the Count value decreases on each iteration of the loop.
procedure TForm1.Button1Click(Sender: TObject);
var
i : Integer;
begin
for i := ShellListView1.Items.Count - 1 downto 0 do
ShellListView1.Items[i].Free;
end;

How to change List Item value on WHEN_VALIDATE_ITEM

I am working on Forms 6i on a very old software.
There is a requirement to add 3 List Item (Combo Box) to the form.
If the value in List Item X is changed, then upon WHEN_VALIDATE_ITEM, I need to change the value on List Item Y.
Here is the code but it's not working.
BEGIN
IF :PIH.TEXT_ITEM1544='Book' THEN
Copy('Own Use',Name_In('PIH.TEXT_ITEM1546'));
END IF;
END;
There are no errors in compilation, but I believe that when I select the value Book and press enter or tab and go to another field, nothing is triggered.
Any help would be really appreciable.
What do you want to do exactly? If you want to assign the value 'Own Use' to the item PIH.TEXT_ITEM1546 you can do it with:
:PIH.TEXT_ITEM1546 := 'Own Use';
Or with:
Copy('Own Use','PIH.TEXT_ITEM1546')
The statement you're using:
Copy('Own Use',Name_In('PIH.TEXT_ITEM1546'));
is trying to copy the value 'Own Use' to the item referenced by PIH.TEXT_ITEM1546, i.e., it's trying to copy the value to an item named as the value stored in the item PIH.TEXT_ITEM1546.
The Name_In function gets the value of the specified item.

Enable/Disable Item based on the value of the List Item

I am trying to code a listItem which will have 2 values "New" and "Edit". I also have a search (Push Button) in the same canvas. I want to disable the Search button when I have selected "new" in the list item and enable it when "Edit" is selected in the list item.
Here is my code : I am using Oracle Forms 6i , WHEN_LIST_CHANGED Trigger ..
begin
if :CONTROL.LI_DO='New' then
go_item('PB_SEARCH');
SET_ITEM_PROPERTY('PB_SEARCH',enabled,property_false);
else if :CONTROL.LI_DO='Edit' then
go_item('PB_SEARCH');
SET_ITEM_PROPERTY('PB_SEARCH',enabled,property_true);
end if;
end if;
end;
Any help is appreciated .
Been a while since I did forms, but can you disable an item that has current focus?
I.e. navigate (GO_ITEM) to another item then try to disable PB_SEARCH.
LI_DO.Functional."Elements in List" : New (value 0), Edit (value 1);
LI_DO.Data."Data Type" : Number;
LI_DO."Initial Value" : 1;
LI_DO.Required : "Yes";
After those regulations, you may use the code below for "WHEN-LIST-CHANGED";
begin
if :CONTROL.LI_DO = 0 then
--go_item('PB_SEARCH');
SET_ITEM_PROPERTY('PB_SEARCH',enabled,property_false);
--else if :CONTROL.LI_DO = 1 then
elsif :CONTROL.LI_DO = 1 then
--go_item('PB_SEARCH');
SET_ITEM_PROPERTY('PB_SEARCH',enabled,property_true);
end if;
--end if;
end;
You have to know the concept of using enabled property.
The following blog illustrate this with an example clears the point of misunderstanding of using 'enabled'property alone.
Pls. follow the solution steps you should be familiar with the four required properties in co-ordinate with each together to enable and disable an item

VB6 how to get the selected/checked control in a control array

I have to modify a VB6 app and am repeatedly beating my head against a wall over control arrays.
I know that the event handler for the array includes its index value and I can set some variable there, but i should be able to directly access the selected radio button in an array of OptionButton. Currently I'm doing this
For i = 0 To optView.Count - 1
If optView.Item(i).value = True Then
currIndex = i
Exit For
End If
Next
Is this really my only option?
Yes, this is our only option. The control array object does not contain any selecting logic (which makes sense, as "selected" might mean different things for different controls). The only change I'd make is replacing the For with For Each.
Another way to do this that I have used. Write a function, and then call the function, passing in the control name, to return the index number. Then you can reuse this in the future especially, if you add it to a module (.bas).
Function f_GetOptionFromControlArray(opts As Object) As Integer
' From http://support.microsoft.com/KB/147673
' This function can be called like this:
' myVariable = f_GetOptionFromControlArray(optMyButtons) 'Control syntax OK
' myVariable = f_GetOptionFromControlArray(optMyButtons()) 'Array syntax OK
On Error GoTo GetOptionFail
Dim opt As OptionButton
For Each opt In opts
If opt.Value Then
f_GetOptionFromControlArray = opt.Index
Exit Function
End If
Next
GetOptionFail:
f_GetOptionFromControlArray = -1
End Function

Resources