Realizacja GTK z MessageBox

głosy
28

I starali się wdrożyć Win32 w MessageBoxużyciu GTK. Aplikacja za pomocą SDL / OpenGL, więc nie jest to aplikacja GTK.

I obsłużyć inicjalizacji ( gtk_init) typu rzeczy wewnątrz MessageBoxfunkcji w następujący sposób:

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

Teraz jestem bynajmniej doświadczonego programistę GTK, i zdaję sobie sprawę, że jestem prawdopodobnie robić coś strasznie złego.

Jednak moim problemem jest to, że ostatni pojawił się dialog z funkcja ta pozostaje wokół aż wyjść procesowych. Jakieś pomysły?

Utwórz 02/08/2008 o 00:27
źródło użytkownik
W innych językach...                            


3 odpowiedzi

głosy
5

Kilka rzeczy:

Podczas tworzenia (a nie przy użyciu) niepotrzebne Toplevel okno, nazwany window. Można po prostu usunąć te linie:

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

Ponadto, przepływ nie wydaje się całkiem dobrze. gtk_main()rozpoczyna GTK główną pętlę, która blokuje aż coś jego wyjściu. gtk_dialog_run()również uruchamia główną pętlę, ale to wychodzi tak szybko, jak jeden z przycisków zostanie kliknięty.

Myślę, że to wystarczy, aby usunąć gtk_init_add()i gtk_main()połączeń, a po prostu do czynienia z wartości zwracanej. Również gtk_widget_destroy()połączenie jest niepotrzebne, ponieważ okno dialogowe jest automatycznie niszczone kiedy gtk_dialog_run () zwraca.

Odpowiedział 02/08/2008 o 19:49
źródło użytkownik

głosy
16

Hmm ok. Sugeruję kod tak, to:

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
}

Struct jest, bo trzeba przejść wokół kilka fragmentów danych. gtk_idle_add()Wezwanie dodaje metodę być uruchamiany, gdy główny pętla działa i jest w stanie spoczynku, a FALSEwartość zwracana z display_dialog()połączenia oznacza, że jest prowadzony tylko raz. Po tym, jak uzyskać wynik z okna, możemy wyjść z pętli głównej. To będzie powodować gtk_main()w głównym MessageBox()sposobem, aby powrócić, a będziesz mieć dostęp wynik stamtąd.

Mam nadzieję że to pomoże!

Odpowiedział 03/08/2008 o 03:30
źródło użytkownik

głosy
6

Aby zarządzać okno dialogowe z GTK +, użyj GtkDialog i gtk_dialog_run () zamiast zarządzania oknem i główną pętlę przez siebie.

EDIT / Uzupełnienie:

Co mam na myśli to „po prostu użyć”: Nie rozumiem, dlaczego utworzyć okna nigdy użyciu i główną pętlę, która wydaje się bezużyteczne (przynajmniej z kawałkiem kodu, który pisał). Możesz napisać coś tak krótkie jak:

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;
    } 
}
Odpowiedział 02/06/2010 o 16:59
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more