2013-06-26 2 views
2

나는 (SDL을 사용하고 있습니다.) 잘 작동하는 크로스 플랫폼 게임 엔진에서 일하고 있습니다. 그러나 SDL 또는 OpenGL (화면에 렌더링)을 사용하지 않고도 사용자에게 메시지 상자를 표시하는 간단한 방법이 필요합니다. 화면이 파괴되었거나 아직 생성되지 않은 경우 화면에 메시지를 렌더링 할 수 없습니다.Linux 용 SDL 크로스 플랫폼 메시지 상자

각 플랫폼에 대해 여러 구현으로 된 메시지 상자 기능을 구현했습니다. Windows 구현은 MessageBox를 사용하고 Mac OS X 구현은 Cocoa의 NSAlert를 사용하며 Linux 구현에 사용할 수있는 것을 모르겠습니다. X11은 SDL이 리눅스에서 윈도우 잉 (windowing)을 위해 사용하기 때문에 생각했습니다.

나는 다른 답변을 시도했지만 너무 애매하거나 X11 등으로 전체 게임 엔진을 다시 조작해야합니다. 콘솔 응용 프로그램에서 사용할 수있는 Windows MessageBox 함수와 같은 응용 프로그램과 독립적 인 솔루션을 찾으려고합니다.

참고 : Mac 및 Windows 구현 코드는 모두 잘 작동합니다. 도움이 필요한 Linux 구현 일뿐입니다.

오, Mac OS X에서 컴파일 할 때 Objective-C++를 활용하므로 C++ msgbox() 함수와 함께 Cocoa (Objective-C)를 혼합 할 수 있습니다.

msgbox.h

#ifndef MSGBOX_H 
#define MSGBOX_H 

//Cross-platform message box method. 
#include "platform.h" 
#include "string.h" 

//This is my own cross platform enum for message boxes. 
//This enumeration 'overlaps' with some declarations in windows.h but that is fine. 
enum //Message box values. 
{ 
    MB_OK, //For OK message box and return value. 
    MB_OKCANCEL, 
    MB_YESNO, 
    MB_RETRYCANCEL, 
    MB_YESNOCANCEL, 
    MB_ABORTRETRYIGNORE, 
    MB_CANCELTRYCONTINUE, 
    MB_CANCEL, 
    MB_YES, 
    MB_NO, 
    MB_RETRY, 
    MB_IGNORE, 
    MB_TRYAGAIN, 
    MB_CONTINUE, 
    MB_ABORT, 
}; 

//The message box function (multiple implementations for each platform). 
int msgbox(string msg, string title, int buttons); 

#endif // MSGBOX_H 

msgbox.cpp

#include "msgbox.h" 

#if CURRENT_PLATFORM == PLATFORM_WINDOWS //We can use the windows API for our messagebox. 

#include <windows.h> //For the message box function. 
#define IDTRYAGAIN 10 //Some fixes to help this application compile. 
#define IDCONTINUE 11 

int msgbox(string msg, string title, int buttons) 
{ 
    //Display the mesagebox. 
    int retval = MessageBox(NULL, msg.c_str(), title.c_str(), buttons | MB_ICONEXCLAMATION | MB_SYSTEMMODAL); 

    //Map the windows return value to ours. 
    switch(retval) 
    { 
    case IDOK:  return MB_OK; 
    case IDCANCEL: return MB_CANCEL; 
    case IDYES:  return MB_YES; 
    case IDNO:  return MB_NO; 
    case IDRETRY: return MB_RETRY; 
    case IDIGNORE: return MB_IGNORE; 
    case IDTRYAGAIN:return MB_TRYAGAIN; 
    case IDCONTINUE:return MB_CONTINUE; 
    } 
} 

#elif CURRENT_PLATFORM == PLATFORM_MACOSX //Use Cocoa to display the message box. 

