wxWidgets: make tooltips less annoying, - c++

I have added tooltips to my checkbox elements, but they are too annoying. They appear immediately after hovering the mouse cursor over the element and do not disappear after the cursor has left the checkbox.
I could start a timer, but I don't know how I can check if the cursor is within the desired element or has left it.
And the second question is, is there any event like wxEVT_LEAVE_WINDOW, but for the checkbox to remove the tooltip when the cursor goes out of bounds.

Thanks, #New Pagodi
I am still dont get normal behaivor of tips, but your trich works. I can get tip window from wxCheckBox element just calling GetChildren().
wxRichToolTip* tip = new wxRichToolTip(wxT("INFO"), msg);
tip->SetTimeout(0, 500);
tip->ShowFor(it->second.first);
wxWindowList tipWindow = it->second.first->GetChildren();
auto a = tipWindow.GetLast()->GetData();
a->Bind(wxEVT_MOTION, &DeviceListDialog::onLeaveCheckbox, this);

Related

How to catch KeyEvents when wxGrid Editor is Shown

When typing in a cell in wxGrid, the arrow keys function to go back and forward between the characters. However, depending on caret position I would like to move the cursor to the next cell when an arrow key is pressed. Currently, wxGrid is configured to capture Enter key, which makes the cursor to move downwards (to the cell below).
My question is how can I capture KeyEvent when editor is still shown.
My approach:
void Grid::OnGridCmdEditorShown( wxGridEvent& event )
{
m_IsEditorShown=true;
//Connect(wxEVT_KEY_DOWN,wxKeyEventHandler(Grid::OnKeyDown),NULL, this); //This approach did not help either
event.Skip();
}
void Grid::OnKeyDown(wxKeyEvent& event)
{
if(m_IsEditorShown) wxMessageBox("You are keying");
event.Skip();
}
When the editor is shown and say I type abc to the current cell, the MessageBox only appears when I press enter. How can catch the KeyEvents when the editor is still shown, for example, the user types a to the current cell and the MessageBox is shown.
You need to use a custom editor (probably just deriving from the standard wxGridCellTextEditor) and bind to the wxEVT_CHAR event of the editing control created in its Create().
Notice that if you want to handle the initial key press, which results in showing the editor in the first place, you need to override wxGridCellEditor::StartingKey() instead, as this key press happens before the editing control is shown.
One way that worked for me was to connect a handler to each grid editor after it had been created, by adding this to Grid constructor:
Bind(wxEVT_GRID_EDITOR_CREATED, [=](wxGridEditorCreatedEvent& event) {
event.GetControl()->Bind(wxEVT_KEY_DOWN, &Grid::OnKeyDown, this);
});
This will not handle the initial key press which results in showing the editor in the first place, but from what I understand that would not be necessary here.

Selecting items in a QTreeView with keyboard arrows

I'm trying to select an item in my QTreeView with the arrow keys but cannot find a method belonging to this class that returns the index of the highlighted item.
Up to now, i have only been able to select item with a click of the mouse :
connect(m_QTreeView, SIGNAL(clicked(QModelIndex)), this, SLOT(ItemTreeClicked(QModelIndex)));
but if I try to then change the focus with the keyboard arrows the current index is not updated.
To be honest, even my "mouse click" version isn't perfect because i have had use a Boolean that is initialized to false and passes to true when I enter the slot ItemTreeClicked. I had to do this because when i try to delete an item from the list, if I haven't clicked anything yet my app crashes.
I am coding in c++ on QtCreator 4.7.4
Any help or example code would be greatly appreciated.
Cheers.
Maybe you could subclass QTreeView and override the keyPressEvent method so it changes the current index?
myqtreeview::keyPressEvent(QKeyEvent* event){
QModelIndex qmi = this->currentIndex();
if(event->key() == Qt::Key_Down){
this->setCurrentIndex(QAbstractItemModel::createIndex(qmi->row()+1, qmi->column()));
}else{
...
}
QTreeView::keyPressEvent(event);
}
Note: This is just an idea, I can't test it at the moment so you probably have to adjust this a bit if you want to try it out

mfc buttons will display incompletely if adding two buttons at runtime

CButton *btn = new CButton();
btn->Create("btn", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, CRect(0,0,50,50), this, 1234);
btn = new CButton();
btn->Create("btn", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, CRect(40,30,50,50), this, 1234);
running above code in CDialog::OnInitDialog() will only display first button correctly, the second button will be displayed incompletely.
Any suggestion is appreciated.
The CRect constructor you're using is not doing what you think it's doing. The 4 parameter override takes left, right, top, bottom as parameters. You are simply making the rectangle too small - there's nothing incomplete about it.
As an aside you're giving both controls the same control ID of 1234 - that's potentially dangerous - you should rather give them unique values.

