GTK-Implementierung von MessageBox

Lesezeit: 4 Minuten

Benutzeravatar von Bernard
Bernhard

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

Ich kümmere mich um die Initialisierung (gtk_init) Art von Sachen in der MessageBox funktionieren 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, ich bin keineswegs ein erfahrener GTK-Programmierer, und mir ist klar, dass ich wahrscheinlich etwas schrecklich falsch mache.

Mein Problem ist jedoch, dass der letzte Dialog mit dieser Funktion aufgetaucht ist, bis der Prozess beendet ist. Irgendwelche Ideen?

Benutzeravatar von Joe Shaw
Joe Shaw

Hm, okay. 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 erforderlich, da Sie einige Daten weitergeben müssen. Das gtk_idle_add() call fügt eine Methode hinzu, die ausgeführt werden soll, wenn die Hauptschleife ausgeführt wird und im Leerlauf ist, und die FALSE Rückgabewert von der display_dialog() Aufruf bedeutet, dass es nur einmal ausgeführt wird. Nachdem wir das Ergebnis aus dem Dialog erhalten haben, verlassen wir die Hauptschleife. Das wird die verursachen gtk_main() in deiner Hauptsache MessageBox() zurückzugebende Methode, und Sie können von dort aus auf das Ergebnis zugreifen.

Benutzeravatar von Platypus
Schnabeltier

Um ein Dialogfeld mit GTK+ zu verwalten, verwenden Sie ein GtkDialog and gtk_dialog_run() anstatt ein Fenster und eine Hauptschleife selbst zu verwalten.

BEARBEITEN / NACHTRAG:

Was ich meine, ist “einfach verwenden”: Ich verstehe nicht, warum Sie ein Fenster erstellen, das Sie nie verwenden, und eine Hauptschleife, die nutzlos erscheint (zumindest aus dem von Ihnen geposteten Codestück). Sie können etwas so kurzes 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;
    } 
}

Benutzeravatar von Joe Shaw
Joe Shaw

Ein paar Dinge:

Sie erstellen (und verwenden nicht) ein unnötiges Toplevel-Fenster mit dem Namen 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);

Außerdem scheint der Fluss 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 ausreichen, wenn Sie die entfernen gtk_init_add() und gtk_main() Aufrufe, und kümmern Sie sich einfach um den Rückgabewert. Auch die gtk_widget_destroy() Der Aufruf ist unnötig, da das Dialogfenster automatisch zerstört wird, wenn gtk_dialog_run() zurückkehrt.

1394680cookie-checkGTK-Implementierung von MessageBox

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy