Force update of a virtual CListCtrl - mfc

I have a CListCtrl containings about 2500 differents elements consisting of a 48x48 icon and text.
Due to the amount of data I implemented it as a virtual list providing
ON_NOTIFY(LVN_GETDISPINFO, IDC_LST_ICONS, &CWGDIconSearchDlg::OnLvnGetdispinfoLstIcons)
ON_NOTIFY(LVN_ODFINDITEM, IDC_LST_ICONS, &CWGDIconSearchDlg::OnLvnOdfinditemLstIcons)
My problem is when I change list content these callback get never called.
How can I force it?

Windows cannot know that you have changed an item in virtual list.
In order to trigger a redraw of your CListCtrl, you must call yourcontrol.Invalidate() which will trigger a repaint of your control.

Related

Virtual Combo Box in MFC

I have 10 CComboBox in a tab page and I want to load 10k data to each combobox?
It is taking more time for the tab page to get loaded.
In MFC how to implement virtual combobox like virtual list control?
I need to set default selection in the combobox on loading tab.
Can you please someone give me some ideas?
Thanks
There is no such virtual Combobox in the WinApi, but you have serveral optimizations.
Only load the complete data to the box, if needed. So only when you get the CBN_DROPDOWN event you populate the box with all items. Otherwise you just insert the one selected item.
This method has a drawback that cursor up down in a closed combo doesn't work.
Also you can populate the box only when it receives the focus. Also in this case you just populate the box with the current selected item.
The best result you get is using a owner draw combobox, without using CBS_HASSTRING. CB_ADDSTRING receives a pointer to your data. In DrawItem you use this pointer for drawing.
You still need to add 10k items to each box, but there is no string management and the box is real fast without this memory allocations.

When is CMFCListCtrl::OnGetCellBkColor function called?

I'm using CMFCListCtrl to control background color of each cell when i want in my MFC Project..
so I'm overriding OnGetCellBkColor() to define each cell's background color.. but the problem is this funcion is never called during runtime.
even when I add the items. when is this function called? Can i call this function manually when I want?
OnGetCellBkColor is called from within OnCustomDraw. So it is called in a normal sequence when items are drawn. But it is never called when you defined you list control as owner drawn. So LVS_OWNERDRAWFIXED must not be set to the styles.
You have the source code to find this information by yourself.
Also a problem might be that you didn't subclassed the created control or never created the control as a CMFCListCtrl.

How to sync a Progress Control with a set of data which is loading in a Dialog Box in Visual C++

I'm trying to add a progress control in my dialogs, that will step upon every iteration of a loop until completion. I've never played around with progress controls before, so I'm totally clueless as to where I should start. I've added a progress control resource view into my dialog, but it just shows up as an empty progress control. I'd like to have the progress control dynamically appear/update when after pressing a button an image from somewhere stars being loaded.
I am trying to add a progress control on a dialog box in Visual c++ environment.
After adding this tool the following code added to main.cpp :
void CPanoramicsampleDlg::OnNMCustomdrawProgress1(NMHDR *pNMHDR, LRESULT *pResult){
}
I can show procedure of loading in a Text control as follow:
sprintf_s(pack1,"Data%d%%",Event);
::SetWindowText(GetDlgItem(IDC_Static)->m_hWnd,pack1);
so in this way I can see loading process as %d in a text window but I don't know how to show loading procedure by progress control and how and where to define range or even progress bar handle for this progress control so on.
finally I would like to know is there any function for progress control for example:
::EnableWindow(GetDlgItem(IDC_Progress1)->m_hWnd);
You should first add a variable for the control, by right-clicking on the progress bar in the dialog editor, and choosing Add Variable... Your dialog class will then have an instance of a CProgressCtrl class on which you can then call the members that IInspectable has mentioned in his answer. Delete the OnNMCustomdrawProgress1 handler, you don't need it.
e.g.
m_progressCtrl.EnableWindow(TRUE);
m_progressCtrl.SetRange(0, 100);
m_progressCtrl.SetPos(75);
Then whatever that eventParam1 value is that you mention, proportion it between your start and stop value, and call SetPos with it.
Update after comment:
Do the SetRange() in the OnInitDialog() function. If you don't already have an OnInitDialog you need to override it, follow the instructions in the accepted answer of this question to do it.
VS 2008, MFC: add OnInitDialog - how?
As for where you put the SetPos(): You describe that you can already track loading progress in a text control using some or other eventParam1. That sounds like a handler or callback from what ever loading you're doing, and that is where you will instead SetPos() on the progress bar instance.
The CProgressCtrl Class provides the following members that you will have to use:
CProgressCtrl::SetRange: Allows you to set lower and upper bound. These values ideally reflect your starting state and finishing condition.
CProgressCtrl::SetPos: Used to update the current position. You would update the current position where you used to output progress in your edit control.
As an alternative to calling CProgressCtrl::SetPos with an explicit position value, you can set a step increment, calling CProgressCtrl::SetStep, and update the control with a call to CProgressCtrl::StepIt. If you know the step increment ahead of time, this is an easier way to go about updating the current position.
Additional information is available at the MSDN: Using CProgressCtrl.

