Mostrando postagens com marcador FXMessageBox. Mostrar todas as postagens
Mostrando postagens com marcador FXMessageBox. Mostrar todas as postagens

sexta-feira, 25 de setembro de 2009

FXMessageBox: Tratando a resposta do usuário

Neste tutorial, falei sobre as opções de botões que o FXMessageBox fornece ao usuário. Obviamente, cada mensagem requer um conjunto de botões adequado. Mas como saber qual botão foi pressionado?

Hoje, veremos como detectar qual o botão clicado pelo usuário, em resposta à mensagem exibida.


Relembrando o conjunto de botões

O protótipo das funções que exibem mensagens são da seguinte forma (message, aqui, é utilizado como um nome genérico para information, question, warning e error):
static FXuint message(FXWindow* owner, FXuint opts, const char* caption,
        const char* message, ...);

O parâmetro opts é onde se informa o conjunto de botões que vão aparecer na mensagem, através da seguinte enumeração (abstraindo os valores):
enum {
  MBOX_OK,
  MBOX_OK_CANCEL,
  MBOX_YES_NO,
  MBOX_YES_NO_CANCEL,
  MBOX_QUIT_CANCEL,
  MBOX_QUIT_SAVE_CANCEL,
  MBOX_SKIP_SKIPALL_CANCEL,
  MBOX_SAVE_CANCEL_DONTSAVE
};

Percebam, então, que os botões que podem aparecer em uma mensagem são:
  • OK
  • Cancel
  • Yes
  • No
  • Quit
  • Save
  • Don't save
  • Skip
  • Skip All
Tratando a resposta

Voltando ao protótipo da função, vemos que ela retorna um FXint. É justamente esse retorno que indica qual o botão pressionado. Esse valor também está presente em uma enumeração para facilitar (dar nomes a números mágicos é uma boa prática de programação). Essa enumeração é a seguinte:
enum {
  MBOX_CLICKED_YES      = 1,    /// The YES button was clicked
  MBOX_CLICKED_NO       = 2,    /// The NO button was clicked
  MBOX_CLICKED_OK       = 3,    /// The OK button was clicked
  MBOX_CLICKED_CANCEL   = 4,    /// The CANCEL button was clicked
  MBOX_CLICKED_QUIT     = 5,    /// The QUIT button was clicked
  MBOX_CLICKED_SAVE     = 6,    /// The SAVE button was clicked
  MBOX_CLICKED_SKIP     = 7,    /// The SKIP button was clicked
  MBOX_CLICKED_SKIPALL  = 8     /// The SKIP ALL button was clicked
};

Oito valores enumerados para nove botões?

É...

