QMessageBox addButton() using standard icon/display - c++

I'm trying to make our popup messages boxes have more appropriate text, rather than the generic "Ok", "Cancel", etc. However, I don't see an easy way to get the standard icons on the buttons.
For example, normally the QMessageBox::Save button has an icon with it. Instead I want the text to be "Save Part", but since this is still essentially a save operation it'd be nice to have the same icon.
I'd be happy to have this tied to the Role, as all my custom test buttons map to one of the standard roles. Is there any easy way to get the standard icons onto the custom buttons?

If you just want to change the text on the StandardButton but keep the standard icon you can do the following:
QMessageBox *box = new QMessageBox("title", "text", QMessageBox::NoIcon, QMessageBox::Save, QMessageBox::Close, QMessageBox::Open);
box->button(QMessageBox::Save)->setText("Save part");
box->show();
This will result in following:
And the button will keep the same role

Add a button with QMessageBox::addButton to QMessageBox, then call the Button's setIcon with the icon returned by the QStyle::standardIcon you want.

Related

Embedding dialogs in main dialog and switching them with button click in MFC

I have a design like below:
So basically, I want to embed three dialogs in the application main dialog and switch between them, for each button click i.e., button 1 will show dialog one , button 2 will hide dialog 1 and show dialog 2 .. and so on.
Each dialog will be having a different design and functions.
I tried using CPropertySheet class to Add pages but its GUI is different. It has either option for navigating the dialogs using next / back button , or from a tab control.
None of which is as per my requirement.
So I want to know is it possible to have a design like this in MFC ? If yes how? Which Class/ control should I use.
Any help will be appreciated.
What you can do is use a normal CDialog class, add your buttons to it and also create a frame/rect as a placeholder for where your embedded dialogs are to appear. The following piece of code will create and position your embedded dialog.
CRect rect;
CWnd *pHost = GetDlgItem(ID_OF_YOUR_FRAME_RECT);
pHost->GetWindowRect(&rect);
ScreenToClient(&rect);
pDialog->Create(ID_OF_YOUR_DIALOG, this);
pDialog->MoveWindow(&rect);
pDialog->ShowWindow(SW_SHOW);
On button clicks, you hide the previously shown dialog (SW_HIDE) and show your selected dialog(SW_SHOW) with ShowWindow(...).
If you create your embedded dialogs with IDD_FORMVIEW style in the add resource editor it'll have the proper styles for embedding.
Another option is probably to use an embedded PropertySheet and hide the tab row and programatically change the tabs on the button clicks. I just find it to be too much fuzz with borders, positioning, validation and such for my liking.
If you have the MFC Feature Pack, that first came with VS2008 SP1 and is in all later versions, you might like to consider CMFCPropertySheet. There are a number of examples on the linked page, that are very similar to your design.
For example, this:
What worked for me just using dialog based application is SetParent() method. Dont know why nobody mentioned it. It seems to work fine.
I am doing like below:
VERIFY(pDlg1.Create(PanelDlg::IDD, this));
VERIFY(pDlg2.Create(PanelDlg2::IDD, this));
VERIFY(pDlg3.Create(PanelDlg2::IDD, this));
::SetParent(pDlg1.GetSafeHwnd(), this->m_hWnd);
::SetParent(pDlg2.GetSafeHwnd(), this->m_hWnd);
::SetParent(pDlg3.GetSafeHwnd(), this->m_hWnd);
Now I can show or hide a child dialog at will (button clicks) as below:
pDlg1.ShowWindow(SW_SHOW);
pDlg2.ShowWindow(SW_HIDE);
pDlg3.ShowWindow(SW_HIDE);

How to prevent closing QMessageBox after clicking a button

