Enable an Button in MFC Dialog - mfc

I have two buttons:
Radio button: "Hex"
Button: "A"
I want to enable "A" anytime users "Hex" button is checked (the state of "A" is "Disabled" when it is created), how can I do that? Thank everyone.

You need to use CButton's EnableWindow function.
buttonA.EnableWindow( TRUE );
If you do not have the CButton object, you can access the button by calling GetDlgItem with its ID:
GetDlgItem( IDC_BUTTON_A )->EnableWindow( TRUE );

You should use ON_UPDATE_COMMAND_UI mechanism to enable/disable the 'A' or any other button in your dialog. By default it is not available for dialog based application but you can easily enable them by following this article.
The code in your update function will look something like this:
void CCalculatorDlg::OnUpdateButtonA(CCmdUI* pCmdUI)
{
if( m_ctrlBtnHex.GetCheck() == BST_CHECKED )
{
pCmdUI->Enable( TRUE );
}
else
{
pCmdUI->Enable( FALSE );
}
}
In your case since A, B, C, D, E, F will essentially have same states so you can instead do this:
void CCalculatorDlg::OnUpdateButtonA(CCmdUI* pCmdUI)
{
if( m_ctrlBtnHex.GetCheck() == BST_CHECKED) )
{
m_ctrlBtnA.EnableWindow( TRUE );
m_ctrlBtnB.EnableWindow( TRUE );
m_ctrlBtnC.EnableWindow( TRUE );
// so on...
}
else
{
m_ctrlBtnA.EnableWindow( FALSE );
m_ctrlBtnB.EnableWindow( FALSE );
m_ctrlBtnC.EnableWindow( FALSE );
// so on...
}
}

NameOfYourButton.EnableWindow( TRUE );

Related

Ctrl+Left mouse click event capture Qt

How can one get Ctrl+Left mouse click event in Qt widget. I am able to get key event from QObject::keyPressEvent() and mouse click from QObject::mousePressEvent(). But I need to capture both in the same function. Can someone give some pointer to right direction. Thanks.
You can try to use an additional variable, like:
private:
bool ctrlIsPressed = false;
protected:
void keyPressEvent(QKeyEvent *event)
{
if( event->key() == Qt::Key_Control )
ctrlIsPressed = true;
}
void keyReleaseEvent(QKeyEvent *event)
{
if( event->key() == Qt::Key_Control )
ctrlIsPressed = false;
}
void mousePressEvent()
{
if( ctrlIsPressed )
// ... Your code
}
You can call QMouseEvent::modifiers() to check whether it returns the value Qt::ControlModifier.
Check out this Stackoverflow.com question. I think it is exactly the issue you are having.
How to detect the modifier key on mouse click in Qt

How to know the QTreeView item decoration is clicked

I'm trying to know when the user selects the decoration of an item, because I was trying to implement a single click expand/collapse QTreeview and the decoration now does nothing. It doesn't expand or collapse the item where as if I click on the item it works properly.
void MyTreeView::mousePressEvent(QMouseEvent *event)
{
QTreeView::mousePressEvent(event);
if (event->button() == Qt::LeftButton)
{
QModelIndex index = indexAt(event->pos());
isExpanded(index) ? collapse(index) : expand(index);
}
}
The problem is that when the decoration is selected, it enters the if condition. If it was not, everything works fine.
I don't know if I have to block the decoration action or have a condition in the if statement.
How do I know the decoration is selected and not the item itself or how do I block decoration action ?
Try this:
void MyTreeView::mousePressEvent( QMouseEvent* aEvent )
{
QModelIndex index = indexAt( aEvent->pos() );
if ( index.isValid() )
{
const bool wasExpanded = isExpanded( index );
QTreeView::mousePressEvent( aEvent );
if ( aEvent->button() == Qt::LeftButton )
{
const bool expanded = isExpanded( index );
// QTreeView did not change the item's state ... but you want.
if ( wasExpanded == expanded )
{
expanded ? collapse( index ) : expand( index );
}
}
}
else
{
QTreeView::mousePressEvent( aEvent );
}
}

QGraphicsItem and tab order

For some GUI application I use QMainWindow with different controls on it: QGraphicsScene + QGraphicsView , QPushButtons, QWidget.
Inside QGraphicsScene located a lot of different items type:
QGraphicsPolygonItem
QGraphicsTextItem
QGraphicsRectItem
But for me is most important is Polygon item, this item has those flags:
setFlag(QGraphicsItem::ItemIsFocusable, true);
setFlag(QGraphicsItem::ItemIsMovable, true);
setFlag(QGraphicsItem::ItemIsSelectable, true);
I can select every item by mouse, but I need to change focus for those items by Tab.
How is it possible ?
SetTabOrder worked only with QGraphicsObjects.
I tried to solve this problem with QGraphicsView::focusNextPrevChild redefining
bool MyGraphicsView::focusNextPrevChild( bool next )
{
QGraphicsPolygonItem *target;
QGraphicsPolygonItem *current;
if( scene()->focusItem() )
{
target = qgraphicsitem_cast<QGraphicsPolygonItem*>( scene()->focusItem() );
bool is_focus_next=false;
foreach( QGraphicsItem *item, scene()->items() )
{
current = qgraphicsitem_cast<QGraphicsPolygonItem*>( item );
// set focus for next before selected
if( current && is_focus_next )
{
item->setFocus( Qt::MouseFocusReason );
// item->setSelected( true );
is_focus_next = false;
break;
}
// searching for selected item
if( current && current == target )
{
is_focus_next = true;
}
}
}
}
But only first Tab worked, When I pressed Tab again focus has moved to other QWidget outside the QGraphicsView control.
Please, could you help me with Tab order focus for QGraphicsItem.
Thank you
EDIT: The final version, thanks to Steffen.
bool MyGraphicsView::focusNextPrevChild( bool next )
{
QGraphicsPolygonItem *target;
QGraphicsPolygonItem *current;
if( scene()->focusItem() )
{
target = qgraphicsitem_cast<QGraphicsPolygonItem*>( scene()->focusItem() );
bool is_focus_next=false;
foreach( QGraphicsItem *item, scene()->items() )
{
current = qgraphicsitem_cast<QGraphicsPolygonItem*>( item );
// set focus for next before selected
if( current && is_focus_next )
{
item->setFocus( Qt::MouseFocusReason );
return true;
}
// searching for selected item
if( current && current == target )
{
is_focus_next = true;
}
}
}
return QGraphicsView::focusNextPrevChild(next);
}
You should return true to indicate that you actually found a widget. As you have no return statement at all at the moment, the behaviour is undefined. You can also add some logic to return false on the last element to allow the user to leave your QGraphicsView again.
See also the documentation for QWidget::focusNextPrevChild().

