c - tutorial - gtk+ visual studio




GTK-Implementierung von MessageBox (2)

Ich habe versucht, Win32 MessageBox mit GTK zu implementieren. Die App benutzt SDL / OpenGL, also ist das keine GTK-App.

Ich gtk_init die Initialisierungsart ( gtk_init ) in der MessageBox Funktion wie folgt:

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

Nun bin ich kein erfahrener GTK-Programmierer, und ich merke, dass ich wahrscheinlich etwas Schreckliches mache.

Mein Problem ist jedoch, dass der letzte Dialog, der mit dieser Funktion angezeigt wird, so lange bleibt, bis der Prozess beendet wird. Irgendwelche Ideen?


Ein paar Dinge:

Sie erstellen (und verwenden Sie nicht) ein nicht benötigtes Toplevel-Fenster namens window . Sie können diese Zeilen einfach löschen:

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

Auch scheint der Fluss nicht ganz richtig zu sein. gtk_main() startet die GTK-Hauptschleife, die blockiert, bis etwas sie verlässt. gtk_dialog_run() auch eine Hauptschleife gtk_dialog_run() , die jedoch beendet wird, sobald eine der Schaltflächen angeklickt wird.

Ich denke, es könnte für Sie genügen, die gtk_init_add() und gtk_main() zu entfernen und sich einfach mit dem Rückgabewert zu befassen. Auch der Aufruf von gtk_widget_destroy() ist nicht notwendig, da das Dialogfenster automatisch zerstört wird, wenn gtk_dialog_run () zurückkehrt.


Hmm, ok. Ich würde Code wie diesen vorschlagen, dann:

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
}

Die Struktur ist, weil Sie einige Datenstücke übergeben müssen. Der Aufruf gtk_idle_add() fügt eine Methode hinzu, die ausgeführt werden soll, wenn die Hauptschleife läuft und display_dialog() ist, und der Rückgabewert FALSE aus dem Aufruf display_dialog() bedeutet, dass sie nur einmal ausgeführt wird. Nachdem wir das Ergebnis aus dem Dialog erhalten haben, beenden wir die Hauptschleife. Das führt dazu, dass gtk_main() in Ihrer MessageBox() -Methode zurückgegeben wird und Sie von dort aus auf das Ergebnis zugreifen können.

Hoffe das hilft!





x11