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á!

Um comentário:

eduardo4jesus disse...

não sabia onde comentar... entao to comentando aqui... ^^'

Estou tendo uma dificuldade com o FXMENUBAR ,o FXMENUTITLE e o FXMENUCOMMAND...

principalmente o ultimo...

tipo. consegui criar uma barra de menu com as opçoes...
so que nao tem como eu saber se as paineis funcionaram pq nao conseguir colocar nenhum comando dentro dele...

Se possivel, tem como vc falar sobre essea 3 coisas[nao sei se sao funçoes... ou classes....] abordando os atributos??

=)

pedaços do meu codigo

FXMenuBar* menubar;
FXMenuPane* pane1;
FXMenuPane* pane2;
FXMenuPane* pane3;
FXMenuPane* pane4;
FXMenuPane* pane5;

MainWindow::MainWindow(FXApp *a)
: FXMainWindow(a, "Projeto IBF", NULL, NULL, DECOR_ALL, 0, 0, 200, 200) {

menubar=new FXMenuBar(this,LAYOUT_SIDE_TOP|LAYOUT_FILL_X);

new FXMenuTitle(menubar,"M&1",NULL,pane1);
new FXMenuTitle(menubar,"M&2",NULL,pane2);
new FXMenuTitle(menubar,"M&3",NULL,pane3);
new FXMenuTitle(menubar,"M&4",NULL,pane4);
new FXMenuTitle(menubar,"M&5",NULL,pane5);

pane1=new FXMenuPane(this);
new FXMenuCommand(pane1,"&Quit\tCtl-Q",NULL);

essa ultima linha se nao me engano vai dar alguma loucura no compilador...