c - tutorial - gtk ubuntu



Implementación GTK de MessageBox (2)

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

gtk_init tipo de cosas de inicialización ( gtk_init ) dentro de la función MessageBox 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?


Answer #1

Unas pocas cosas:

Está creando (y no utilizando) una ventana de nivel superior innecesaria, llamada 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 bucle principal, pero sale tan pronto como se hace clic en uno de los botones.

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


Answer #2

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 llamada gtk_idle_add() agrega un método para ejecutarse cuando el ciclo principal se está ejecutando y está inactivo, y el valor de retorno FALSE de la llamada display_dialog() significa que solo se ejecuta una vez. Después de obtener el resultado del diálogo, salimos del ciclo principal. Eso hará que gtk_main() el gtk_main() en su método principal MessageBox() , y podrá acceder al resultado desde allí.

¡Espero que esto ayude!





x11