2008-08-01 71 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; 
    } 
}