c - GTK-Implementierung von MessageBox

Translate

Ich habe versucht, Win32 zu implementierenMessageBoxmit GTK. Die App verwendet SDL / OpenGL, dies ist also keine GTK-App.

Ich kümmere mich um die Initialisierung (gtk_init) Sachen in derMessageBoxFunktion 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;
} 

Jetzt bin ich kein erfahrener GTK-Programmierer und mir ist klar, dass ich wahrscheinlich etwas schrecklich Falsches mache.

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

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

Alle Antworten

Translate

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

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 ein paar Datenstücke weitergeben müssen. Dasgtk_idle_add()call fügt eine Methode hinzu, die ausgeführt werden soll, wenn die Hauptschleife ausgeführt wird und inaktiv ist, und dieFALSERückgabewert von derdisplay_dialog()call bedeutet, dass es nur einmal ausgeführt wird. Nachdem wir das Ergebnis aus dem Dialog erhalten haben, verlassen wir die Hauptschleife. Das wird das verursachengtk_main()in deiner HauptsacheMessageBox()Methode, um zurückzukehren, und Sie können von dort aus auf das Ergebnis zugreifen.

Hoffe das hilft!

Quelle
Translate

Verwenden Sie einen GtkDialog und, um ein Dialogfeld mit GTK + zu verwaltengtk_dialog_run ()anstatt ein Fenster und eine Hauptschleife selbst zu verwalten.

EDIT / ADDENDUM:

Was ich meine ist "nur verwenden": Ich verstehe nicht, warum Sie ein Fenster erstellen, das Sie nie verwenden, und eine Hauptschleife, die nutzlos erscheint (zumindest aus dem Code, den Sie gepostet haben). Sie können etwas so kurz schreiben wie:

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

Ein paar Dinge:

Sie erstellen (und verwenden nicht) ein unnötiges Fenster auf oberster Ebene mit dem Namenwindow. 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 der Fluss scheint nicht ganz richtig zu sein.gtk_main()Startet die GTK-Hauptschleife, die blockiert, bis etwas sie verlässt.gtk_dialog_run()Startet auch eine Hauptschleife, die jedoch beendet wird, sobald auf eine der Schaltflächen geklickt wird.

Ich denke, es könnte für Sie ausreichen, die zu entfernengtk_init_add()undgtk_main()ruft auf und behandelt einfach den Rückgabewert. Auch dergtk_widget_destroy()Ein Aufruf ist nicht erforderlich, da das Dialogfenster automatisch zerstört wird, wenn gtk_dialog_run () zurückkehrt.

Quelle