39

MessageBox私はGTKを使用してWin32を実装しようとしています。アプリはSDL/OpenGLを使用しているため、これはGTKアプリではありません。

関数内で初期化(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プログラマーではなく、恐らくひどく間違ったことをしていることに気づきました。

ただし、私の問題は、プロセスが終了するまでこの関数が表示されたまま最後のダイアログが表示されることです。何か案は?

4

3 に答える 3

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()1 回だけ実行されることを意味します。ダイアログから結果を取得したら、メイン ループを終了します。これにより、gtk_main()メインMessageBox()メソッドの が返され、そこから結果にアクセスできるようになります。

于 2008-08-03T02:30:05.907 に答える
7

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;
    } 
}
于 2010-06-02T15:59:04.987 に答える
5

いくつかのこと:

という名前の不要なトップレベル ウィンドウを作成しています (使用していません) 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()もメイン ループを開始しますが、ボタンの 1 つがクリックされるとすぐに終了します。

gtk_init_add()andgtk_main()呼び出しを削除して、戻り値を処理するだけで十分だと思います。また、gtk_widget_destroy()gtk_dialog_run() が戻ると、ダイアログ ウィンドウは自動的に破棄されるため、この呼び出しは不要です。

于 2008-08-02T18:49:30.390 に答える