Updating CMFCRibbonBar elements from document

I would like to update the ribbon from the CDocument derived class because the information relevant for ribbon's status is stored there. The was created by the Wizard and edited in resource manager
Some elements (Buttons, checkboxes) can be updated with ON_UPDATE_COMMAND_UI macro.
But I have a headache with update other things like CMFCRibbonComboBox or CMFCRibbonProgressBar because CCmdUI doesn't provide suitable functions to deal with them (ie AddItem)
Other option using GetDlgItem doesn't work, because neither CDocument nor RibbonBar elements are derived from CWnd.
So what is the way to update CMFCRibbonComboBox and others?
I faced a similar problem with combo boxes on a toolbar. The combo box was used to display the current mouse coordinates of a point in "world coordinate" space while the mouse was moved. I derived my own class for the combo and exposed some methods that would update its contents. I then picked the most appropriate point in the code to make the appropriate calls to those methods. That may be during the paint cycle (eg. OnDraw), or, during idle time. A similar approach of deriving and exposing methods should work for you. The only caveat is to pick the correct location to inject your calls to perform the update.
I first tried RogerRowland's solution, but it soon became annoying to add a function to MainFrame for every trifle , then to call AfxGetMainWnd() from document and apply static_cast on it.
Instead I now store pointers to the ProgressBar and the combobox inside the document. I added the methods to CMainFrame to get them and removed the rest.
The only dificulty with it is the fact that the document is constructed before the main window. So I have to delay the initialisation of the mentioned pointers. I solved it by adding setRibbonBarPointers() to the document and calling it from OnInitialUpdate() of the view

How to set height for owner draw variable CListBox (MFC)

I have a variable-height owner draw ListBox control. When I call AddString, a MeasureItem message is sent asking me to tell Windows the size of the item. The problem is, the code hasn't had a chance to call SetItemData yet, so the code can't determine the size yet.
I've tried calling SetRedraw(FALSE) hoping that would postpone the measure request, but no luck.
So how can I add an item to a CListBox and get the Item Data passed in at the same time? I've tried with and without LBS_HASSTRINGS. Not sure what else to try.
If your list box control does not have the LBS_HASSTRINGS style, the pointer argument to AddString() is not considered as a string but as item data (see the remarks section in the documentation for LB_ADDSTRING).
Therefore, if your list items consist in both a string and some item data, you can wrap these two pieces of information in a structure or a class and pass a pointer to that wrapper to AddString().
The upside is that both the string and the item data will be available by the time MeasureItem() is called. The downside is that you will have to implement CompareItem() if your list is sorted, and to free the wrappers both when items are deleted and before the list box control is destroyed.