int msgbox(string msg, string title, int buttons) 
{ 
    NSString* defbutton = nil; 
    NSString* altbutton = nil; 
    NSString* otherbutton = nil; 

    switch(buttons) 
    { 
    default: 
    case MB_OK: 
     defbutton = @"Ok"; 
     break; 

    case MB_OKCANCEL: 
     defbutton = @"Ok"; 
     altbutton = @"Cancel"; 
     break; 

    case MB_RETRYCANCEL: 
     defbutton = @"Retry"; 
     altbutton = @"Cancel"; 
     break; 

    case MB_YESNO: 
     defbutton = @"Yes"; 
     altbutton = @"No"; 
     break; 

    case MB_YESNOCANCEL: 
     defbutton = @"Yes"; 
     altbutton = @"No"; 
     otherbutton = @"Cancel"; 
     break; 

    case MB_ABORTRETRYIGNORE: 
     defbutton = @"Abort"; 
     altbutton = @"Retry"; 
     otherbutton = @"Ignore"; 
     break; 

    case MB_CANCELTRYCONTINUE: 
     defbutton = @"Cancel"; 
     altbutton = @"Try Again"; 
     otherbutton = @"Continue"; 
     break; 
    } 

    NSAlert* alert = [NSAlert alertWithMessageText:[NSString  stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]] 
           defaultButton:defbutton 
           alternateButton:altbutton 
            otherButton:otherbutton 
        informativeTextWithFormat:@"%s", msg.c_str()]; 

    //brings this 'application' to the front. 
    [[NSRunningApplication currentApplication]  activateWithOptions:NSApplicationActivateIgnoringOtherApps]; 
    NSInteger retval = [alert runModal]; 

    //Convert the NSAlert return values into my MB_* return values. 
    if(retval == NSAlertDefaultReturn) 
    { 
     switch(buttons) 
     { 
     case MB_OK: 
     case MB_OKCANCEL: 
      return MB_OK; 

     case MB_YESNO: 
     case MB_YESNOCANCEL: 
      return MB_YES; 

     case MB_ABORTRETRYIGNORE: 
      return MB_ABORT; 

     case MB_CANCELTRYCONTINUE: 
      return MB_CANCEL; 

     case MB_RETRYCANCEL: 
      return MB_RETRY; 
     } 
    } else if(retval == NSAlertAlternateReturn) 
    { 
     switch(buttons) 
     { 
     case MB_OKCANCEL: 
     case MB_RETRYCANCEL: 
      return MB_CANCEL; 

     case MB_YESNO: 
     case MB_YESNOCANCEL: 
      return MB_NO; 

     case MB_ABORTRETRYIGNORE: 
      return MB_RETRY; 

     case MB_CANCELTRYCONTINUE: 
      return MB_TRYAGAIN; 
     } 
    } else if(retval == NSAlertOtherReturn) 
    { 
     switch(buttons) 
     { 
     case MB_YESNOCANCEL: 
      return MB_CANCEL; 

     case MB_ABORTRETRYIGNORE: 
      return MB_IGNORE; 

     case MB_CANCELTRYCONTINUE: 
      return MB_CONTINUE; 
     } 
    } 

    return NULL; 
} 

#else 

int msgbox(string msg, string title, int buttons) 
{ 
    //WHAT DO I DO?????? 
    return 0; 
} 

//#error No implementation of message boxes on current platform! 
#endif // CURRENT_PLATFORM 

편집 : 내가하지 않으려는 여기

내가 윈도우 & 맥 구현을 위해 지금까지 가지고있는 코드입니다 몇 가지 이유로 Qt를 사용하십시오 : 너무 무거워서 내 컴퓨터에서 작동하지 않습니다 & i 이 프로그램에 대한 충분한 통제권을주지 못합니다. 어쨌든 다른 게임 라이브러리에 의존하지 않고 취미 프로젝트로 처음부터이 게임 엔진을 만들려고합니다. 결국 SDL을 내 코드로 대체하려고합니다.

+0

왜 여기

코드입니다 대신 Qt와 같은 크로스 플랫폼 GUI 툴킷을 사용 하시겠습니까? 그렇다면 이것에 대해 걱정할 필요가 없습니다. –

+0

Qt의 지원을 넘어 더 많은 플랫폼을 목표로 삼을 것입니다. 또한 Qt는 내 마음에 들기에 너무 무거워서 메시지 루프 등을 제어하지 못합니다. Qt를 이미 사용해 보았고 내 주요 개발 컴퓨터에서 작동하지 않습니다. – hddh

+0

실제 질문은 무엇입니까? 예를 들어 Xlib 또는 OpenMotif를 사용하여 비 대한 라이브러리가없는 Linux에서 메시지 상자를 표시하는 데는 여러 가지 방법이 있습니다. – scai

답변

2

SDL 2.0의 SDL_ShowMessageBox를 사용하는 간단한 래퍼 함수를 ​​만들었으며 이전에 제출 한 코드를 대체했으며 Linux의 Mac 인 & Windows에서 작동합니다.

