Jump to content
steelha

Delphi 12 Ribbon Issue

Recommended Posts

 

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;

preview.png

preview2.png

Share this post


Link to post

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

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×