Em muitos programadores, em algum momento da vida, residiu a necessidade de se construir menus em seus sistemas digitais utilizando-se microcontroladores em conjunto com displays. Este artigo tem o objetivo de criar um algorítmo para o controle de um Menu padrão onde será possível criar sub-menus e sub-programas nas opções de confirmação do menu ou sub-menu de maneira rápida e customizável, bastando para isso pequenas modificações.
A seguir colocarei o cabeçalho do arquivo de declarações de tipos utilizados nesse artigo:
typedef struct {
const char *titulo;
int (*menu)(int *);
} opt;
O dado apresentado anteriormente é uma estrutura onde são armazenados uma string e um ponteiro para uma função. Essa função deve retornar um valor inteiro por atribuição e um valor inteiro por referência. Essa estrutura será utilizada para armazenar o título da opção do menu e uma função que será executada caso essa opção seja selecionada.
Como a estrutura apresentada somente armazena dados de uma única opção do menu, caso esse menu necessite mais de uma opção, será necessário criar um array contendo várias opções de menu e inicializar os dados desse array de estrutura, visto que a tipagem do título representa um dado do tipo const e deve ser previamente declarado, para ilustrar o que esta sendo dito aqui vejamos alguns exemplos de declarações de menus:
int func1(int*); //declaração da função que será executada pela primeira opção do menu
int func2(int*); //declaração da função que será executada pela segunda opção do menu
int func3(int*); //declaração da função que será executada pela terceira opção do menu
opt menu1[3]={ //declaração de um menu com 3 opções
{"Opc1", func1}, //primeira opção do menu
{"Opc2", func2}, //segunda opção do menu
{"Opc3", func3} //terceira opção do menu
};
A declaração acima descrita é de um menu com três opções onde cada uma delas possui uma função que será executada caso seja realizado algum tipo de confirmação.
Toda vez que for prescionado algum botão de alternância para selecionar outra opção do menu, a próxima opção do menu será desenhada na tela.
A declaração a seguir é de uma função que controla o menu e desenha as opões na tela:
int menu(opt *, char);
Esta função recebe como parâmetros um ponteiro para um array do tipo opt e um char que representa a quantidade de itens do menu.
O código que segue será utilizado para controlar a escrita das opções do menu e a chamada das funções das opções caso haja alguma opção confirmada.
Como o código é reentrante, ou recursivo, é necessário o desenvolvimento de uma pilha para controlar as chamadas entre um menu e outro, para isso foi criado a quantidade máxima de níveis que um menu poderá ter, isso definirá a quantidade de níveis de pilha para a modelagem de nosso código.
Observe o código que segue e verá que teremos um menu com no máximo 4 submenus.
#define qtdniveis 4
pilha stack[qtdniveis];
int nivel=-1;
int menu(opt * opcao, char qtdopt ) {
int sair=1, tecla, nopt=0, valor;
nivel++;
stack[nivel].oldopcao=opcao;
stack[nivel].oldnopt=nopt;
stack[nivel].oldqtdopt=qtdopt;
titular((const char *)(opt *)(stack[nivel].oldopcao+stack[nivel].oldnopt)->titulo);
realeaseKeys();
while(sair) {
tecla=getKey();
if(tecla) {
switch(tecla) {
case confirma: {
sair=(int)(opt*)(stack[nivel].oldopcao+stack[nivel].oldnopt)->menu(&valor);
titular((const char *)(opt*)(stack[nivel].oldopcao+stack[nivel].oldnopt)->titulo);
}break;
case mudar: {
if(++stack[nivel].oldnopt>=stack[nivel].oldqtdopt) {
stack[nivel].oldnopt=0;
}
titular((const char *)(opt*)(stack[nivel].oldopcao+stack[nivel].oldnopt)->titulo);
realeaseKeys();
} break;
case confirma | mudar: {
} break;
default: {
}
}
}
}
nivel--;
return valor;
}