我一直在试图使用GTK来实现Win32的MessageBox
。 该应用程序使用SDL / OpenGL,所以这不是一个GTK应用程序。
我在MessageBox
函数中处理初始化( gtk_init
)类的东西,如下所示:
int MessageBox(HWND hwnd, const char* text, const char* caption, UINT type) { GtkWidget *window = NULL; GtkWidget *dialog = NULL; gtk_init(>kArgc, >kArgv); 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程序员,我意识到我可能做了一些可怕的错误。
但是,我的问题是,用这个函数popup的最后一个对话框会一直存在,直到进程退出。 有任何想法吗?
嗯。。好。 我建议这样的代码,然后:
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()
返回,您将能够从那里访问结果。
希望这可以帮助!
一些东西:
您正在创建(而不是使用)不必要的顶层窗口,名为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()返回时,对话窗口会自动销毁。
要使用GTK +管理对话框,请使用GtkDialog和gtk_dialog_run(),而不是自行管理窗口和主循环。
编辑/增补:
我的意思是“只是用”:我不明白你为什么要创建一个你永远不会使用的窗口和一个似乎是无用的主循环(至少从你发布的代码段)。 你可以写一些简短的内容:
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; } }