Qt Crash when listWidget item is clicked twice - c++

In my project, I have a listWidget. When the user clicks an item in the list, it loads this:
void BlockSelect::on_blockList_clicked(const QModelIndex &index)
{
QString blockListName;
QString temp_hex;
QString temp_hex2;
int temp_int;
QListWidgetItem *newitem = ui->blockList->currentItem();
blockListName = newitem->text();
temp_hex = blockListName.mid(0, blockListName.indexOf(" "));
if(temp_hex.indexOf(":") == -1)
{
temp_int = temp_hex.toInt();
ui->blockIdIn->setValue(temp_int);
ui->damageIdIn = 0;
}
else
{
temp_hex2 = temp_hex.mid(temp_hex.indexOf(":")+1, temp_hex.length()-(temp_hex.indexOf(":")+1));
temp_hex = temp_hex.mid(0, temp_hex.indexOf(":"));
temp_int = temp_hex.toInt();
ui->blockIdIn->setValue(temp_int);
temp_int = temp_hex2.toInt();
ui->damageIdIn->setValue(temp_int);
}
}
Most of this is just string manipulation. (You don't have need to study this syntax or anything)
My problem is, when the user clicks on another list item quickly (Before this current process is finished) the program crashes. Is there any way to allow fast clicks (multiple processes at once) or maybe an alternative solution?
Thanks for your time :)

