我需要为Linux(SDL)应用程序实现一个简单的图形消息框,类似于C ++中的Windows MessageBox(gcc / g ++ 4.4.0)。它需要做的只是显示标题,消息和确定或关闭按钮,并在单击该按钮时返回调用功能。
SDL只使用X(11)打开(OpenGL)渲染窗口。
我已经查看了一个关于GTK实现的类似线程,但该实现似乎无法正常工作。
我也尝试了wxWidgets的wxMessageBox函数,但是编译头文件会使编译器在include / c ++ / 4.4.0 / bits / stl_algobase.h中抛出有关语法错误的错误消息(openSuSE 11.1上的gcc 4.4.0 32位)位)。使用wxWidgets还意味着必须链接大量的库,将STL添加到我的应用程序(否则不需要)以及谁知道还有什么,所以我不想使用wxWidgets。
X11 / motif(openmotif)有我需要的东西(XmCreate {Error | Warning | InfoDialog),但这些需要一个我没有的父窗口小部件(例如顶层窗口),不接受这些的NULL参数
所以我现在很难过。有一种简单的方法可以做我想要的吗?或者至少有一半的简单/简单/直接的?如果是,那么哪一个(尽可能多地提供详细信息)将非常感激。
答案 0 :(得分:6)
在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)
答案 1 :(得分:3)
我个人使用Qt4的QMessageBox。
示例:
QMessageBox mb(QMessageBox::Question, "Title", "Message", QMessageBox::Ok | QMessageBox::Cancel);
if(mb.exec() == QMessageBox::Ok) { do_stuff(); }
答案 2 :(得分:2)
看起来你必须创建一个顶级的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复制的,这可能会为您提供更多指示。
答案 3 :(得分:2)
这是我的解决方案。我选择使用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;
帮助函数确定行和最大值。短信的cols:
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);
}
答案 4 :(得分:1)
我建议您查看一个支持SDL作为后端的GUI库。一个这样的库是GG,它有类ThreeButtonDlg。当Run()返回时,您可以查看其Result()。请参阅minimal示例中的Initial方法。