MFC: Which CFrameWnd function is called after CView::OnInitalUpdate() is called? - mfc

I have an MFC app that uses a CSplitterWnd to create multiple-pane views. That process is done in the CFrameWnd::OnCreateClient() call. After that, at some point, the various views have their CView::OnInitialUpdate() function called. One of the views is a CTreeView and another a CListView with multiple columns that are setup within the OnInitialUpdate(). I need to setup the default CTreeView Item which updates the CListView as well. However, if I set the default within OnInitialUpdate the CListView has not yet setup the various columns. Therefore it seems I need to set the default CTreeView Item after all that is done. I presume I'd do this in some CFrameWnd callback. My question is at what point do I do that?
TIA!

It appears that you have dependencies between your views; that's not right.
The data should be stored in the document (even the current selection, if it supposed to be shared between views).
Than the view that is responsible for the change should call CDocument::UpdateAllViews(). As a result, all other views OnUpdate() will be called.
Please see https://learn.microsoft.com/en-us/cpp/mfc/reference/cview-class?view=vs-2019

Related

How insert multiple FormView in View of an SDI application

I searched on the forum and I don't find a solution for my issue. So I hope you can help me :)
I work on a personal project for SFC designing (Sequential functional chart) and I'm working with visual studio in SDI(I'm using MFC library). If you see the "design" of an SFC you can see the different elements needed to compose this. So you can find Step, Transition, and more. If I take a step for explaining my issue, after double click on the step a popup dialog is opened with the elements to define this step (actions on this step, and more). The issue is here, I can't see two or more step elements at the same time. I want to reuse the existing concept on other software, see this.
Step close
Step open
Dialog to add
My question is, how I can implement a dialog with my graphic element in mainframe (In this case, a step)? I don't know how I can insert a dialog with my element, I think I need to use CFormView, but I don't know.
This dialog needs to be resizable and reduce directly by the step graphic.
any idea?
Thank you in advance! Sorry for my English ..
Sorry, I think my request is not clear .. (Thank you for your answer)
The context, it's an SDI application with the Document/View architecture. Actually the view is derived from CScrollView.
So, in the document class, you have the different lists of components for make SFC (Steps, transitions and symbols ..). I'm working today on Step element.
The user inserts a new step, the step is draw on the view like this :
enter image description here
And now the user want change the events on this Step, for this after double click on the step the events editor is opened at right of step draw, like this :
enter image description here
For this, I've created a new dialog resource and create the class by wizard in CForwView derived class. In step attribute, you can find one instance of this derived class (The derived class of dialog).
But this doesn't work correctly, I think my method is bad. At the first try, I have sent the pointer of the current document to the "CFormView::Create" function for having the "Save" button active with the focus on the FormView. But after destroying the step, the instance of FormView is destroyed and the document with the instance of formview ...
No problem, you can use "Create" within CCreateContext a null pointer. But with the document or without I have a lot of problems (graphic design not correct in FormView, regularly (not systematic I have assert fail on Proc exchange (for differents reason)). But the "concept" is good, the editor follows the draw if I scroll, I can open or close the editor at any time and on any elements.
For the old capture, it's my SFC designer "model". My application is a complement to this application, so I want a similar design. I don't know how work my model application ..
On my application all is draw by MFC GDI, I don't use ActiveX or other tools.
So what is the correct way to implement one instance of editor by instance of step ?
For the implementation on this FormView I have :
- Make new dialog in ressource
- Create a derived class of CFormView with the created dialog
- Add one instance in attributes of Step element
- "OnDbClickOnStep" -> Call "Create" with the good position / size, pointer of mainview (in my case the CSrollView derived class)
- Done, FormView inserted in a mainview, I can edit my step events.
? Not done, I lost save button and other function linked to the document with the focus on a control in FormView. The app want a document with this view, how to override this ?
? Error in Proc exchange, for different reason...
You have an idea ?
You normally don't draw anything in the "main frame" (or the "MDI clild frames", in the case of a MDI application), this is done by the library, and imo sufficiently so. You display your data in a CView-derived class.
CView is the base class of all other MFC view classes. It's a simple graphical class - you need to paint it yourself in the OnDraw() member.
CScrollView is a descendant of CView, adding scrolling functionality (scroll-bars are automatically displayed if the scrollable area is bigger than the visible window area).
CFormView is a descendant of CScrollView, displaying a dialog resource-script, containing "controls" (edit-boxes, check-boxes, images, ActiveX etc).
As in your case the "controls" won't be initially known (except maybe for some few special cases) and rather programatically created, the resource script will most likely be empty, so using either CFormView or CScrollView will basically be the same. I would suggest starting with CFormView, and "downgrade" it to CScrollView if CFormView is not necessary or causes you troubles.
What are those "Step" items shown in the pics? ActiveX controls, child dialogs maybe? These work best as child controls on a dialog window. Are they already implemented, or they are just pics of some other software? Btw ActiveX is a way to define controls that can be used in other projects too, without having to include them in the project source.

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 save layout settings of MFC application?

I understand there are functions that can easily write windows registry, however I found out that in new MFC project created with wizard, some information (like split bar position, visibility of controls) gets stored automatically (or at least I found no CWinApp::Write* calls in the project). Since I have also older projects that don't have this behaviour I need to figure out how to make this without help of project wizard. Would anyone please know how does this work?
The MFC control state saving magic happens in the 'New' MFC Feature Pack, specifically in the SaveState methods, for example CMFCToolBar::SaveState.
To take advantage of this you'll therefore need to upgrade your Toolbars and Menus to use the newer controls and upgrade your application to inherit from CWinAppEx. I recommend that you use a New MFC Wizard based app as a guide on how to upgrade your old MFC app.
Most of the information is saved in CPane::SaveState(), thus if you want state of some component saved, you need to use classes derived from CPane. (for more info here is the class hierarchy).
The process of saving window states is initiated through CFrameImpl::OnClosingMainFrame(). This function in turn calls CWinAppEx::SaveState() which saves some application settings and then ALL instances of CMFCToolBar (they add themselves to global list of CMFCToolBars in call to OnCreate). In a similar way all dockable panes are saved but the list belongs to your main frame. Then positioin and size of your main frame is saved.
CViews and CFrameWnds are somewhat less favored, for what I found and tried out, the only information saved was visibility.
I used that loooong time ago. If I correctly reminds it, you should save the informations you want in a overridden CWinApp::ExitInstance() before calling base class method, and you load them in CWinApp::InitInstance. Be sure to allow for default values, because at first run, there will be nothing to load, and do not forget to call (or copy) base class.

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

CDocument call UpdateAllViews() before CView::OnInitialUpdate(), is this good?

I've got a MFC existing project. The CDocument class can update views even when view is not initially updated. Views are of CFormView type, and I know there will be DoDataExchange() called in CFormView::OnInitialUpdate().
Will this cause problem?
I think, it depends on how you implemented OnUpdate in the view classes of your document. UpdateAllViews is nothing more than an iteration over all views of your document which calls OnUpdate for every view. The base implementation of OnUpdate only invalidates the view rectangle. If you access FormView controls in your OnUpdate methods the result might depend on whether OnInitialUpdate has been called before or not. Otherwise it probably doesn't matter if you call UpdateAllViews before or after OnInitialUpdate.