Question

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

Je m'occupe de l'initialisation (gtk_init) une sorte de truc à l'intérieur du MessageBox fonctionner 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'à la fin du processus.Des idées?

Était-ce utile?

La solution

Hum, d'accord.Je suggérerais alors un code comme celui-ci :

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 éléments de données.Le gtk_idle_add() L'appel ajoute une méthode à exécuter lorsque la boucle principale est en cours d'exécution et inactive, et l'appel FALSE valeur de retour du display_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 provoquera le gtk_main() dans votre principal MessageBox() méthode de retour, et vous pourrez accéder au résultat à partir de là.

J'espère que cela t'aides!

Autres conseils

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

MODIFIER / ADDENDUM :

Ce que je veux dire, c'est "utiliser simplement" :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 d'après le 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;
    } 
}

Quelques choses:

Vous créez (et n'utilisez pas) une fenêtre de niveau supérieur inutile, nommée window.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 déroulement ne semble pas tout à fait correct. gtk_main() démarre la boucle principale GTK, qui se bloque jusqu'à ce que quelque chose en sorte. gtk_dialog_run() démarre également une boucle principale, mais elle se termine dès que l'on clique sur l'un des boutons.

Je pense qu'il suffirait peut-être de supprimer le gtk_init_add() et gtk_main() appels, et traitez simplement la valeur de retour.Également gtk_widget_destroy() L'appel n'est pas nécessaire, car la fenêtre de dialogue est automatiquement détruite au retour de gtk_dialog_run().

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top