代码之家  ›  专栏  ›  技术社区  ›  Razzupaltuff

MS Windows中类似Linux的(C++)MessageBox

  •  7
  • Razzupaltuff  · 技术社区  · 16 年前

    我需要为Linux(SDL)应用程序实现一个简单的图形消息框,类似于C++中的Windows MexEdbox(Gcc/G+4.4.0)。它所需要做的只是显示一个标题、一条消息和一个ok或close按钮,并在单击该按钮时返回调用函数。

    SDL只使用X(11)打开一个窗口进行(OpenGL)渲染。

    我还尝试了wxWidgets的wxMessageBox函数,但编译头会使编译器抛出有关include/c++/4.4.0/bits/stl_algobase.h(openSuSE 11.1 32位上的gcc 4.4.0 32位)中语法错误的错误消息。使用wxWidgets还意味着必须链接大量的库,将STL添加到我的应用程序中(除此之外它不需要STL),谁知道还有什么,所以我不想使用wxWidgets。

    所以我现在被难住了。有没有一个简单的方法来做我想做的事?或者至少是简单/简单/直接的一半?如果是,请选择哪一个(请提供尽可能多的详细信息)。

    5 回复  |  直到 16 年前
        1
  •  6
  •   THE JOATMON    12 年前

    在SDL2中,您现在可以显示消息框:

    http://wiki.libsdl.org/SDL_ShowSimpleMessageBox

    int SDL_ShowSimpleMessageBox(Uint32      flags,
                                 const char* title,
                                 const char* message,
                                 SDL_Window* window)
    

    http://wiki.libsdl.org/SDL_ShowMessageBox

    int SDL_ShowMessageBox(const SDL_MessageBoxData* messageboxdata,
                           int*                      buttonid)
    
        2
  •  3
  •   OneOfOne    16 年前

    我个人使用Qt4 QMessageBox .

    QMessageBox mb(QMessageBox::Question, "Title", "Message",  QMessageBox::Ok | QMessageBox::Cancel);
    if(mb.exec() == QMessageBox::Ok) { do_stuff(); }
    
        3
  •  2
  •   Matthew Talbert    16 年前

    看起来您必须创建顶级X11/Motif窗口。以下是一些让您开始学习的代码:

    #include <Xm/Xm.h> 
    #include <Xm/PushB.h>
    
    /* Prototype Callback function */
    
    void pushed_fn(Widget , XtPointer , 
                   XmPushButtonCallbackStruct *);
    
    
    main(int argc, char **argv) 
    
    {   Widget top_wid, button;
        XtAppContext  app;
    
        top_wid = XtVaAppInitialize(&app, "Push", NULL, 0,
            &argc, argv, NULL, NULL);
    
        button = XmCreatePushButton(top_wid, "Push_me", NULL, 0);
    
        /* tell Xt to manage button */
                    XtManageChild(button);
    
                    /* attach fn to widget */
        XtAddCallback(button, XmNactivateCallback, pushed_fn, NULL);
    
        XtRealizeWidget(top_wid); /* display widget hierarchy */
        XtAppMainLoop(app); /* enter processing loop */ 
    
    }
    
    void pushed_fn(Widget w, XtPointer client_data, 
                   XmPushButtonCallbackStruct *cbs) 
      {   
         printf("Don't Push Me!!\n");
      }
    

    here 这可能会给你更多的建议。

        4
  •  2
  •   Razzupaltuff    16 年前

    这是我的解决办法。我选择使用Motif(OpenMotif),因为它需要相对较少的额外库(Xm、Xt、X11)。根据消息大小,我的实现会打开一个简单的消息框或一个更复杂的对话框,其中包含一个不可编辑、可滚动的文本(后者取自Motif程序员手册,并根据我的目的进行了调整)。

    #include <Xm/Xm.h>
    #include <Xm/MwmUtil.h>
    #include <Xm/MainW.h>
    #include <Xm/CascadeB.h>
    #include <Xm/MessageB.h>
    #include <Xm/RowColumn.h>
    #include <Xm/Form.h>
    #include <Xm/PushBG.h>
    #include <Xm/LabelG.h>
    #include <Xm/PanedW.h>
    #include <Xm/Text.h>
    #include <Xm/DialogS.h>
    #include <Xm/Command.h>
    
    static XtAppContext appShell;
    

    确定文本消息行数和最大列数的帮助函数:

    static int MsgSize (char* pszMsg, int& nCols)
    {
    if (!(pszMsg && *pszMsg))
       return 0;
    int nRows = 1;
    nCols = 0;
    for (char* p = pszMsg; *p && (pszMsg = strchr (p, '\n')); nRows++, p = ++pszMsg) {
       if (nCols < pszMsg - p)
          nCols = pszMsg - p;
       }
    return nRows;
    }
    

    消息对话框关闭按钮的回调函数:

    void DestroyShell (Widget widget, XtPointer clientData, XtPointer callData)
    {
    Widget shell = (Widget) clientData;
    XtDestroyWidget (shell);
    // tell the application event loop to terminate w/o terminating the application
    XtAppSetExitFlag (appShell);
    }
    

    构建一个包含可滚动、不可编辑文本小部件和关闭按钮的对话框。摘自Motif程序员手册,稍加修改(无图标,单按钮),最小的窗口装饰)。

    void XmMessageDialog (const char* pszMsg, int nRows, int nCols, bool bError)
    {
        Widget       msgBox, pane, msgText, form, widget;
        void         DestroyShell(Widget, XtPointer, XtPointer);
        Arg          args [10];
        int          n = 0;
        int          i;
        Dimension    h;
    
    // Set up a DialogShell as a popup window. Set the delete window protocol response to XmDESTROY to make sure that
    // the window goes away appropriately. Otherwise, it's XmUNMAP which means it'd be lost forever, since we're not storing
    // the widget globally or statically to this function.
    Widget topWid = XtVaAppInitialize (&appShell, "D2X-XL", NULL, 0, &argc, argv, NULL, NULL);
    XtSetArg (args [0], XmNdeleteResponse, XmDESTROY);
    msgBox = XmCreateDialogShell (topWid, bError ? const_cast<char*>("Error") : const_cast<char*>("Warning"), args, 1);
    XtVaGetValues (msgBox, XmNmwmDecorations, &i, NULL);
    i &= ~(MWM_DECOR_ALL | MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE | MWM_DECOR_MENU);
    XtVaSetValues (msgBox, XmNmwmDecorations, i, NULL);
    XtVaGetValues (msgBox, XmNmwmFunctions, &i, NULL);
    i &= ~(MWM_FUNC_ALL | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_FUNC_CLOSE);
    XtVaSetValues (msgBox, XmNmwmFunctions, i, NULL);
    // Create a PanedWindow to manage the stuff in this dialog. PanedWindow won't let us set these to 0!
    XtSetArg (args [0], XmNsashWidth, 1);
    // Make small so user doesn't try to resize
    XtSetArg (args [1], XmNsashHeight, 1);
    pane = XmCreatePanedWindow (msgBox, const_cast<char*>("pane"), args, 2);
    // Create a RowColumn in the form for Label and Text widgets. This is the control area.
    form = XmCreateForm (pane, const_cast<char*>("form1"), NULL, 0);
    // prepare the text for display in the ScrolledText object we are about to create.
    n = 0;
    XtSetArg (args [n], XmNscrollVertical, True); n++;
    XtSetArg (args [n], XmNscrollHorizontal, False); n++;
    XtSetArg (args [n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
    XtSetArg (args [n], XmNeditable, False); n++;
    XtSetArg (args [n], XmNcursorPositionVisible, False); n++;
    XtSetArg (args [n], XmNwordWrap, True); n++;
    XtSetArg (args [n], XmNvalue, pszMsg); n++;
    XtSetArg (args [n], XmNrows, min (nRows, 30)); n++;
    XtSetArg (args [n], XmNcolumns, min (nCols, 120)); n++;
    msgText = XmCreateScrolledText (form, const_cast<char*>("help_text"), args, n);
    // Attachment values must be set on the Text widget's PARENT, the ScrolledWindow. This  is the object that is positioned.
    XtVaSetValues (XtParent (msgText),
                   XmNleftAttachment, XmATTACH_FORM,
                   XmNtopAttachment, XmATTACH_FORM,
                   XmNrightAttachment, XmATTACH_FORM,
                   XmNbottomAttachment, XmATTACH_FORM,
                   NULL);
    XtManageChild (msgText);
    XtManageChild (form);
    // Create another form to act as the action area for the dialog
    XtSetArg (args [0], XmNfractionBase, 5);
    form = XmCreateForm (pane, const_cast<char*>("form2"), args, 1);
    // The OK button is under the pane's separator and is attached to the left edge of the form. It spreads from
    // position 0 to 1 along the bottom (the form is split into 5 separate grids via XmNfractionBase upon creation).
    widget = XmCreatePushButtonGadget (form, const_cast<char*>("Close"), NULL, 0);
    XtVaSetValues (widget,
                   XmNtopAttachment, XmATTACH_FORM,
                   XmNbottomAttachment, XmATTACH_FORM,
                   XmNleftAttachment, XmATTACH_POSITION,
                   XmNleftPosition, 2,
                   XmNrightAttachment, XmATTACH_POSITION,
                   XmNrightPosition, 3,
                   XmNshowAsDefault, True,
                   XmNdefaultButtonShadowThickness, 1,
                   NULL);
    XtManageChild (widget);
    XtAddCallback (widget, XmNactivateCallback, DestroyShell, (XtPointer) msgBox);
    // Fix the action area pane to its current height -- never let it resize
    XtManageChild (form);
    XtVaGetValues (widget, XmNheight, &h, NULL);
    XtVaSetValues (form, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL);
    // This also pops up the dialog, as it is the child of a DialogShell
    XtManageChild (pane);
    }
    

    消息框“确定”按钮的回调函数

    void XmCloseMsgBox (Widget w, XtPointer clientData, XtPointer callData)
    {
    XtAppSetExitFlag (appShell);
    }
    

    决定是使用“简单”还是“高级”消息框,显示其中一个,并在用户单击其“关闭/确定”按钮时将其删除。

    void XmMessageBox (const char* pszMsg, bool bError)
    {
       Widget   topWid;
       int      nRows, nCols;
    
    nRows = MsgSize (const_cast<char*>(pszMsg), nCols);
    if ((nRows > 3) || (nCols > 360))
       XmMessageDialog (pszMsg, nRows, nCols, bError);
    else { // use the built-in message box
       topWid = XtVaAppInitialize (&appShell, "D2X-XL", NULL, 0, &argC, argv, NULL, NULL);
       // setup message box text
       Arg args [1];
       XmString xmString = XmStringCreateLocalized (const_cast<char*>(pszMsg));
       XtSetArg (args [0], XmNmessageString, xmString);
       // create and label message box
       Widget xMsgBox = bError
                        ? XmCreateErrorDialog (topWid, const_cast<char*>("Error"), args, 1)
                        : XmCreateWarningDialog (topWid, const_cast<char*>("Warning"), args, 1);
       // remove text resource
       XmStringFree (xmString);
       // remove help and cancel buttons
       XtUnmanageChild (XmMessageBoxGetChild (xMsgBox, XmDIALOG_CANCEL_BUTTON));
       XtUnmanageChild (XmMessageBoxGetChild (xMsgBox, XmDIALOG_HELP_BUTTON));
       // add callback to the "close" button that signals closing of the message box
       XtAddCallback (xMsgBox, XmNokCallback, XmCloseMsgBox, NULL);
       XtManageChild (xMsgBox);
       XtRealizeWidget (topWid);
       }
    XtAppMainLoop (appShell);
    XtUnrealizeWidget (topWid);
    XtDestroyApplicationContext (appShell);
    }
    
        5
  •  1
  •   Martin v. Löwis    16 年前

    我建议您研究一种支持SDL作为后端的GUI库。一个这样的库是GG,它有 ThreeButtonDlg . 当它的Run()返回时,您可以查看它的Result()。请参见其中的初始方法 minimal 例子。