Implémentation GTK de MessageBox

J'ai essayé d'implémenter MessageBox de Win32 en utilisant GTK. L'application utilise SDL/OpenGL, donc ce n'est pas une application GTK.

Je gère le genre de trucs d'initialisation (gtk_init) à l'intérieur de la fonction MessageBox 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 jusqu'à ce que le processus se termine. Des idées ?

请先 登录 后评论

1 réponses

Joe Shaw

Hum, d'accord. 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. L'appel gtk_idle_add() ajoute une méthode à exécuter lorsque la boucle principale est en cours d'exécution et inactive, et la valeur de retour FALSE de l'appel display_dialog() signifie que 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 entraînera le retour du gtk_main() dans votre méthode principale MessageBox(), et vous pourrez accéder au résultat à partir de là.

J'espère que cela vous aidera !

请先 登录 后评论