2008-08-01 70 views
27

的我一直在努力實現的Win32的使用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()調用增加了一個方法,主迴路運行時要運行和閒置,並從display_dialog()調用FALSE返回值意味着它只能運行一次。從對話框中得到結果後,我們退出主循環。這會導致MessageBox()方法中的gtk_main()返回,並且您將能夠從那裏訪問結果。

希望這會有所幫助!

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(),而不是自行管理窗口和主循環。

編輯/附錄:

我的意思是「只使用」:我不明白爲什麼要創建一個Windows從不使用和好像沒用(至少從片的主循環你發佈的代碼)。你可以寫短的東西:

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