implementazione GTK di MessageBox

voti
28

Ho cercato di implementare di Win32 MessageBoxutilizzando GTK. L'applicazione utilizza SDL / OpenGL, quindi questo non è un applicazione GTK.

Mi occupo l'inizializzazione ( gtk_init) genere di cose all'interno della MessageBoxfunzione come segue:

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

Ora, io sono in alcun modo un programmatore esperto GTK, e mi rendo conto che probabilmente sto facendo qualcosa di terribilmente sbagliato.

Tuttavia, il mio problema è che l'ultima finestra di dialogo spuntato con questa funzione rimane intorno fino a quando le uscite di processo. Qualche idea?

È pubblicato 02/08/2008 alle 00:27
fonte dall'utente
In altre lingue...                            


3 risposte

voti
5

Poche cose:

Si sta creando (e non usando) una finestra di primo livello non necessaria, di nome window. Si può solo eliminare queste righe:

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

Inoltre, il flusso non sembra giusto. gtk_main()avvia il ciclo principale GTK, che blocca fino a quando qualcosa esce di esso. gtk_dialog_run()inizia anche un ciclo principale, ma esce non appena uno dei pulsanti viene cliccato.

Penso che potrebbe essere sufficiente per voi per rimuovere le gtk_init_add()e gtk_main()chiamate, e semplicemente a che fare con il valore di ritorno. Anche la gtk_widget_destroy()chiamata non è necessaria, come la finestra di dialogo viene distrutto automaticamente quando gtk_dialog_run rendimenti ().

Risposto il 02/08/2008 a 19:49
fonte dall'utente

voti
16

Hmm va bene. Io suggerirei di codice come questo, allora:

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 struct è perché è necessario passare intorno un paio di pezzi di dati. La gtk_idle_add()chiamata aggiunge un metodo da eseguire quando il ciclo principale è attivo e inattivo, e il FALSEvalore restituito dalla display_dialog()chiamata significa che è eseguito solo una volta. Dopo aver ottenuto il risultato dalla finestra di dialogo, abbiamo smesso il ciclo principale. Che verrà causare l' gtk_main()nel vostro principale MessageBox()metodo per restituire, e sarete in grado di accedere al risultato da lì.

Spero che questo ti aiuti!

Risposto il 03/08/2008 a 03:30
fonte dall'utente

voti
6

Per gestire una finestra di dialogo con GTK +, utilizzare un GtkDialog e gtk_dialog_run () invece di gestire una finestra e un ciclo principale da soli.

EDIT / ADDENDUM:

Quello che voglio dire è "solo uso": Non capisco il motivo per cui si crea una finestra che non usate mai e un anello principale che sembra inutile (almeno dal pezzo di codice che hai postato). È possibile scrivere qualcosa di più breve:

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;
    } 
}
Risposto il 02/06/2010 a 16:59
fonte dall'utente

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