Fuçando no código fonte, descobri algo assim:
new FXButton(buttons, "&Don't Save", NULL, this, ID_CLICKED_NO, ...

Ou seja, o valor retornado quando o usuário clica em "Don't Save" é MBOX_CLICKED_NO. Faz sentido, mas eu acharia melhor se tivesse um nome específico, o valor até poderia ser o mesmo. Mas vai entender...



Exemplo

Vou dar um exemplo simples, até porque aqui não tem mistério nenhum (fora esse de cima...). Suponha que o usuário vai realizar uma operação que não pode ser desfeita. Isso deve ser informado ao usuário, caso ele volte atrás em sua decisão. Nosso tratador fica assim:
long FoxTutorialMainWindow::onCmdEraseAll(FXObject*, FXSelector sel, void*) {
  FXuint answer;

  answer = FXMessageBox::question(this, MBOX_YES_NO, "Apagar tudo",
      "Essa ação não pode ser desfeita.\nDeseja continuar?");

  switch (answer) {
    case MBOX_CLICKED_YES:
      FXMessageBox::information(this, MBOX_OK, "Dados apagados",
          "Todos os dados foram apagados.");
    break;

    case MBOX_CLICKED_NO:
      FXMessageBox::information(this, MBOX_OK, "Dados não apagados",
          "Os dados não foram apagados.");
    break;

    default: break;
  }

  return 1;
}

Resultado




Discussão

Nada de mais aqui. Se o usuário clicou em "Yes", exibe uma mensagem informando que todos os dados foram apagados. Se clicou em "No", informa que não foram apagados. Realmente sem mistérios.


Conclusão

Este tópico foi apenas um complemento de outro anterior (link). Aqui encerro oficialmente a série sobre o FXMessageBox. A partir daqui, começaremos a falar de elementos que compõem uma interface gráfica típica (menus, barras de ferramentas, barra de status etc.). Até lá!

segunda-feira, 25 de maio de 2009

FXMessageBox: Opções de botões

No tópico anterior, apresentei as mensagens que o FOX Toolkit fornece ao usuário através da classe FXMessageBox. Percebam que as mensagens de informação, aviso e erro possuíam apenas o botão OK, enquanto a pergunta possuía dois botões, Sim e Não.

Neste tópico, mostrarei as opções de botões disponíveis para as caixas de mensagem. Novamente, mostrarei apenas os trechos de código e o resultado, pois são bem auto-explicativos.

Os botões que devem aparecer na caixa de mensagem são passados como segundo parâmetro, e são definidos em termos de uma enumeração declarada em FXMessageBox.h:
enum {
MBOX_OK = 0x10000000,
MBOX_OK_CANCEL = 0x20000000,
MBOX_YES_NO = 0x30000000,
MBOX_YES_NO_CANCEL = 0x40000000,
MBOX_QUIT_CANCEL = 0x50000000,
MBOX_QUIT_SAVE_CANCEL = 0x60000000,
MBOX_SKIP_SKIPALL_CANCEL = 0x70000000,
MBOX_SAVE_CANCEL_DONTSAVE = 0x80000000
};


MBOX_OK
FXMessageBox::information(&app, MBOX_OK, "Informação",
"Operação finalizada");



MBOX_OK_CANCEL
FXMessageBox::question(&app, MBOX_OK_CANCEL, "Apagar tudo",
"Essa operação não pode ser desfeita.\nDeseja continuar?");



MBOX_YES_NO
FXMessageBox::question(&app, MBOX_YES_NO, "Sair",
"Sair do programa?");



MBOX_YES_NO_CANCEL
FXMessageBox::question(&app, MBOX_YES_NO_CANCEL, "Salvar arquivo",
"O arquivo foi alterado.\nDeseja salvar antes de sair?");



MBOX_QUIT_CANCEL
FXMessageBox::question(&app, MBOX_QUIT_CANCEL, "Processo em execução",
"Terminar o aplicativo encerrará um processo em andamento."
"\nDeseja mesmo sair?"
);



MBOX_QUIT_SAVE_CANCEL
FXMessageBox::question(&app, MBOX_QUIT_SAVE_CANCEL, "Salvar arquivo",
"O arquivo foi alterado.\nDeseja salvar antes de sair?");



MBOX_SKIP_SKIPALL_CANCEL
FXMessageBox::error(&app, MBOX_SKIP_SKIPALL_CANCEL, "Entrada inválida",
"Entrada inválida.");



MBOX_SAVE_CANCEL_DONTSAVE
FXMessageBox::question(&app, MBOX_SAVE_CANCEL_DONTSAVE, "Salvar arquivo",
"O arquivo foi alterado.\nDeseja salvar antes de sair?");



Em inglês?
É... open-source: quem quiser em português, tem que ir no código-fonte, traduzir e recompilar.


No próximo tópico, mostrarei como tratar a opção selecionada pelo usuário.

Até lá.

FXMessageBox: Tipos de mensagem

Esta será uma série a respeito da classe FXMessageBox. Ela serve para, como o próprio nome diz, exibir uma mensagem ao usuário de forma fácil e rápida.

Já utilizei esta classe em um tutorial passado para exibir uma mensagem de boas-vindas ao FOX Toolkit. Aquele foi apenas um tipo de mensagem dentre quatro disponíveis nesta classe:
  • informação
  • pergunta
  • aviso
  • erro

Esses quatro tipos de mensagem são fornecidos em forma de funções estáticas de FXMessageBox, ou seja, não é preciso instanciar explicitamente um objeto para exibir uma mensagem ao usuário.

Neste tópico, apenas discutirei os parâmetros de cada função, que são gerais, e mostrarei um exemplo de cada tipo, pois realmente não há muito o que explicar. Vamos lá.


Parâmetros

Cada função estática (information, question, warning, error) recebe pelo menos quatro parâmetros:
FXWindow* owner, FXuint opts, const char* caption, const char* message, ...

Existe também uma outra versão que, em vez de se passar uma janela, passa-se o aplicativo:
FXApp* app, FXuint opts, const char* caption, const char* message, ...

Essa segunda versão é útil, por exemplo, quando se deseja exibir uma mensagem ao usuário antes da janela principal ser criada.

Os parâmetros serão explicados a seguir.


FXWindow *owner / FXApp *app

Janela/aplicativo da mensagem. Nada de muito especial aqui.


FXuint opts

As opções da mensagem. Aqui se informam quais são os botões que aparecerão na mensagem (OK, Cancelar etc.). Para não ficar muito extenso, abordarei essa questão em outro tópico.


const char* caption

Título da janela com a mensagem. Também nada de especial aqui.


const char* message, ...

Texto da mensagem. Aqui, sim, há um detalhe importante.

Percebam as reticências. Isso indica que essa função recebe um número variável de parâmetros. Neste caso, no mínimo os quatro que são explicitamente declarados.

Essa mensagem é formatada pelo FOX de forma muito semelhante à função printf(). Ou seja, se eu quiser exibir uma mensagem que contenha dados da aplicação, não é necessário montá-la manualmente, pois o FOX faz isso automaticamente. Um exemplo (didático...) será mostrado mais à frente.


Exemplos

Nesta seção, mostrarei um exemplo de cada tipo de mensagem. O código-fonte para esse tutorial está disponível no final do tópico.

Serão mostrados apenas o trecho de código usado para exibir a mensagem e uma captura de tela da mensagem.
Obs.: Apenas lembrando, pelo fato de serem funções estáticas, são chamadas diretamente da classe, sem necessidade de instanciar um objeto, através do operador de escopo (::).

Informação
FXMessageBox::information(this, MBOX_OK, "Informação",
"Operação finalizada");




Pergunta
FXMessageBox::question(this, MBOX_YES_NO, "Sair",
"Deseja realmente sair do programa?");




Aviso
FXMessageBox::warning(this, MBOX_OK, "Aviso",
"Valor não especificado.\nAtribuindo padrão 1.");




Erro
FXMessageBox::error(this, MBOX_OK, "Erro",
"%s: Arquivo não encontrado", filename.text())




Discussão

Em primeiro lugar, percebam que para cada tipo de mensagem há um ícone diferente; é basicamente isso que diferencia um tipo do outro, pois o resto é igual. Essas são o que chamamos de funções de conveniência, pois automatizam tarefas comuns.

Segundo, na mensagem de aviso, eu utilizei uma quebra de linha para evitar que a mensagem fique muito longa. Isso é de controle exclusivo do usuário; o texto da mensagem é exibido através de um FXLabel, que não executa quebra de linha automática.

E terceiro, na mensagem de erro, um exemplo didático da formatação da mensagem a la printf(): a mensagem exibe o conteúdo de uma variável.


Conclusão

Esta foi apenas uma introdução às mensagens que o FOX Toolkit disponibiliza para o usuário. Existem outros aspectos relacionados, que serão discutidos em outros tópicos.

Até lá, e um abraço.

---
Código-fonte deste tutorial.