I use wxWidgets 2.9.5 on a Windows 7 machine.
When I select more then one element in my wxlistctrl using shift, GetNextItem() only returns the index of the first element selected.
Even the example from the manual: http://docs.wxwidgets.org/trunk/classwx_list_ctrl.html#ad8372c4619ad5ea55ad16889caa32e78
which I attached doesn't work; Hence it returns the index of the first element selected when the GetNextItem() is called at first, but when it is called the second time it returns -1.
long item = -1;
for ( ;; )
{
item = listctrl->GetNextItem(item,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
if ( item == -1 )
break;
// this item is selected - do whatever is needed with it
wxLogMessage("Item %ld is selected.", item);
}
Does anyone has had to workaround the same problem?
Thank you.
Almost exactly the same code (see MyFrame::OnShowSelInfo()) does work in the listctrl sample included in wxWidgets, so I really don't know why it doesn't work for you. Can you try to reproduce the problem in the sample?
Related
I am testing some Qt code using a QComboBox.
When the QComboBox is clicked and expands, it expands out from the currently selected items position from within the list. This behaviour does not seem correct, though I have done nothing that would change the default behaviour.
So if I expand the box for the first time, is expands downwards since the first item in the box is selected. If I then select the middle item and close and open it again, when it opens it expands half upwards and half downwards. This is because the middle item is selected. If I select the bottom item, and then close and expand again, it will expand completely upwards since the selected item is in the bottom of the list of items.
I am running the application on Linux Mint 18.2. Is this just the way that QComboBoxes are designed, or is there a way I can change this behavior.
The only code at all manipulating this box is...
for ( QStringList::const_iterator i = colorNames.constBegin();
i != colorNames.constEnd(); ++i ) {
QPixmap solidPixmap( 20, 10 );
solidPixmap.fill( QColor( *i ) );
QIcon* solidIcon = new QIcon( solidPixmap );
foreColorBox->addItem( *solidIcon, *i );
backColorBox->addItem( *solidIcon, *i );
}
This could probably be a Linux-Mint specific behaviour. On Windows-7, my QCombobox opens the selection drawer down, regardless of the selection.
On macOS High Sierra, the same combobox has a behaviour as in your question.
So, it is evident that QCombobox implementation uses the native behaviour of the platform it runs.
Working on a program where 6 combobox's have relative data, once an index is selected, the others shouldn't be able to select it, hence I'm just removing it from the index on the others, however in practice it is removing the index plus every index before it for some reason. Any idea why?
void AssignStatsWindow::on_comboBox_currentIndexChanged()
{
ui->comboBox_2->removeItem(ui->comboBox->currentIndex()); //these should remove 1 index but removes many
ui->comboBox_3->removeItem(ui->comboBox->currentIndex());
ui->comboBox_4->removeItem(ui->comboBox->currentIndex());
ui->comboBox_5->removeItem(ui->comboBox->currentIndex());
ui->comboBox_6->removeItem(ui->comboBox->currentIndex());
for (int i = ui->comboBox->count(); i >= 0; --i) //removes all but newly selected index, seems to be working fine
{
if (i != ui->comboBox->currentIndex()) {
ui->comboBox->removeItem(i);
}
}
}
comboBox is the one having the indexChanged and triggering the code, comboBox_2 through 6 are the others that need adjust and are 'over-removing' indexes. Once I get this first one working correctly it should be easy to build the rest of the indexChanged for the rest of the comboBoxes. Any help would be greatly appreciated.
From the Qt 5.5 documentation:
Removes the item at the given index from the combobox. This will update the current index if the index is removed.
in practice it is removing the index plus every index before it for some reason. Any idea why?
It seems that the work to remove an item is being performed in a slot that responds to the currentIndexChanged signal. The above documentation states removing an item will change the current index of the combo box which will result in the slot being triggered many times, thereby removing many items.
I am using a selfmade QSortFilterProxyModel to do the filtering and sorting of a model in my application.
Here is the filterAcceptsRow function:
//---------------------------------------------------------------------------------
bool
SkillSortFilterProxyModel::filterAcceptsRow(int p_row, const QModelIndex& p_parent) const
{
QModelIndex currentIndex = sourceModel()->index(p_row, 0, p_parent);
SkillModelItem* currentItem = (SkillModelItem*)currentIndex.internalPointer();
// Check the item
bool accept = filterAcceptsItem(currentItem);
// We may hide a category if it is empty
if (accept && currentItem->isCategory && !_showEmptyCategories)
{
// Iterate over the children to find out if any will be accepted
// And if so, accept the category
int numChildren = currentItem->children.size();
accept = false;
for (int i = 0; i < numChildren; ++i)
{
SkillModelItem* item = currentItem->children[i];
if (filterAcceptsItem(item))
{
accept = true;
break;
}
}
}
// Return result
return accept;
}
Here is what it is supposed to do: I think the exact nature of the SkillModelItem is not important here, but you should understand that the same model item class is used for skill categories and skills themselves. The filterAcceptsRow function calls filterAcceptsItem to see if the particular item should be shown or not. That works well.
However, if the item is a category, its children should also be checked to see if it has any accepted children, and if so, the category should be shown.
Should work in theory, but what happens in practice is that after currentItem->children.size() is called, the currentItem->children (which is a std::vector) becomes invalid! It returns the correct size, but if I call it again, the size is now some random number. And accessing the child items in the for loop after crashes the application.
I have no idea what is going on here. The application is not threaded (at least I do not use any threads). I am using Qt Creator on Windows, using MinGW as the compiler. I also tried using MSVC but that will not even compile as it claims it cannot find any header files (which MinGW can find without problems). Also tried recompiling, re-running qmake, etc. All to no avail.
Any ideas what could be the problem here?
If it helps, you can look at the sources here: GitHub repo
Turns out this is a debugger problem.
If I do not step through at runtime, the function works just fine.
Seems like there is a bug in either Qt Creator or the MinGW version coming with it.
Ive made a search function for my List Control in Report View in my MFC Dialog. It looks like this
m_List.SetItemState((m_List.FindItem(&Finde)),LVIS_SELECTED,LVIS_SELECTED );
It searches the Content that is in the Variable Finde and marks it. Now it should mark the row. But I first have to click somewhere in the program. It doesnt mark the row directly after the function gets called.
Can anyone help me?
Here is the full function
LVFINDINFO Finde;
Finde.flags = LVFI_PARTIAL|LVFI_STRING;
Finde.psz = _T("Siffert");
if ((m_List.FindItem(&Finde)) != -1)
{
m_List.SetItemState((m_List.FindItem(&Finde)),LVIS_SELECTED,LVIS_SELECTED );
//m_List.SetSelectionMark((m_List.FindItem(&Finde)));
}
else
{
MessageBox(_T("No Results"));
}
You need to use the style LVS_SHOWSELALWAYS
Otheriwse the selection is only shown when the control has the focus and is active.
EDIT: Also keep in mind that there is also a LVIS_FOCUSED style, that also forces scrolling to this item.
I need to update a combobox with a new value so it changes the reflected text in it. The cleanest way to do this is after the comboboxhas been initialised and with a message.
So I am trying to craft a postmessage to the hwnd that contains the combobox.
So if I want to send a message to it, changing the currently selected item to the nth item, what would the postmessage look like?
I am guessing that it would involve ON_CBN_SELCHANGE, but I can't get it to work right.
You want ComboBox_SetCurSel:
ComboBox_SetCurSel(hWndCombo, n);
or if it's an MFC CComboBox control you can probably do:
m_combo.SetCurSel(2);
I would imagine if you're doing it manually you would also want SendMessage rather than PostMessage. CBN_SELCHANGE is the notification that the control sends back to you when the selection is changed.
Finally, you might want to add the c++ tag to this question.
A concise version:
const int index = 0;
m_comboBox.PostMessage(CBN_SELCHANGE, index);
What might be going wrong is the selection is being changed inside the selection change message handler, which result in another selection change message.
One way to get around this unwanted feedback loop is to add a sentinel to the select change message handler as shown below:
void onSelectChangeHandler(HWND hwnd)
{
static bool fInsideSelectChange = 0;
//-- ignore the change message if this function generated it
if (fInsideSelectChange == 0)
{
//-- turn on the sentinel
fInsideSelectChange = 1;
//-- make the selection changes as required
.....
//-- we are done so turn off the sentinel
fInsideSelectChange = 0;
}
}
if you fx want to change the title - which is the line shown when combobox is closed, then you can do following:
m_ComboBox.DeleteString(0); // first delete previous if any, 0 = visual string
m_ComboBox.AddString(_T("Hello there"));
put this in fx. in OnCloseupCombo - when event close a dropdownbox fires
ON_CBN_CLOSEUP(IDC_COMBO1, OnCloseupCombo)
This change is a new string not a selection of already assigned combobox elements