I hope that you execute all this code in the GUI thread. If so, then there will be no problem - if your code were correct (it isn't). There is no such thing as the "process" that you mention in your question. The clicks are handled by a slot, and they are invoked from an event handler within the list. This is not supposed to crash, and the clicks will be handled in a serialized fashion - one after another.
Here's the bug: Why do you reset the value of an allocated UI pointer element to zero?
ui->damageIdIn = 0;
This is nonsense. Maybe you mean to ui->damageIdIn->setValue(0) or ui->damageIdIn->hide(). You then proceed to use this zero value in
ui->damageIdIn->setValue(temp_int);
and it crashes.
You may also have bugs in other places in your code.

Related

QListView with millions of items slow with keyboard

I'm using a QListView with a custom model derived from QAbstractItemModel. I have on the order of millions of items. I have called listView->setUniformItemSizes(true) to prevent a bunch of layout logic from being called when I'm adding items to the model. So far, everything works as expected.
The problem is that using the keyboard to navigate the list is slow. If I select an item in the list, then press up/down, the selection moves fast until the selection needs to scroll the list. Then it becomes extremely laggy. Pressing page-up or page-down is also very laggy. The problem seems to be when an item is selected (aka the "current item") with the keyboard and the list is also scrolled up/down.
If I use the mouse, navigating the list is fast. I can use the mouse wheel, which is fast. I can drag the scroll bar up/down as fast as I want--from the top of the list to the bottom--and the list view updates wickedly fast.
Any ideas on why the combination of changing selections and scrolling the list is so slow? Is there a viable work-around?
Update 9/9/15
In order to better illustrate the issue, I'm providing amplifying information in this update.
Performance Issues with KEYBOARD + SCROLLING
This is mostly a performance question, although it does tie in with the user experience (UX) somewhat. Check out what happens as I use the keyboard to scroll through a QListView:
Notice the slow-down near the bottom? This is the focal point of my question. Let me explain how I am navigating the list.
Explanation:
Starting at the top, the first item in the list is selected.
Pressing and holding the down arrow key, the current item (selection) is changed to the next item.
Changing selection is fast for all of the items that are currently in view.
As soon as the list needs to bring the next item into view, the selection rate slows down significantly.
I expect that the list should be able to scroll as fast as the typematic rate of my keyboard--in other words, the time it takes to select the next item should not slow down when the list is scrolled.
Fast Scrolling with MOUSE
Here's what it looks like when I use the mouse:
Explanation:
Using the mouse, I select the scroll bar handle.
Quickly dragging the scroll bar handle up and down, the list is scrolled accordingly.
All movements are extremely fast.
Note that no selections are being made.
This proves two main points:
The model is not the problem. As you can see, the model has no problem whatsoever performance-wise. It can deliver the elements faster than they can be displayed.
Performance is degraded when selecting AND scrolling. The "perfect storm" of selecting and scrolling (as illustrated by using the keyboard to navigate through the list) causes the slowdown. As a result, I surmise that Qt is somehow doing a lot of processing when selections are being made during scrolling that aren't normally performed.
Non-Qt Implementation is FAST
I want to point out that my issue seems to be specific to Qt.
I have already implemented this type of thing before using a different framework. What I am trying to do is within the scope of model-view theory. I can do exactly what I am describing at blazing fast speeds using juce::ListBoxModel with a juce::ListBox. It's stupid fast (plus, there's no need to create a duplicate index such as a QModelIndex for every single item when each item already has a unique index). I get that Qt needs a QModelIndex for each item for its model-view architecture, and although I don't like the overhead cost, I think I get the rational and I can live with it. Either way, I don't suspect that these QModelIndexes are what is causing my performance slow-down.
With a JUCE implementation, I can even use the page-up & page-down keys to navigate the list, and it just blazes through the list. Using the Qt QListView implementation, it chugs along and is laggy, even with a release build.
A model-view implementation using the JUCE framework is extremely fast. Why is the Qt QListView implementation such a dog?!
Motivating Example
Is it hard to imagine why you'd need so many items in a list view? Well, we've all seen this kind of thing before:
This is the Visual Studio Help Viewer index. Now, I haven't counted all of the items--but I think we'd agree that there are a lot of them! Of course to make this list "useful," they added a filter box that narrows down what is in the list view according to an input string. There aren't any tricks here. It's all practical, real-world stuff we've all seen for decades in desktop applications.
But are there millions of items? I'm not sure it matters. Even if there were "only" 150k items (which is roughly accurate based on some crude measurements), it's easy to point out that you have to do something to make it useable--which is what a filter will do for you.
My specific example uses a list of German words as a plain text file with slightly more than 1.7 million entries (including inflected forms). This is probably only a partial (but still significant) sample of words from the German text corpus that was used to assemble this list. For linguistic study, this is a reasonable use case.
Concerns about improving the UX (user experience) or filtering are great design goals, but they are out of the scope of this question (I'll certainly address them later in the project).
Code
Want a code example? You got it! I'm not sure how useful it will be; it's as vanilla as it gets (about 75% boilerplate), but I suppose it will provide some context. I realize that I'm using a QStringList and that there is a QStringListModel for this, but the QStringList that I'm using to hold the data is a placeholder--the model will eventually be somewhat more complicated, so in the end, I need to use a custom model derived from QAbstractItemModel.
//
// wordlistmodel.h ///////////////////////////////////////
//
class WordListModel : public QAbstractItemModel
{
Q_OBJECT
public:
WordListModel(QObject* parent = 0);
virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
virtual QModelIndex parent(const QModelIndex& index) const;
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex & parent = QModelIndex()) const;
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
public slots:
void loadWords();
signals:
void wordAdded();
private:
// TODO: this is a temp backing store for the data
QStringList wordList;
};
//
// wordlistmodel.cpp ///////////////////////////////////////
//
WordListModel::WordListModel(QObject* parent) :
QAbstractItemModel(parent)
{
wordList.reserve(1605572 + 50); // testing purposes only!
}
void WordListModel::loadWords()
{
// load items from file or database
// Due to taking Kuba Ober's advice to call setUniformItemSizes(true),
// loading is fast. I'm not using a background thread to do
// loading because I was trying to visually benchmark loading speed.
// Besides, I am going to use a completely different method using
// an in-memory file or a database, so optimizing this loading by
// putting it in a background thread would obfuscate things.
// Loading isn't a problem or the point of my question; it takes
// less than a second to load all 1.6 million items.
QFile file("german.dic");
if (!file.exists() || !file.open(QIODevice::ReadOnly))
{
QMessageBox::critical(
0,
QString("File error"),
"Unable to open " + file.fileName() + ". Make sure it can be located in " +
QDir::currentPath()
);
}
else
{
QTextStream stream(&file);
int numRowsBefore = wordList.size();
int row = 0;
while (!stream.atEnd())
{
// This works for testing, but it's not optimal.
// My real solution will use a completely different
// backing store (memory mapped file or database),
// so I'm not going to put the gory details here.
wordList.append(stream.readLine());
++row;
if (row % 10000 == 0)
{
// visual benchmark to see how fast items
// can be loaded. Don't do this in real code;
// this is a hack. I know.
emit wordAdded();
QApplication::processEvents();
}
}
if (row > 0)
{
// update final word count
emit wordAdded();
QApplication::processEvents();
// It's dumb that I need to know how many items I
// am adding *before* calling beginInsertRows().
// So my begin/end block is empty because I don't know
// in advance how many items I have, and I don't want
// to pre-process the list just to count the number
// of items. But, this gets the job done.
beginInsertRows(QModelIndex(), numRowsBefore, numRowsBefore + row - 1);
endInsertRows();
}
}
}
QModelIndex WordListModel::index(int row, int column, const QModelIndex& parent) const
{
if (row < 0 || column < 0)
return QModelIndex();
else
return createIndex(row, column);
}
QModelIndex WordListModel::parent(const QModelIndex& index) const
{
return QModelIndex(); // this is used as the parent index
}
int WordListModel::rowCount(const QModelIndex& parent) const
{
return wordList.size();
}
int WordListModel::columnCount(const QModelIndex& parent) const
{
return 1; // it's a list
}
QVariant WordListModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
{
return QVariant();
}
else if (role == Qt::DisplayRole)
{
return wordList.at(index.row());
}
else
{
return QVariant();
}
}
//
// mainwindow.h ///////////////////////////////////////
//
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void updateWordCount();
private:
Ui::MainWindow *ui;
WordListModel* wordListModel;
};
//
// mainwindow.cpp ///////////////////////////////////////
//
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->listView->setModel(wordListModel = new WordListModel(this));
// this saves TONS of time during loading,
// but selecting/scrolling performance wasn't improved
ui->listView->setUniformItemSizes(true);
// these didn't help selecting/scrolling performance...
//ui->listView->setLayoutMode(QListView::Batched);
//ui->listView->setBatchSize(100);
connect(
ui->pushButtonLoadWords,
SIGNAL(clicked(bool)),
wordListModel,
SLOT(loadWords())
);
connect(
wordListModel,
SIGNAL(wordAdded()),
this,
SLOT(updateWordCount())
);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::updateWordCount()
{
QString wordCount;
wordCount.setNum(wordListModel->rowCount());
ui->labelNumWordsLoaded->setText(wordCount);
}
As noted, I've already reviewed and taken Kuba Ober's advice:
QListView takes too long to update when given 100k items
My question is not a duplicate of that question! In the other question, the OP was asking about loading speed, which as I've noted in my code above, is not a problem due to the call to setUniformItemSizes(true).
Summary Questions
Why is navigating a QListView (with millions of items in the model) using the keyboard so slow when the list is scrolled?
Why does the combination of selecting and scrolling items cause a slow-down?
Are there any implementation details that I am missing, or have I reached a performance threshold for QListView?
1. Why is navigating a QListView (with millions of items in the model)
using the keyboard so slow when the list is scrolled?
Because when you navigate through your list using the keyboard, you enter the internal Qt function QListModeViewBase::perItemScrollToValue, see stack:
Qt5Widgetsd.dll!QListModeViewBase::perItemScrollToValue(int index, int scrollValue, int viewportSize, QAbstractItemView::ScrollHint hint, Qt::Orientation orientation, bool wrap, int itemExtent) Ligne 2623 C++
Qt5Widgetsd.dll!QListModeViewBase::verticalScrollToValue(int index, QAbstractItemView::ScrollHint hint, bool above, bool below, const QRect & area, const QRect & rect) Ligne 2205 C++
Qt5Widgetsd.dll!QListViewPrivate::verticalScrollToValue(const QModelIndex & index, const QRect & rect, QAbstractItemView::ScrollHint hint) Ligne 603 C++
Qt5Widgetsd.dll!QListView::scrollTo(const QModelIndex & index, QAbstractItemView::ScrollHint hint) Ligne 575 C++
Qt5Widgetsd.dll!QAbstractItemView::currentChanged(const QModelIndex & current, const QModelIndex & previous) Ligne 3574 C++
Qt5Widgetsd.dll!QListView::currentChanged(const QModelIndex & current, const QModelIndex & previous) Ligne 3234 C++
Qt5Widgetsd.dll!QAbstractItemView::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a) Ligne 414 C++
Qt5Cored.dll!QMetaObject::activate(QObject * sender, int signalOffset, int local_signal_index, void * * argv) Ligne 3732 C++
Qt5Cored.dll!QMetaObject::activate(QObject * sender, const QMetaObject * m, int local_signal_index, void * * argv) Ligne 3596 C++
Qt5Cored.dll!QItemSelectionModel::currentChanged(const QModelIndex & _t1, const QModelIndex & _t2) Ligne 489 C++
Qt5Cored.dll!QItemSelectionModel::setCurrentIndex(const QModelIndex & index, QFlags<enum QItemSelectionModel::SelectionFlag> command) Ligne 1373 C++
And this function does:
itemExtent += spacing();
QVector<int> visibleFlowPositions;
visibleFlowPositions.reserve(flowPositions.count() - 1);
for (int i = 0; i < flowPositions.count() - 1; i++) { // flowPositions count is +1 larger than actual row count
if (!isHidden(i))
visibleFlowPositions.append(flowPositions.at(i));
}
Where flowPositions contains as many items as your QListView, so this basically iterates through all your items, and this will definitely take a while to process.
2. Why does the combination of selecting and scrolling items cause a slow-down?
Because "selecting and scrolling" makes Qt call QListView::scrollTo (to scroll the view to a specific item) and this is what ends up calling QListModeViewBase::perItemScrollToValue. When you scroll using the scroll bar, the system does not need to ask the view to scroll to a specific item.
3. Are there any implementation details that I am missing, or have I reached a performance threshold for QListView?
I'm afraid you are doing the things right. This is definitely a Qt bug. A bug report must be done to hope having this fixed in later releases. I submitted a Qt bug here.
As this code is internal (private data classes) and not conditionnal to any QListView setting, I see no way to fix it except by modifying and recompiling the Qt source code (but I don't know exactly how, this would require more investigation). The first function overidable in the stack is QListView::scrollTo but I doubt it would be easy to oevrride it without calling QListViewPrivate::verticalScrollToValue...
Note: The fact that this function goes through all items of the view was apparently introduced in Qt 4.8.3 when this bug was fixed (see changes). Basically, if you don't hide any items in your view, you could modify Qt code as below:
/*QVector<int> visibleFlowPositions;
visibleFlowPositions.reserve(flowPositions.count() - 1);
for (int i = 0; i < flowPositions.count() - 1; i++) { // flowPositions count is +1 larger than actual row count
if (!isHidden(i))
visibleFlowPositions.append(flowPositions.at(i));
}*/
QVector<int>& visibleFlowPositions = flowPositions;
Then you'll have to recompile Qt and I'm pretty sure this will fix the issue (not tested however). But then you'll see new problems if you one day hide some items...to support filtering for instance!
Most likely the right fix would have been to have the view maintain both flowPositions and visibleFlowPositions to avoid creating it on the fly...
I have made the following test:
First of all i create a class to check in the calls:
struct Test
{
static void NewCall( QString function, int row )
{
function += QString::number( row );
map[ function ]++;
}
static void Summary( )
{
qDebug() << "-----";
int total = 0;
QString data;
for( auto pair : map )
{
data = pair.first + ": " + QString::number( pair.second );
total += pair.second;
qDebug( ) << data;
}
data = "total: " + QString::number( total ) + " calls";
qDebug() << data;
map.clear();
}
static std::map< QString, int > map;
};
std::map<QString,int> Test::map;
Then I insert a call to NewCall in index, parent and data methods of WordListModel. Finally i add a QPushButton in the dialog, the clicked signal is linked to a method which call to Test::Summary.
The steps of the test are the next:
Select the last showed item of the list
Press the Summary button to clear the calling list
With tab key select the list view again
Perform a scroll with the direction keys
Press Summary button again
The printed list shows the problem. QListView widget makes a big number of calls. It seems the widget is reloading all the data from the model.
I don't know if it can be improved but you can't do anything but filter the list to limit the number of items to show.
Unfortunately, I believe that you can't do much about this.
We don't have much control over widgets.
Although you can avoid that issue by using ListView instead.
If you try my quick example below you'll notice how fast it can be even using delegates which is costly.
Here is the example:
Window{
visible: true
width: 200
height: 300
property int i: 0;
Timer {
interval: 5
repeat: true
running: true
onTriggered: {
i += 1
lv.positionViewAtIndex(i, ListView.Beginning)
}
}
ListView {
id:lv
anchors.fill: parent
model: 1605572
delegate: Row {
Text { text: index; width: 300; }
}
}
}
I put a Timer to simulate the scrolling, but of course you can turn on or off that timer depending on whether keys are pressed as well as changing i += 1 by i += -1 if ▲ is pressed instead of ▼. You'd have to add overflow and underflow checks too.
You can also choose the scrolling speed by changing interval of Timer. Then it's just a matter of modifying the selected element's color etc. to show it's selected.
On top of which you can use cacheBuffer with ListView to cache more elements but I don't think it is necessary.
If you want to use QListView anyway take a look at this example: http://doc.qt.io/qt-5/qtwidgets-itemviews-fetchmore-example.html
Using the fetch method allow to keep performance even with big datasets. It allows you to fill the list as you scroll.

(Qt C++) Send int value from dialog to MainWindow?

I am quite new to C++ and Qt. I've gotten pretty far on my current project, but I've been putting off this one part. I have a pushbutton that opens a new dialog like this:
void MainWindow::on_fillAll_clicked()
{
int yo;
BlockSelect bSelect;
bSelect.setModal(true);
bSelect.exec();
if( bSelect.exec() == QDialog::Accepted )
{
//Get stuff here?
//I want to fill yo with the spinbox value
yo = bSelect.stuff();
return;
}
qDebug() << yo;
}
This works fine. In the dialog I have a spin box. I want to send that value inputted to the spin box to my main window when the user clicks OK.
I have been trying to get "int yo;" to have that value from the spinbox but everything I try just gets an error.
I added this to my BlockSelect public class:
int stuff();
And I made this function in my blockselect.cpp:
int BlockSelect::stuff()
{
qDebug() << "The function was called";
return ui->yolo->value();
}
But qDebug never shows anything???
So how can I fill yo from the main window with yolo from the dialog?
Sorry if I didn't explain this well :( I'm still learning.
Thanks for your time :)
First of all, there is no need to call exec() twice, just use it once within the if statement.
To answer your question, you still have the bSelect dialog object (and I'm assuming BlockSelect is a class you define?), so make an accessor function inside it to retrieve the values you want.
if( bSelect.exec() == QDialog::Accepted )
{
//Get stuff here?
//I want to fill yo with the spinbox value
yo = bSelect.stuff();
return;
}
EDIT:
Your BlockSelect class needs to contain an accessor function, this means a function that returns a value.
int stuff() { return ui->yolo->value();}
What I'm doing here is retrieving the spinbox's value (assuming it is named 'yolo') and returning it as a result of calling the 'stuff' function.

Get target of cascades TouchEvent not working

I'm having problems trying to reach for the target of the Touch Event from BB10 cascades API. I have several containers, one below the other, and each one of them have the same Touch signal and slot assigned. Everything is being dynamically loaded from C++. So, in order to catch each touch event, I need to know which container triggered the event. I've read that I just need to use the TARGET property from the TouchEvent, but is not working and I dont know why. So I'm asking for help
Here's my code:
for (int i = 0; i < 10; i++) {
QmlDocument *qml = QmlDocument::create("asset:///customComponents/TableRow.qml").parent(this);
Container *passivesRow = qml->createRootObject<Container>();
passivesRow->setProperty("labelTextOne", "Hello_" + i);
bool res = QObject::connect(passivesRow,
SIGNAL(touch(bb::cascades::TouchEvent*)), this,
SLOT(handleAccountTouch(bb::cascades::TouchEvent*)));
Q_ASSERT(res);
Q_UNUSED(res);
myCurrentPageContainer->add(passivesScroll);
}
void PosicionConsolidada::handleAccountTouch(bb::cascades::TouchEvent* event) {
if (event->touchType() == TouchType::Up) {
qDebug() << "event catched";
VisualNode *p = event->target();
qDebug() << "object p: " << p->property("labelTextOne"); //Print nothing
}
}
Everything else is working just fine. My list of Containers is being created fine with their respective texts. When I click one of them, the event is being catched successfuly. I also tried to cast the VisualNode object to Container and it didn't work either. Please help!.
I would advice you an alternate approach which I used before. You can set objectName of control like this:
passiveRow->setObjectName("Hello_" + i");
QObject::connect(passiveRow, SIGNAL(touch(bb::cascades::TouchEvent*)), this,
SLOT(handleAccountTouch(bb::cascades::TouchEvent*)));
& in SLOT using it you can know which control emitted the signal:
if (event->touchType() == TouchType::Up) {
qDebug() << "object: " << QObject::sender()->objectName();
}
Here, sender() returns the control which emitted the signal.
In the API reference, there is no onTouch signal for the container.
On the contrary of other element like CustomControl
I do not know how your signal was successfully connected to your slot, but I guess that it was propagated from another component inside the container. So the target may be a Label or something else inside it.

QTime->addSecs cause segmentation fault

I'm writing simple pomodoro application, which is basically countdown timer. Right now, I've got countdown working, but the weird thing is that when I add another attribute to my class (arbitrary), I get Sedmentation fault error.
Using gdb, the problem should be here:
void Status::showPomodoroTime() {
QTime time = pomodoroTime->addSecs(elapsed);
activeTime->display(time.toString("mm:ss"));
}
where activeTime is QLCDNumber widget and elapsed is int.
More context:
void Status::createDefaultIntervals()
{
pomodoroInterval = new QTime(0, 25);
pomodoroBreak = new QTime(0, 5);
pomodoroLongBreak = new QTime(0, 15);
}
void Status::run()
{
if (pomodoroActive == STOP) {
pomodoroTime = pomodoroInterval;
showPomodoroTime();
}
pomodoroActive = RUN;
updateStatusArea();
timerTick();
}
CreateDefaultInterval definitely runs before showPomodoroTime.
What bugs me, that whole application works fine. Just when I add another attribute, it starts to throw sedfault.
How can variable declaration in *.h file cause segfault in *.cpp?
If you want more code, I can put it anywhere. I just don't know, what place is persistent enough. Don't want to post it here (about 300 lines of code).
check if(pomodoro!= NULL) and then do addSecs().
pomodoroTime is probably uninitialized or deleted

How does MFC's "Update Command UI" system work?

I'd like to know more about how this system works, specifically when and how the framework actually decides to update a UI element.
My application has a 'tools' system where a single tool can be active at a time. I used the "ON_UPDATE_COMMAND_UI" message to 'check' the tool's icon/button in the UI, which affected both the application menu and the toolbars. Anyway, this was all working great until some point in the last couple of days, when the toolbar icons stopped getting highlighted properly.
I investigated a little and found that the update command was only being received when the icon was actually clicked. What's strange is this is only affecting the toolbars, not the menu, which is still working fine. Even when the buttons in the menu are updated the toolbar icon stays the same.
Obviously I've done something to break it - any ideas?
EDIT:
Never mind. I'd overwritten the Application's OnIdle() method and hadn't called the original base class method - that is, CWinApp::OnIdle() - which I guess is where the update gets called most of the time. This code snippet from https://msdn.microsoft.com/en-us/library/3e077sxt.aspx illustrates:
BOOL CMyApp::OnIdle(LONG lCount)
{
// CWinApp's original method is involved in the update message handling!
// Removing this call will break things
BOOL bMore = CWinApp::OnIdle(lCount);
if (lCount == 0)
{
TRACE(_T("App idle for short period of time\n"));
bMore = TRUE;
}
// ... do work
return bMore;
// return TRUE as long as there are any more idle tasks
}
Here's a good article that kinda explains how to do it. Don't use his code example with WM_KICKIDLE though, instead scroll down to the comments section. There are two code samples that explain how to do it better. I quote:
//Override WM_INITMENUPOPUP
void CDialog::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
CDialog::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
// TODO: Add your message handler code here
if(pPopupMenu &&
!bSysMenu)
{
CCmdUI CmdUI;
CmdUI.m_nIndexMax = pPopupMenu->GetMenuItemCount();
for(UINT i = 0; i < CmdUI.m_nIndexMax; i++)
{
CmdUI.m_nIndex = i;
CmdUI.m_nID = pPopupMenu->GetMenuItemID(i);
CmdUI.m_pMenu = pPopupMenu;
// There are two options:
// Option 1. All handlers are in dialog
CmdUI.DoUpdate(this, FALSE);
// Option 2. There are handlers in dialog and controls
/*
CmdUI.DoUpdate( this, FALSE );
// If dialog handler doesn't change state route update
// request to child controls. The last DoUpdate will
// disable menu item with no handler
if( FALSE == CmdUI.m_bEnableChanged )
CmdUI.DoUpdate( m_pControl_1, FALSE );
...
if( FALSE == CmdUI.m_bEnableChanged )
CmdUI.DoUpdate( m_pControl_Last, TRUE );
*/
}
}
}
See if this helps - http://msdn.microsoft.com/en-us/library/essk9ab2(v=vs.80).aspx