c - Implémentation GTK de MessageBox

Translate

J'ai essayé d'implémenter Win32MessageBoxen utilisant GTK. L'application utilisant SDL / OpenGL, donc ce n'est pas une application GTK.

Je gère l'initialisation (gtk_init) sorte de trucs à l'intérieur duMessageBoxfonction comme suit:

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

Maintenant, je ne suis en aucun cas un programmeur GTK expérimenté, et je me rends compte que je fais probablement quelque chose d'horriblement mal.

Cependant, mon problème est que la dernière boîte de dialogue apparue avec cette fonction reste active jusqu'à ce que le processus se termine. Des idées?

This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

Hmm, ok. Je suggérerais un code comme celui-ci, alors:

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 structure est due au fait que vous devez transmettre quelques données. legtk_idle_add()call ajoute une méthode à exécuter lorsque la boucle principale est en cours d'exécution et inactive, et leFALSEvaleur de retour dudisplay_dialog()call signifie qu'il n'est exécuté qu'une seule fois. Après avoir obtenu le résultat de la boîte de dialogue, nous quittons la boucle principale. Cela causera legtk_main()dans votre mainMessageBox()méthode à retourner, et vous pourrez accéder au résultat à partir de là.

J'espère que cela t'aides!

La source
Translate

Pour gérer une boîte de dialogue avec GTK +, utilisez un GtkDialog etgtk_dialog_run ()au lieu de gérer vous-même une fenêtre et une boucle principale.

MODIFIER / ADDENDA:

Ce que je veux dire, c'est "juste utiliser": je ne comprends pas pourquoi vous créez une fenêtre que vous n'utilisez jamais et une boucle principale qui semble inutile (du moins à partir du morceau de code que vous avez posté). Vous pouvez écrire quelque chose d'aussi court que:

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;
    } 
}
La source
Translate

Quelques choses:

Vous créez (et n'utilisez pas) une fenêtre de niveau supérieur inutile, nomméewindow. Vous pouvez simplement supprimer ces lignes:

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

De plus, le flux ne semble pas tout à fait correct.gtk_main()démarre la boucle principale GTK, qui se bloque jusqu'à ce que quelque chose la quitte.gtk_dialog_run()démarre également une boucle principale, mais elle se termine dès que l'un des boutons est cliqué.

Je pense qu'il vous suffira peut-être de supprimer legtk_init_add()etgtk_main()appels, et traitez simplement la valeur de retour. Égalementgtk_widget_destroy()n'est pas nécessaire, car la fenêtre de dialogue est automatiquement détruite lorsque gtk_dialog_run () revient.

La source