I have 3 buttons on QMessageBox added by QMessageBox::addButton() method. Is it possible to prevent closing the message box if a button has been clicked? By default every button closes the window, but I don't want to do it for one button.
One interesting way to approach it that worked for me is to completely disconnect the signals for the target button created, and then re-add the intended functionality. This won't work for everyone, especially if the button isn't created this way and/or you still want to close the dialog correctly. (There might be a way to add it back and/or simulate the behavior with QDialog::accept, QDialog::reject, QDialog::done - haven't tried yet.)
Example:
QMessageBox *msgBox = new QMessageBox(this);
QAbstractButton *doNotCloseButton = msgBox->addButton(tr("This button will not close anything"), QMessageBox::ActionRole);
// Disconnect all events - this will prevent the button from closing the dialog
doNotCloseButton->disconnect();
connect(doNotCloseButton, &QAbstractButton::clicked, this, [=](){ doNotCloseButton->setText("See? Still open!"); });
If you can get a pointer to the QMessageBox widget, you can try to install a QObject::eventFilter on it which filters the QEvent::Close.
Just had the same problem but I wanted to add a checkbox and it kept closing the dialog on clicked even with the ButtonRole set to QMessageBox::ActionRole (tried others too). For this scenario I just called blockSignals(true) on the QCheckBox and now it allows check/uncheck behaviour without closing the dialog. Luckily QCheckBox works fine without signals but assume you want a signal from your button.
They should likely add a new role that doesn't close the dialog as it's a pain to derive a class for simple customizations.
I looked through the addButton() functions overloads, but there is no custom behavior for the buttons you add with this method. They will behave like the standard buttons on a messagebox should.
However if you want to create a fully customizable dialog, then your best option is to extend the QDialog class and use whatever controlls you like on it.
Thanks to #Albert's Answer, I found that this also possible in python:
messagebox = QMessageBox()
button = QPushButton("This button will not close anything")
messagebox.addButton(button, QMessageBox.ButtonRole.NoRole)
button.disconnect()

c++ win32 create a text only button

I would like to add a simple text button to my c++ win32 application. I'm creating the button using CreateWindowEx function, but can't figure out the correct style to do so. I would like to display a text only button and be able to recive messages when the user clicks on it. The style i would like to get is identical to the text button in windows 7 system volume control (where it says "Mixer"). If possible i would like to display a tooltip also.
That mixer control looks more like a hyperlink control than a button. I'd go for the SysLink control if that's what you need.
You could create a "Button" class window with the BS_OWNERDRAW style and handle the WM_DRAWITEM messages. In your WM_DRAWITEM message handler you can simply display the text.
Actually that button is an owner draw button - it listens to mouse move messages and when you hover over it, it underlines the text (the syslink control doesn't have this behavior). Otherwise it's a stock button.

How do I change properties of buttons within button boxes in Qt Designer?

I have been searching online to no avail. Does anyone know how to access a button in a button box (created using the "Dialog with Buttons Right" template)?
In Designer, select the OK or Cancel button. Then open the property editor and scroll down to the QDialogButtonBox section. You can then expand the standardButtons item to see the various buttons that are available. Other properties, such as the centerButtons property, are also available.
However, designer gives you very little control over the button box.
In code, you can do many other things, such as change the text that appears on the "standard buttons." From the documentation:
findButton = new QPushButton(tr("&Find"));
findButton->setDefault(true);
moreButton = new QPushButton(tr("&More"));
moreButton->setCheckable(true);
moreButton->setAutoDefault(false);
buttonBox = new QDialogButtonBox(Qt::Vertical);
buttonBox->addButton(findButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(moreButton, QDialogButtonBox::ActionRole);
As long as you give the button box a name in designer, you can set these properties in code.
I am writing this answer for the Python community. I am using PySide and faced a similar problem. I have a QDialogButtonBox and I would like to have my own buttons instead of the default ones.
I am using PySide which is more or less the exact replica of the c++ code, so I believe other c++ developers can also get something from it.
Here how I would do that:
my_ok_button = QtGui.QPushButton("My Ok Button")
my_cancel_button = QtGui.QPushButton("My Cancel Button")
ok_cancel_button = QtGui.QDialogButtonBox(QtCore.Qt.Horizontal)
ok_cancel_button.addButton(my_ok_button, QtGui.QDialogButtonBox.ButtonRole.AcceptRole)
ok_cancel_button.addButton(my_cancel_button, QtGui.QDialogButtonBox.ButtonRole.RejectRole)
I would then insert my button box to my layout like ususal:
layout.addWidget(ok_cancel_button, 1, 1)
Now later in my code I can do anything with my button. Lets change its name:
my_ok_button.setText("Some Other Name")
So then things to note here is that:
you must set the role of the buttons in the addButton() method if you
want to use functionalities given by standard buttons. E.g. if you
wish to do something like below, you need to have the button roles
set.
ok_cancel_button.accepted.connect(self.ok_method_handler)
ok_cancel_button.rejected.connect(self.close)
More information can be found here.

Making a groupbox button win32 C++

i have a button that is a rectangle how would i put words in it i want to make so ican click the word and it starts the progrma i know ShellExecute the style is BS_GROUPBOX
If you have more than one program you want to start, you need a button per program you want to start.
To start you external progrma, in the button parent window, you need to process the WM_COMMAND message with the BN_CLICKED notification.
To set the text of the button, you need to send WM_SETTEXT message to the button with the text you want shown.
Btw, BS_GROUPBOX is used for creating the rectangle around radio buttons. This style is not going to work for your scenario.
If you want an alternative to using multiple Button controls, you can use a Toolbar. In fact, it seems to me that a toolbar would be a better control for you. You can read more about creating a toolbar.