2008-08-01 33 views
27

Tôi đã cố gắng triển khaicủa Win32 bằng GTK. Ứng dụng sử dụng SDL/OpenGL, vì vậy đây không phải là ứng dụng GTK.Triển khai GTK của MessageBox

tôi xử lý khởi động (gtk_init) loại công cụ bên trong MessageBox chức năng như sau:

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

Bây giờ, tôi không phải là một lập trình viên GTK giàu kinh nghiệm, và tôi nhận ra rằng tôi đang làm điều gì đó có thể sai lầm khủng khiếp.

Tuy nhiên, sự cố của tôi là hộp thoại cuối cùng xuất hiện với chức năng này vẫn tồn tại cho đến khi quá trình thoát. Bất kỳ ý tưởng?

Trả lời

17

Hmm, ok. Tôi muốn đề xuất mã như thế này, sau đó:

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 
} 

Cấu trúc này là vì bạn cần truyền một vài mẩu dữ liệu. Cuộc gọi gtk_idle_add() thêm phương thức sẽ chạy khi vòng lặp chính đang chạy và không hoạt động và giá trị trả về FALSE từ cuộc gọi display_dialog() có nghĩa là phương thức đó chỉ chạy một lần. Sau khi chúng tôi nhận được kết quả từ hộp thoại, chúng tôi thoát khỏi vòng lặp chính. Điều đó sẽ làm cho số gtk_main() trong phương thức MessageBox() chính của bạn trở lại và bạn sẽ có thể truy cập kết quả từ đó.

Hy vọng điều này sẽ hữu ích!

6

Một vài điều:

Bạn đang tạo (và không sử dụng) một cửa sổ mục cấp đầu không cần thiết, tên window. Bạn chỉ có thể xóa các dòng sau:

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

Ngoài ra, luồng này dường như không đúng. gtk_main() bắt đầu vòng lặp chính GTK, sẽ chặn cho đến khi có thứ gì đó thoát ra. gtk_dialog_run() cũng bắt đầu một vòng lặp chính, nhưng nó sẽ thoát ngay sau khi một trong các nút được nhấp.

Tôi nghĩ rằng có thể đủ để bạn xóa các cuộc gọi gtk_init_add()gtk_main() và chỉ cần xử lý giá trị trả lại. Ngoài ra, cuộc gọi gtk_widget_destroy() là không cần thiết vì cửa sổ hộp thoại sẽ tự động bị hủy khi gtk_dialog_run() trả về.

7

Để quản lý hộp thoại với GTK +, hãy sử dụng GtkDialog và gtk_dialog_run() thay vì quản lý cửa sổ và vòng lặp chính của chính bạn.

EDIT/PHỤ LỤC:

Những gì tôi có nghĩa là "chỉ cần sử dụng": Tôi không hiểu tại sao bạn tạo ra một cửa sổ mà bạn không bao giờ sử dụng và một vòng lặp chính mà dường như vô dụng (ít nhất là từ các mảnh mã bạn đã đăng). Bạn có thể viết một cái gì đó ngắn như:

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