문제
나는 Win32를 구현하려고 노력해 왔습니다. MessageBox
GTK를 사용합니다.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(>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 프로그래머가 아니며 아마도 뭔가 끔찍하게 잘못된 일을 하고 있다는 것을 깨달았습니다.
그러나 내 문제는 이 기능을 사용하여 팝업된 마지막 대화 상자가 프로세스가 종료될 때까지 계속 유지된다는 것입니다.어떤 아이디어가 있나요?
해결책
음 알았어.그렇다면 다음과 같은 코드를 제안하겠습니다.
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()
call은 한 번만 실행된다는 의미입니다.대화 상자에서 결과를 얻은 후 메인 루프를 종료합니다.그로 인해 gtk_main()
당신의 메인에 MessageBox()
메서드를 반환하면 거기에서 결과에 액세스할 수 있습니다.
도움이 되었기를 바랍니다!
다른 팁
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;
}
}
몇 가지:
이름이 불필요한 최상위 창을 만들고 사용하지 않고 있습니다. 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()이 반환되면 대화상자 창이 자동으로 소멸되므로 호출이 필요하지 않습니다.