2008-08-01 5 views
27

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

Я обрабатывать инициализацию (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 программист, и я понимаю, что я, вероятно, делать что-то ужасно неправильно.

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

ответ

17

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

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(), и вы сможете получить к нему доступ.

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

6

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

Вы создаете (и не используя) ненужное окно верхнего уровня, названный 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().

7

Чтобы управлять диалоговым окном с помощью 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; 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^