How to save layout settings of MFC application? - c++

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.

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.

ActiveX Property Persistance

I have a question about an ActiveX Control I am developing. I have hashed my way through most problems but I am stuck at a real road block. This ActiveX is being imorted into other software so I have to have a good implementation of the Property Pages. I have managed to get some persistant properties working with one issue. When I make a change in the property page it is updated and persists as long as the application that is development app that is using it is open but it reverts back when I reload the app. I have narrowed this down to the fact that the development app doesnt realize the ActiveX has changed and therfore doesnt save. If i make a unrelated change and save the program all is good and the values persist as expected. I have tried everything and cant seem t get the application that imports my ActiveX to realize when it has changed via the property page. I am wondering if anyone has some work arounds for this type of problem. It seems to me if I could force the DoPropExchange() it would work but I dont know how to call this explicitly.
Thanks in advance
Matt
Thanks for the input. I did have the SetModifiedFlag() but it wasnt working. After poking at it I solved that problem but now I am redirecting my question. I had removed the property above in question from the idl files dispinterface in order to prevent the application that loads the activex from displaying the property in its "Connection List"(3rd party application specific"). It appears that the app loads all the interface into this list but this is not good as some properties should be persistant and only modifiable through the proppages. I tried all the flags like hidden and local but still were displayed in the list. When I removed it from the dispinterface it was how I wanted it but would not signal the IsModified. My new question is in there another way to define properties for an instance like this or is it possible to have a secondary interface(I have not tested if the application would see this interface because I am not sure how I would go about defining this inteface)or to have a property only between the proppage and control. Or is there another way to signal the dirty. The OnMemberVariable of the control was properly executing I know from testing it just seems SetModifiedFlag() doesnt do anything if the property is not in the dispinterface
Thanks Again
You need to mark your control as "modified", so that its host could detect it and re-save persistent properties. In this case IPersistXxx::IsDirty implemented by your control would indicate dirty state.
MFC based control has COleControl::SetModifiedFlag for this purpose:
Call this function whenever a change occurs that would affect your control's persistent state. For example, if the value of a persistent property changes, call this function with bModified TRUE.
Update: To hide a property from property browser you can use nonbrowsable attribute.
Use the [nonbrowsable] attribute to tag an interface or dispinterface member that should not be displayed in a properties browser.

Deleting / Editing ATL COM DLL properties / methods

I have created a COM ATL DLL in VS2012.
Adding events and properties is very easy.
However, I see no easy way to edit or delete an event or a property.
VS2012 automatically creates a lot of code for the event or property when I use the Add Wizard, and I am not sure if I should really delete or change this automatically created code manually when I made a mistake and want to replace or delete something.
Is there a way to edit and delete them in a clean way?
Perhaps there is a property / event manager somewhere in VS2012, but I did not find it.
Thank you!
You edit declaration of the methods/properties of your interest on IDL, and then the project stops building until you respectively fix it by reflecting changes on your C++ implementation - that's it.
IDL changes along with implementation updated respectively builds you updated DLL.
Be aware that applications which are already built against earlier method/property set might be in trouble after the update. Related earlier questions you might be interested in (you might, however be not - which I sense is the case at the moment, if your question is about updates while you are developing, and not updates on released module):
COM: If I change the parent of an Interface do I need to create a new Interface?
Would adding a new function to the existing COM interface break its binary compatibility?
Why is it necessary to add new events to the *end* of an IDL interface?

Creating a DialogBar with MFC with my own controls

I'm turning mad with a little problem with Visual Studio 2008 and MFC. I'm working on a project actually and I'm trying to create an SDI Application. Right, now I want to add a dockable DialogBar. Well, the first time I added it with the resource view, I could create the bar without problems.
But... I want to add some controls like a couple of ListBox, buttons and so on. The program doesn't allows me to create member variables for these controls. The option appears in grey.
Searching a little, I found that it's mandatory to create a new class derived from CDialogBar and "enhance" it with the Message handler and so on. I've been reading some tutorials and it didn't work for me.
Can you please help me? I'm starting to get nervous, the use of dialogbars is mandatory in my design and I've never implemented them before.
Thank you very much, and sorry for my poor english.
You can add a control member variable by hand instead of using the wizard. All it takes is a call to DDX_Control in the dialog bar's DoDataExchange function.
But CDialogBar-derived classes do not handle control clicks. The CDialogBar class forwards all of those messages to the dialog bar's parent window. So be prepared to add the message handlers to the parent (usually CMainFrame).
For learning purposes you might try creating your dialog bar as a CDialog first, to see the proper code lines and message map entries supplied by the wizard. Then you can copy/move these details as appropriate into your actual code project.

Choosing between a Dialog Based Vs SDI Projects

I am new to MFC well not entirely new but wanted to ask experts on this forum as why one would choose one project over the other. I hope this is not a stupid question as I am relatively new to MFC.
Thanks so much
Chose based on what template your application fits best into:
Single Document Interface (SDI) - if your application needs to work with only 1 document or data object or data set at a time
Example: notepad.exe
Multiple Document Interface (MDI) - if your applicaiton needs to work with multiple documents or data objects or data set at a time
Example: Visual Studio
Dialog Based - for anything else.
Example: Calculator
No matter what you chose, you still have the same functionality available to you in the end and you can cusotmize it in any way. So you aren't limiting yourself to anything you start with.
All variants come with CWinApp which is the base class for which you derive your MFC applications.
With a dialog based application you start with a CDialog as well. With an SDI application you start with CMainFrame, CDocument, and CView as well.
If you select an SDI project you get a whole Model-View-Controller framework included.
You get a document class (inheriting from CDocument) which ideally should hold all of the data, and a view class (inheriting from CView) to do with the display.
You get given a hosting frame with a menu already attached, and there are functions you can override to save and load to file.
If you have a dialog based application, then you get one dialog. That's it. Of course, this dialog can spawn off others, but the application essentially consists of a dialog.
If you're developing a small application that just does one task, a dialog application is appropriate, because you don't need the overhead.
If you are developing an application where the user will be loading, editing and saving data, then the SDI path would be more appropriate.
Having answered your question, I'd politely ask if there was a compelling reason why you were choosing MFC over Windows Forms. I believe that MFC was an excellent technology for its day, but the Visual Studio suite offers more advanced tools (if you're prepared to go down the .NET path).
If a "document" is the right metaphor for your application, use SDI or MDI. (Single of only one document can be open at a time, Multiple if more than one.) When you think about it, the document metaphor really isn't appropriate for most applications.