CEdit control MFC, placing cursor to end of string after SetWindowText

I am using VC9, I've a CEdit control whose contents are reset to default test (say - "fill-in") at the click of a button and then I call SetFocus for the CEdit control. The problem is that the cursor blinks at the start of the default text, and i want it to blink an the end of the default string.
How can this be done?
You can use CEdit::SetSel to accomplish that.
Example:
CEdit* e = (CEdit*)GetDlgItem(IDC_EDIT1);
e->SetWindowText("hello world");
e->SetFocus();
e->SetSel(0,-1); // select all text and move cursor at the end
e->SetSel(-1); // remove selection
You can use CEdit::SetSel to accomplish that:
CEdit* e = (CEdit*)GetDlgItem(IDC_EDIT1);
e->SetWindowText("hello world");
// e->SetSel(0,-1); // you don't need this line
e->SetFocus();
e->SetSel(-1);
It will place the cursor in the end of the string.
I had a strange finding but still relevant to it.
This solution did not work for me initially. Even after calling SetSel(-1) my cursor was moving to the top of the edit box.
Then I did some code reshuffle and it started working.
The learning was that if I update any other control after updating the edit control, the cursor will move to the top of the edit box. But if edit box is the last control updated, the cursor remains in the end of the edit box.
Like I had a code something like
Add text to edit & call SetSel(-1)
update static control
And the cursor would not stay in the end. But when I changed it to
update static control
Add text to edit & call SetSel(-1)
My cursor was displayed in the end of the edit box.
I had it on my mind since the day I had this finding to update the knowledge base here. Hope it helps some random soul whose cursor jumps to top of edit box even after calling the API.

How do I display a tooltip for a CMFCRibbonButton in the status bar?

I have a CMFCRibbonStatusBar in my mainframe to which I add a CMFCRibbonButtonsGroup which again has a CMFCRibbonButton. This button has the same ID as a menu entry.
Creating the button is done as follows:
CMFCRibbonButtonsGroup* pBGroup = new CMFCRibbonButtonsGroup();
CMFCToolBarImages images;
images.SetImageSize(CSize(32, 16)); // Non-square bitmaps
if(images.Load(IDB_STATUSBAR_IMAGES))
{
pBGroup->SetImages(&images, NULL, NULL);
}
m_pStatusButton = new CMFCRibbonButton(ID_STATUS_SHOWSTATUS,
_T(""),
IMAGEINDEX_DEFAULTSTATUS);
pBGroup->AddButton(m_pStatusButton);
m_wndStatusBar.AddExtendedElement(pBGroup, _T(""));
I want to use this button as a status indicator.
I want to display a tool tip in the following two cases:
when the status changes and
when the user moves the mouse over the button.
I have no idea how to start in the first place. I have looked at the ToolTipDemo and DlgToolTips sample projects but couldn't figure out how to do it since all they do is display tooltips for the toolbar items or dialog buttons (CWnd-derived instead of CMFCRibbonButton).
If you are familiar with the ToolTipDemo sample project: Since there seem to be several ways of doing things, I would prefer the tooltip to look like the "Extended Visual Manager-based" tool tip as shown in this screenshot.
Thanks!
I don't think it's possible to show the tooltip without the mouse cursor being over the control. That's all done automatically.
However if you want to have a nice looking tooltip like in your screenshot, you need to call SetToolTipText and SetDescription, like this:
CMFCRibbonButton* pBtn = new CMFCRibbonButton(12345, _T(""), 1);
pBtn->SetToolTipText("This is the bold Title");
pBtn->SetDescription("This is the not-so-bold Description");
pGroup->AddButton(pBtn);
I am using CMFCRibbonButton controls within a CMFCRibbonButtonGroup, which is added to the CMFCRibbonStatusBar. Take note of the 4th parameter in the CMFCRibbonButton() constructor, bAlwaysShowDescription, as this seems to affect the behavior depending upon whether SetDescription() has been called.
Specifically, if SetDescription() has not been called, it doesn't matter whether bAlwaysShowDescription is TRUE or FALSE - the tool tip is displayed (as I would expect). If SetDescription() is set and bAlwaysShowDescription is FALSE, when hovering over the button the tool tip is displayed with the description below it.
What seems counterintuitive given the name of this bAlwaysShowDescription parameter, is that when this is TRUE and SetDescription() is set, NEITHER the tool tip nor the description appear. I wonder if this is related to this post:
https://connect.microsoft.com/VisualStudio/feedback/details/399646/cmfcribbonbutton-wont-show-tooltip-if-balwaysshowdescription-1
Hope this helps and you can achieve what you need with the different combinations of bAlwaysShowDescription parameter and whether SetDescription() is set.