【问题标题】:GTK implementation of MessageBoxMessageBox 的 GTK 实现
【发布时间】:2010-09-05 05:49:09
【问题描述】:

我一直在尝试使用 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(&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 程序员,而且我意识到我可能做错了什么。

但是,我的问题是最后一个对话框弹出了这个函数,直到进程退出。有什么想法吗?

【问题讨论】:

    标签: c linux gtk x11


    【解决方案1】:

    嗯,好的。我建议这样的代码,然后:

    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() 返回,您将能够从那里访问结果。

    【讨论】:

      【解决方案2】:

      要使用 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;
          } 
      }
      

      【讨论】:

        【解决方案3】:

        一些事情:

        您正在创建(而不是使用)一个不必要的顶层窗口,名为 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() 返回时自动销毁。

        【讨论】:

          猜你喜欢
          • 2012-10-06
          • 2019-08-22
          • 2013-12-31
          • 1970-01-01
          • 2011-11-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多