Implementación GTK de MessageBox

votos
28

He estado tratando de implementar Win32 MessageBoxusando GTK. La aplicación que usa SDL / OpenGL, por lo que esta no es una aplicación GTK.

Manejo el gtk_inittipo de cosas de inicialización ( ) dentro de la MessageBoxfunción de la siguiente manera:

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;
} 

Ahora, de ninguna manera soy un programador experimentado de GTK, y me doy cuenta de que probablemente estoy haciendo algo horriblemente mal.

Sin embargo, mi problema es que el último cuadro de diálogo que aparece con esta función se mantiene hasta que el proceso finaliza. ¿Algunas ideas?

Publicado el 02/08/2008 a las 00:27
fuente por usuario
En otros idiomas...                            


3 respuestas

votos
16

Mmm, ok. Sugeriría un código como este, entonces:

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
}

La estructura es porque necesitas pasar un par de datos. La gtk_idle_add()llamada agrega un método para ejecutarse cuando el ciclo principal se está ejecutando y está inactivo, y el FALSEvalor de retorno de la display_dialog()llamada significa que solo se ejecuta una vez. Después de obtener el resultado del diálogo, salimos del ciclo principal. Eso hará que regrese el método gtk_main()principal MessageBox()y podrá acceder al resultado desde allí.

¡Espero que esto ayude!

Respondida el 03/08/2008 a las 03:30
fuente por usuario

votos
6

Para administrar un cuadro de diálogo con GTK +, use un GtkDialog y gtk_dialog_run () en lugar de la gestión de una ventana y un bucle principal por sí mismo.

EDIT / Adición:

Lo que quiero decir es "solo uso": No entiendo por qué se crea una ventana y que nunca usa un bucle principal que parece inútil (al menos desde el trozo de código que envió). Se puede escribir algo tan corto como:

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;
    } 
}
Respondida el 02/06/2010 a las 16:59
fuente por usuario

votos
5

Unas pocas cosas:

Está creando (y no utilizando) una ventana de nivel superior innecesaria, nombrada window. Puedes simplemente eliminar estas líneas:

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);

Además, el flujo no parece del todo correcto. gtk_main()inicia el bucle principal de GTK, que bloquea hasta que algo sale de él. gtk_dialog_run()también inicia un ciclo principal, pero sale tan pronto como se hace clic en uno de los botones.

Creo que podría ser suficiente para que usted pueda eliminar los gtk_init_add()y gtk_main()las llamadas, y simplemente tratar con el valor de retorno. Además, la gtk_widget_destroy()llamada es innecesaria, ya que la ventana de diálogo se destruye automáticamente cuando devuelve gtk_dialog_run ().

Respondida el 02/08/2008 a las 19:49
fuente por usuario

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