implementação GTK de MessageBox

votos
28

Eu tenho tentado implementar do Win32 MessageBoxusando GTK. O aplicativo usando SDL / OpenGL, então isso não é um aplicativo GTK.

Eu lidar com a inicialização ( gtk_inittipo) de coisas dentro da MessageBoxfunção da seguinte forma:

int MessageBox(HWND hwnd, const char* text, const char* caption, UINT type)
{
    GtkWidget *window = NULL;
    GtkWidget *dialog = NULL;

    gtk_init(&gtkArgc, &gtkArgv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(window), delete_event, G_CALLBACK(delete_event), NULL);
    g_signal_connect(G_OBJECT(window), destroy, G_CALLBACK(destroy), NULL);
    // gcallback calls gtk_main_quit()
    gtk_init_add((GtkFunction)gcallback, NULL);

    if (type & MB_YESNO) {
        dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, text);
    } else {
        dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, text);
    }

    gtk_window_set_title(GTK_WINDOW(dialog), caption);
    gint result = gtk_dialog_run(GTK_DIALOG(dialog));

    gtk_main();

    gtk_widget_destroy(dialog);

    if (type & MB_YESNO) {
        switch (result) {
        default:
        case GTK_RESPONSE_DELETE_EVENT:
        case GTK_RESPONSE_NO:
            return IDNO;
            break;
        case GTK_RESPONSE_YES:
            return IDYES;
            break;
        }
    }

    return IDOK;
} 

Agora, eu sou de nenhuma maneira um programador experiente GTK, e eu percebo que provavelmente estou fazendo algo terrivelmente errado.

No entanto, o meu problema é que o último diálogo apareceu com esta função fica em torno de até que o processo será encerrado. Alguma ideia?

Publicado 02/08/2008 em 00:27
fonte usuário
Em outras línguas...                            


3 respostas

votos
16

Hmm, ok. Eu sugiro código como este, então:

typedef struct {
    int type;
    int result;
} DialogData;

static gboolean
display_dialog(gpointer user_data)
{
    DialogData *dialog_data = user_data;
    GtkWidget *dialog;

    if (dialog_data->type & MB_YESNO)
        dialog = gtk_message_dialog_new(...);
    else
        dialog = gtk_message_dialog_new(...);

    // Set title, etc.

    dialog_data->result = gtk_dialog_run(...);

    gtk_main_quit();  // Quits the main loop run in MessageBox()

    return FALSE;
}

int MessageBox(...)
{
    DialogData dialog_data;

    dialog_data.type = type;

    gtk_idle_add(display_dialog, &dialog_data);

    gtk_main();

    // Do stuff based on dialog_data.result
}

A estrutura é porque você precisa para passar em torno de um par de peças de dados. A gtk_idle_add()chamada adiciona um método a ser executado quando o loop principal está em execução e ocioso, eo FALSEvalor de retorno da display_dialog()chamada significa que ele só é executado uma vez. Depois de obter o resultado na caixa de diálogo, nós sair do loop principal. Isso vai fazer com que a gtk_main()sua principal MessageBox()método para retornar, e você será capaz de acessar o resultado de lá.

Espero que isto ajude!

Respondeu 03/08/2008 em 03:30
fonte usuário

votos
6

Para gerenciar uma caixa de diálogo com o GTK +, use um GtkDialog e gtk_dialog_run () em vez de gerenciar uma janela e um loop principal por si mesmo.

EDIT / ADENDO:

O que quero dizer é "apenas usar": Eu não entendo por que você cria uma janela que você nunca usa e um loop principal, que parece inútil (pelo menos a partir do pedaço de código que você postou). Você pode escrever algo tão curto quanto:

int MessageBox(HWND hwnd, const char* text, const char* caption, UINT type)
{
    GtkWidget *dialog ;

    /* Instead of 0, use GTK_DIALOG_MODAL to get a modal dialog box */

    if (type & MB_YESNO)
        dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, text );
    else
        dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, text );


    gtk_window_set_title(GTK_WINDOW(dialog), caption);
    gint result = gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy( GTK_WIDGET(dialog) );

    if (type & MB_YESNO)
    {
        switch (result)
        {
        default:
        case GTK_RESPONSE_DELETE_EVENT:
        case GTK_RESPONSE_NO:
            return IDNO;
        case GTK_RESPONSE_YES:
            return IDYES;
        }
        return IDOK;
    } 
}
Respondeu 02/06/2010 em 16:59
fonte usuário

votos
5

Algumas coisas:

Você está criando (e não usando) uma janela de nível superior desnecessário, com o nome window. Você pode simplesmente apagar estas linhas:

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_event), NULL);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);

Além disso, o fluxo não parece muito certo. gtk_main()inicia o loop principal do GTK, que bloqueia até que algo sai-lo. gtk_dialog_run()também começa um loop principal, mas ele sai, logo que um dos botões é clicado.

Eu acho que pode ser o suficiente para você para remover os gtk_init_add()e gtk_main()chamadas, e simplesmente lidar com o valor de retorno. Além disso, a gtk_widget_destroy()chamada é desnecessária, como a janela de diálogo é destruído automaticamente quando gtk_dialog_run () retorna.

Respondeu 02/08/2008 em 19:49
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more