steelha 0 Posted May 12 Hello, I'm having trouble creating a dynamic menu from a table using the Ribbon component in Delphi 12. I've created the tabs as the main menu options and the groups as submenus, but when I try to create the items for each group, I only get one. Here's the image and code. If anyone knows how to solve the problem I would be very grateful. CODE: procedure TfrmPrincipal.Cargar_Menu; var TabItem : TRibbonTabItem; Group : TRibbonGroup; BarAction : TActionClientItem; PadreIDTab : Integer; PadreIDGrupo : Integer; BarItem : TActionBarItem; Bg : TRibbonLargeButtonControl; Bs : TRibbonSmallButtonControl; begin ribMenu.Tabs.Clear; QryMenu.Close; QryMenu.SQL.Clear; QryMenu.SQL.Add('SELECT * '); QryMenu.SQL.Add('FROM Menu '); QryMenu.SQL.Add('WHERE (padre_id IS NULL OR padre_id = 0) AND activo = 1 '); QryMenu.SQL.Add('ORDER BY orden'); QryMenu.Open; QryMenu.First; while not QryMenu.Eof do // Crear las pestañas principales begin TabItem := ribMenu.Tabs.Add; TabItem.Caption := Trim(QryMenu.FieldByName('titulo').Value); PadreIDTab := QryMenu.FieldByName('menu_item_id').Value; QrySubMenu.Close; QrySubMenu.SQL.Clear; QrySubMenu.SQL.Add('SELECT * '); QrySubMenu.SQL.Add('FROM Menu '); QrySubMenu.SQL.Add('WHERE padre_id = :PadreIDTab AND activo = 1 '); // Obtener los grupos de la pestaña QrySubMenu.SQL.Add('ORDER BY orden'); QrySubMenu.Parameters.ParamByName('PadreIDTab').Value := PadreIDTab; QrySubMenu.Open; QrySubMenu.First; while not QrySubMenu.Eof do // Crear los grupos dentro de la pestaña begin if UpperCase(QrySubMenu.FieldByName('tipo').Value) = 'GRUPO' then begin Group := TRibbonGroup.Create(ribMenu); Group.Parent := TabItem.Page; Group.Caption := Trim(QrySubMenu.FieldByName('titulo').AsString); PadreIDGrupo := QrySubMenu.FieldByName('menu_item_id').Value; // Capturar el ID del grupo QryItems.Close; QryItems.SQL.Clear; QryItems.SQL.Add('SELECT * '); QryItems.SQL.Add('FROM Menu '); QryItems.SQL.Add('WHERE padre_id = :PadreIDGrupo AND activo = 1 '); // Obtener los ítems del grupo QryItems.SQL.Add('ORDER BY orden'); QryItems.Parameters.ParamByName('PadreIDGrupo').Value := PadreIDGrupo; QryItems.Open; QryItems.First; while not QryItems.Eof do // Crear los ítems dentro del grupo begin if UpperCase(QryItems.FieldByName('tipo').Value) = 'ITEM' then begin BarItem := amMenu.ActionBars.Add; BarAction := BarItem.Items.Add; BarAction.Caption := Trim(QryItems.FieldByName('titulo').Value); BarItem.ActionBar := Group; end; QryItems.Next; end; QryItems.Close; // Cerrar la consulta de ítems end; QrySubMenu.Next; end; QrySubMenu.Close; // Cerrar la consulta de grupos QryMenu.Next; end; QryMenu.Close; // Cerrar la consulta de pestañas end; Share this post Link to post
Die Holländer 84 Posted Tuesday at 12:28 PM When creating a GUI for applications with database and business logic, using tab menus, like Ribbon component, with many buttons can lead to a lot of code in your form. Create at least objects with you database logic.. Share this post Link to post
steelha 0 Posted Tuesday at 12:38 PM ok, thanks sorry for no Thanks for the comment, I forgot to post the solution in case anyone decides to use it. I'm still working on improving the implementation of the buttons, icons, and actions. Here's the code of dynamic menu from DB: procedure TfrmPrincipal.Button2Click(Sender: TObject); var TabItem: TRibbonTabItem; Group: TRibbonGroup; // This will act as our TCustomActionBar BarAction: TActionClientItem; PadreIDTab: Integer; PadreIDGrupo: Integer; Action: TAction; i: Integer; GroupCaption: string; CurrentActionBarItem: TActionBarItem; Bg: TRibbonLargeButtonControl; Bs: TRibbonSmallButtonControl; begin ribMenu.Tabs.Clear; QryMenu.Close; QryMenu.SQL.Clear; QryMenu.SQL.Add('SELECT * '); QryMenu.SQL.Add('FROM Menu '); QryMenu.SQL.Add('WHERE (padre_id IS NULL OR padre_id = 0) AND activo = 1 '); QryMenu.SQL.Add('ORDER BY orden ASC'); QryMenu.Open; QryMenu.First; // Limpiar las actionbars antes de empezar el proceso amMenu.ActionBars.Clear; // Importante: limpiar las action bars existentes while not QryMenu.Eof do // Crear las pestañas principales begin TabItem := ribMenu.Tabs.Add; TabItem.Caption := Trim(QryMenu.FieldByName('titulo').Value); PadreIDTab := QryMenu.FieldByName('menu_item_id').Value; QrySubMenu.Close; QrySubMenu.SQL.Clear; QrySubMenu.SQL.Add('SELECT * '); QrySubMenu.SQL.Add('FROM Menu '); QrySubMenu.SQL.Add('WHERE padre_id = :PadreIDTab AND activo = 1 '); // Obtener los grupos de la pestaña QrySubMenu.SQL.Add('ORDER BY orden ASC'); QrySubMenu.Parameters.ParamByName('PadreIDTab').Value := PadreIDTab; QrySubMenu.Open; QrySubMenu.First; while not QrySubMenu.Eof do // Crear los grupos dentro de la pestaña begin if UpperCase(QrySubMenu.FieldByName('tipo').Value) = 'GRUPO' then begin GroupCaption := Trim(QrySubMenu.FieldByName('titulo').AsString); Group := nil; // Inicializamos Group a nil // Buscar si ya existe un grupo con este Caption en la pestaña actual for i := 0 to TabItem.Page.ControlCount - 1 do begin if (TabItem.Page.Controls[i] is TRibbonGroup) and (TRibbonGroup(TabItem.Page.Controls[i]).Caption = GroupCaption) then begin Group := TRibbonGroup(TabItem.Page.Controls[i]); Break; // Se encontró el grupo existente, salir del bucle end; end; // Si no se encontró el grupo, crear uno nuevo if not Assigned(Group) then begin Group := TRibbonGroup.Create(ribMenu); Group.Parent := TabItem.Page; Group.Caption := GroupCaption; end; PadreIDGrupo := QrySubMenu.FieldByName('menu_item_id').Value; // Capturar el ID del grupo // Find or create the TActionBarItem associated with this TRibbonGroup CurrentActionBarItem := nil; for i := 0 to amMenu.ActionBars.Count - 1 do begin // A TRibbonGroup can be assigned to an ActionManager through an ActionBarItem // We can use the Group itself as the identifier, or set the ActionBarItem.Tag if amMenu.ActionBars[i].ActionBar = Group then begin CurrentActionBarItem := amMenu.ActionBars[i]; Break; end; // Alternatively, if you prefer to use Tag (and ensure Tag is set for the ActionBarItem) // if (amMenu.ActionBars[i].Tag = PadreIDGrupo) then // begin // CurrentActionBarItem := amMenu.ActionBars[i]; // Break; // end; end; if not Assigned(CurrentActionBarItem) then // If ActionBarItem for this group doesn't exist, create it begin CurrentActionBarItem := amMenu.ActionBars.Add; // Add creates a new TActionBarItem CurrentActionBarItem.ActionBar := Group; // Assign the TRibbonGroup to the ActionBarItem CurrentActionBarItem.Tag := PadreIDGrupo; // Store the group's ID in the ActionBarItem's Tag for lookup end; QryItems.Close; QryItems.SQL.Clear; QryItems.SQL.Add('SELECT * '); QryItems.SQL.Add('FROM Menu '); QryItems.SQL.Add('WHERE padre_id = :PadreIDGrupo AND activo = 1 '); // Obtener los ítems del grupo QryItems.SQL.Add('ORDER BY orden'); QryItems.Parameters.ParamByName('PadreIDGrupo').Value := PadreIDGrupo; QryItems.Open; QryItems.First; while not QryItems.Eof do // Crear los ítems dentro del grupo begin if UpperCase(QryItems.FieldByName('tipo').Value) = 'ITEM' then begin OutputDebugString(PWideChar('Creando ítem: "' + Trim(QryItems.FieldByName('titulo').Value) + '" para el grupo "' + Group.Caption + '"')); Action := TAction.Create(Self); // Action owner is the form Action.Caption := Trim(QryItems.FieldByName('titulo').Value); Action.OnExecute := ItemClick; Action.Tag := QryItems.FieldByName('menu_item_id').AsInteger; BarAction := CurrentActionBarItem.Items.Add as TActionClientItem; BarAction.Action := Action; BarAction.Caption := Trim(QryItems.FieldByName('titulo').Value); // Add the correct control to the group, linked to the ActionClientItem if QryItems.FieldByName('tipo_control').AsString = 'LARGEBUTTON' then begin Bg := TRibbonLargeButtonControl.Create(Group); // Group as owner Bg.ActionClient := BarAction; end else if QryItems.FieldByName('tipo_control').AsString = 'SMALLBUTTON' then begin Bs := TRibbonSmallButtonControl.Create(Group); // Group as owner Bs.ActionClient := BarAction; end; end; QryItems.Next; end; QryItems.Close; // Close the query for items end; // End of if tipo = 'GRUPO' QrySubMenu.Next; end; QrySubMenu.Close; // Cerrar la consulta de grupos QryMenu.Next; end; if ribMenu.Tabs.Count >= 2 then begin // Simular click en la segunda pestaña (índice 1) ribMenu.TabIndex := 1; ribMenu.TabIndex := 0; end; ribMenu.Refresh; QryMenu.Close; // Cerrar la consulta de pestañas end; Share this post Link to post