реализация GTK из MessageBox

голоса
28

Я пытался реализовать Win32 в MessageBoxиспользовании GTK. Приложение с помощью SDL / OpenGL, так что это не приложение GTK.

Я обрабатывать инициализацию ( gtk_init) рода вещи внутри MessageBoxфункции следующим образом :

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

Теперь, я ни в коем случае не опытный программист GTK, и я понимаю, что я, вероятно, делать что-то ужасно неправильно.

Тем не менее, моя проблема заключается в том, что последний диалог выскочил с этой функцией не остается вокруг, пока процесс не завершит работу. Есть идеи?

Задан 02/08/2008 в 00:27
источник пользователем
На других языках...                            


3 ответов

голоса
16

Хмм хорошо. Я хотел бы предложить такой код, то:

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
}

Структура, потому что вы должны пройти вокруг пару кусков данных. gtk_idle_add()Вызов добавляет метод , который будет работать , когда основной цикл работает и в режиме ожидания, а FALSEвозвращаемое значение от display_dialog()вызова означает , что она выполняется только один раз. После того, как мы получим результат из диалога, мы вышли из основного цикла. Это будет вызывать gtk_main()в основном MessageBox()методе , чтобы вернуться, и вы будете иметь возможность получить доступ к результату оттуда.

Надеюсь это поможет!

Ответил 03/08/2008 d 03:30
источник пользователем

голоса
6

Для управления диалогового окна с GTK +, используйте GtkDialog и gtk_dialog_run () вместо того , чтобы управлять окном и основной циклом самостоятельно.

EDIT / ДОПОЛНЕНИЕ:

То, что я имею в виду «просто использовать»: Я не понимаю, почему вы создаете окна вы никогда не использовать и основной цикл, который кажется бесполезным (по крайней мере, от части коды вы публикуемой). Вы можете написать что-то, как короткий, как:

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;
    } 
}
Ответил 02/06/2010 d 16:59
источник пользователем

голоса
5

Несколько вещей:

Вы создаете (и не использовать) ненужное окно верхнего уровня, по имени window. Вы можете просто удалить эти строки:

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

Кроме того , поток , кажется , не совсем правильно. gtk_main()начинается основной цикл GTK, который блокирует , пока что - то не выходит его. gtk_dialog_run()также начинается основной цикл, но он выходит , как только одна из кнопок нажата.

Я думаю , что это может быть достаточно для того , чтобы удалить gtk_init_add()и gtk_main()вызовы, а просто иметь дело с возвращаемым значением. Кроме того , gtk_widget_destroy()вызов не является необходимым, так как диалоговое окно автоматически уничтожается при gtk_dialog_run () возвращает.

Ответил 02/08/2008 d 19:49
источник пользователем

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