SDL 2.0은 (http://www.libsdl.org/tmp/download-2.0.php)에서 찾을 수 있습니다.

Linux에서 직접 SDL 2를 빌드해야합니다 - 제공된 페이지에서 소스 코드를 다운로드 한 다음 INSTALL.txt의 설치 지침을 따르십시오 (SDL 2를 빌드 한 후 라이브러리는/usr에 저장됩니다)/local/lib 폴더 - 링커를 이동하거나 링커에게 위치를 알려 주어야합니다 (포함 파일은 include 디렉토리에 있습니다).

예 (내 함수를 사용하여) :

int i = showMessageBox(mySDLWindow, "Message", "Title", 3, MB_BUTTONS("BUTTON 1", "BUTTON 2", "BUTTON 3"), 0); 
printf("Button %i was pressed", i + 1); 

messagebox.h :

//Cross-platform message box method. 
#include <string> 
#include <SDL/SDL.h> //SDL 2.0 header file 

//Helper macro 
#define MB_BUTTONS(...) ((char*[]) {__VA_ARGS__}) 

//Flexible message box function. 
//Returns the index of button pressed on success or a negative value on a failure. 
//The parent argument can be set to NULL if not available. 
int showMessageBox(SDL_Window *parent, std::string msg, std::string title, 
        int count, char* buttons[], int defbutton = 0); 

messagebox.cpp :

//Complex function 
int showMessageBox(SDL_Window *parent, string msg, string title, 
        int count, char* buttons[], int defbutton) 
{ 
    //Variables. 
    int resultButton = 0; 
    SDL_MessageBoxData mbdata; 

    //Set the message box information. 
    mbdata.flags = SDL_MESSAGEBOX_INFORMATION; 
    mbdata.message = msg.c_str(); 
    mbdata.title = title.c_str(); 
    mbdata.colorScheme = NULL; 
    mbdata.window = parent; 
    mbdata.numbuttons = count; 

    //Allocate buttons. 
    SDL_MessageBoxButtonData *butarray = new SDL_MessageBoxButtonData[mbdata.numbuttons]; 

    //Set the button values. 
    for(unsigned char i = 0; i < mbdata.numbuttons; i++) 
    { 
     //Is this button the default button? 
     if(i == defbutton) 
     { 
      butarray[i].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; 
     } else 
     { 
      butarray[i].flags = 0; 
     } 

     //Set button text. 
     if(buttons[i] != NULL) 
     { 
      butarray[i].text = buttons[i]; 
     } 

     //Set button ID. 
     butarray[i].buttonid = i; 
    } 

    //Set the message box data's button array. 
    mbdata.buttons = butarray; 

    //Display the message box. 
    int retval = SDL_ShowMessageBox(&mbdata, &resultButton); 

    //Deallocate the buttons array to prevent memory leaks. 
    delete[] butarray;   

    //Return the result (-1 on failure or if the dialog was closed). 
    return retval < 0 ? -1 : resultButton; 
} 
+0

"데비안 -ish 배포판을 사용한다면'/ usr/local'은'pkg-config '에 필요한 다양한'PATH'에 있어야합니다. 'SDL2의 정보 파일을받습니다. 'sudo ldconfig '는 일반적으로 해를 끼치 지 않습니다. – genpfault

+0

예 ldconfig를 사용하여 usr/local/lib를 경로에 추가했습니다. – hddh

1

나는 gdialog/kdialog를 사용 중이며 명령 줄에서 메시지를 전달합니다. 코드는 다음과 같습니다.

이것은 세계에서 가장 강력한 코드는 아니지만 적어도 게임에서는 필자가 실패한 것을 결코 보지 못했습니다. Code-wise 의존성이 없지만, 명령 행을 망가뜨린 문자열, 즉 <,>, &,! \와 같은 이스케이프 문자와 ASCII가 아닌 모든 문자를 사용하지 않아야합니다.

SDL 2.0에는 SDL_ShowMessageBox가 있습니다.

+0

이것은 설치중인'gdialog' 또는'kdialog'에 의존합니다. 아마도 더 많은 수의 시스템에서 사용할 수 있지만 공상은 덜한'xmessage'도 있습니다. – scai

+0

SDL 2.0이 아직 출시되지 않았다는 것을 알지 못했습니다. .lib 및 헤더 파일은 어디에서 얻을 수 있습니까? (나는 GCC/MinGW를 사용하고있다). – hddh

+0

SDL 2.0 라이브러리를 찾았습니다. – hddh