2008-08-01 24 views
27

he estado tratando de poner en práctica MessageBox usando GTK de Win32. La aplicación que usa SDL/OpenGL, por lo que esta no es una aplicación GTK.aplicación GTK del cuadro de mensaje

que manejan la inicialización (gtk_init) tipo de cosas dentro de la función MessageBox 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, yo soy de ninguna manera un programador experimentado GTK, y se dan cuenta de que probablemente estoy haciendo algo terriblemente mal.

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

Respuesta

17

Hmm, bien. Yo sugeriría 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 hay que pasar alrededor de un par de piezas de datos. La llamada gtk_idle_add() añade un método para ejecutarse cuando el bucle principal está en funcionamiento y en reposo, y el valor FALSE regreso de la llamada display_dialog() significa que es sólo ejecuta una vez. Después de obtener el resultado del diálogo, salimos del ciclo principal. Eso va a causar la gtk_main() en su principal método MessageBox() volver, y usted será capaz de acceder al resultado de allí.

Espero que esto ayude!

6

algunas cosas:

va a crear (y no usar) una ventana de nivel superior innecesaria, llamado window. Puede 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 se bloquea hasta que algo sale de él. gtk_dialog_run() también inicia un ciclo principal, pero sale tan pronto como se presiona uno de los botones.

yo creo que puede ser suficiente para que usted pueda eliminar los gtk_init_add() y gtk_main() llamadas, y simplemente tratar 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().

7

Para administrar un cuadro de diálogo con GTK +, use un GtkDialog y gtk_dialog_run() en lugar de administrar una ventana y un bucle principal usted mismo.

EDITAR/Adición:

Lo que quiero decir es "sólo uso": No entiendo por qué se crea una ventana y que nunca usa un bucle principal que parece inútil (por lo menos desde la pieza de código que publicaste). 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; 
    } 
} 
Cuestiones relacionadas