Owner-drawn button with BS_AUTORADIOBUTTON style

How do I get the checked/unchecked state of BS_AUTORADIOBUTTON? My code currently doesn't work.
void CPngButton::DrawItem( LPDRAWITEMSTRUCT lpDIS )
{
ASSERT(lpDIS != NULL);
UINT state = lpDIS->itemState;
if (state & ODS_CHECKED)
{
// do stuff
}
}
I've also tried
if (BST_CHECKED == SendMessage(BM_GETCHECK))
but this doesn't work either.
ODS_CHECKED only applies to menus. BM_GETCHECK and BM_GETSTATE can both provide the checked state:
if (Button_GetState(lpDIS->hwndItem) & BST_CHECKED)
According to the documentation, the ODS_CHECKED flag is only applicable to menu items:
ODS_CHECKED This bit is set if the menu item is to be checked. This bit is used only in a menu.
Instead, to determine the checked state of a button, you should call the CButton::GetCheck function. It will return one of the following values:
BST_UNCHECKED The button is unchecked
BST_CHECKED The button is checked
BST_INDETERMINATE Button state is indeterminate
(only if BS_3STATE or BS_AUTO3STATE set).
For example:
CButton myBtn;
if (myBtn.GetCheck() = BST_CHECKED)
{
// Drawing code here...
}

How do I properly implement a "minimize to tray" function in Qt?

How do I properly implement a "minimize to tray" function in Qt?
I tried the following code inside QMainWindow::changeEvent(QEvent *e), but the window simply minimizes to the taskbar and the client area appears blank white when restored.
if (Preferences::instance().minimizeToTray())
{
e->ignore();
this->setVisible(false);
}
Attempting to ignore the event doesn't seem to do anything, either.
Apparently a small delay is needed to process other events (perhaps someone will post the exact details?). Here's what I ended up doing, which works perfectly:
void MainWindow::changeEvent(QEvent* e)
{
switch (e->type())
{
case QEvent::LanguageChange:
this->ui->retranslateUi(this);
break;
case QEvent::WindowStateChange:
{
if (this->windowState() & Qt::WindowMinimized)
{
if (Preferences::instance().minimizeToTray())
{
QTimer::singleShot(250, this, SLOT(hide()));
}
}
break;
}
default:
break;
}
QMainWindow::changeEvent(e);
}
In addition to what Jake Petroules said, it appears that simply doing:
QTimer::singleShot(0, this, SLOT(hide()));
is enough. From http://qt-project.org/doc/qt-4.8/qtimer.html#details :
As a special case, a QTimer with a timeout of 0 will time out as soon as all the events in the window system's event queue have been processed.
This way you don't have the problem of selecting an appropriate delay value...
void main_window::create_tray_icon()
{
m_tray_icon = new QSystemTrayIcon(QIcon(":/icon.png"), this);
connect( m_tray_icon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(on_show_hide(QSystemTrayIcon::ActivationReason)) );
QAction *quit_action = new QAction( "Exit", m_tray_icon );
connect( quit_action, SIGNAL(triggered()), this, SLOT(on_exit()) );
QAction *hide_action = new QAction( "Show/Hide", m_tray_icon );
connect( hide_action, SIGNAL(triggered()), this, SLOT(on_show_hide()) );
QMenu *tray_icon_menu = new QMenu;
tray_icon_menu->addAction( hide_action );
tray_icon_menu->addAction( quit_action );
m_tray_icon->setContextMenu( tray_icon_menu );
m_tray_icon->show();
}
void main_window::on_show_hide( QSystemTrayIcon::ActivationReason reason )
{
if( reason )
{
if( reason != QSystemTrayIcon::DoubleClick )
return;
}
if( isVisible() )
{
hide();
}
else
{
show();
raise();
setFocus();
}
}
That's how I realize a "minimize to tray". You can now minimize either by double clicking on the icon, or by right-clicking and selecting "Show/Hide" in the menu.
I have found that the showMinimized() slot works without a QTimer delay, so you can use code like:
mw->show();
if ( qApp->arguments().contains( "--startHidden" ) )
mw->showMinimized();
in your main() to show a main window and immediately iconize it, when desired.