I have an MFC MDI app based on Doc/View Architecture. The problem is that I want to pass some parameters to the View class from the main frame "before" OnCreateClient is called. I am not sure how I can do that as most of the stuff in the doc/ view architecture is done under the hood.
Vague question can only be met with vague answers. Please clarify what your parameters do. Are they view-specific? Document-specific? Not visible to the user?
If your problem is that you have multiple view classes which all use a shared data structure, you could use make the shared data structure a global variable which you initialize in your CWinApp-derived class. Or you could (multiply-)derive them from (both CView and) a parent class that manages the shared data structure.
You could read your parameters from the Windows registry. You might want to do this to save the sizes of windows, their styles, etc.
I don't see what OnCreateClient has to do with any of it, though. If CView::GetDocument() returns NULL then your CView-derived class shouldn't be trying to draw anything.
Related
I do not have great expertise in MFC. I have a MFC application with the basic setup: single document application. Now In the project I have the most standard setup: one ...View class one ...Doc class and one ...WinAppEx class. These three represents the model-view-controller design principle respectively. I do not find a way to access View class from the WinAppEx class.
My actual use case is I have some command line arguments passed to the app. I want to display these arguments on my primary view. To access those arguments I have in my ...WinAppEx::InitInstance() method
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
Now I need to pass arguments to the view. I have tried ::GetMainWnd() and traverse its siblings and its children. I also tried ::GetNextDocTemplate() and then ::GetNextDoc() and then ::GetNextView(). I still did not find my ...View instance. Can you please shed some light?
Why do you HAVE to access the view from the application? Why not access the application from the view? From the view class you can call AfxGetApp() and get the command line arguments. Also, for a very simple app, usually there is a global variable defined by the wizard called "theApp".
You may be trying to access the CView before it has been created. At the end of the InitInstance function you can cast the m_pMainWnd to a CMainFrame* and use that pointer to call CMainFrame's GetActiveView() function.
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.
I should find another interest because this one is taking the life out of me quickly. Seems like a lot of people are confused about the intricacies of MFC code, including me. I have an MFC Dialog Box application that creates several dialogs that you navigate to using the typical back or next function. Along the way you collect data via radio group buttons, list boxes and various other controls. For the most part I understand how to get a handle on the data by using the m_ variables provided by the AFX maps throughout the code for each distinct dialog. At the end - and sometimes during - the data collection/selection process gathered by dialogs, I need to do things with what has been collected. I may need to take the data from one dialog and modify the next based on the previous. It seems like when you move through the dialogs the data from the last is lost unless you save it somehow. I know that there are dozens of ways to do this and I have toyed with several of them, from object passing, to creating new classes, new structures, global variables, pointers, whatever.... My concern is, I need a data structure of some sort to stay up and active in memory long enough for my user code to do something with it. That is the problem I think, I don't know in MFC how to deal with this. I have currently decided to go with a struct called dlg_DataHandler (to house collected data from each dialog) with a few test members in a .h file. It has been typedef'd as a pointer. I am creating a variable of this type and setting it = new dlg_DataHandler, but the data isn't getting passed around like I want from dialog to dialog. One thing that I wonder about is, I don't know exactly where to place the "new" statement for creating the variable. Its as if data is not flowing to and from the structure as it should. Anyway here is some of the code:
// file1.h
typedef struct dlg_DataHandler {
int var;
char* String;
int RepetitionRadio; // radio button data
constructor here
} *dlgDataHandler;
extern dlgDataHandler DlgData;
//*****************
// file2.cpp
dlg_DataHandler DlgData = new dlg_DataHandler; // not located anywhere in peticular just in the code since I DON'T KNOW where to put it. DlgData->member gets loaded in the dialog .cpp files to try collect data, but it doesnt seem to be passing data across the different windows.
Put the variable in your main application class (the one derived from CWinApp) and call new in InitInstance(). You can then use AfxGetApp() to gain access to the application instance, and so your variable, from anywhere else in the code.
In web development, when we want to pass something between different pages, we might use the Session to save the data. But in MFC, what can we use to store these things?
Thanks!
Typical MFC Applications will have a Document-View-Frame architecture. Data is stored in the Document object, and accessed globally. You can access it anywhere via AfxGetMainWnd().
AfxGetApp() will also get you a pointer to your main application, which is another good spot to store data if you're not using a Document View architecture. If there is a lot of data, you can construct a class to hold the data, then add an instance as a member variable to the CWinApp in your project.
Another option, which I don't recommend but I have seen, is to have the dialogs themselves as member variables in the CWinApp, and then each dialog can reference the other. Basically, the user clicks 'ok', but then the dialog disappears, but is not deleted. This means all the data they entered is still accessable via the dialog variable.
There are a ton of ways to share data between dialogs. You may need to be more specific about your needs.
Store it in a global variable.
Store it in thread local storage (TLS).
Have one Dialog send a window message via SendMessage() or PostMessage().
Things get more complicated from there.
How can I place a MFC CFormView inside a CDockablePane which was introduced in the VS 2008 MFC Feature Pack?
Check the BCGSoft Samples for doing this with a cview. The class names are a little different but its more or less the same stuff since they provided CDockablePane to Microsoft.
I couldn't find such samples in MFC Feature Pack samples.
All projects containing CFormView are :
TasksPane
TabControl
TabbedView
StatusBarDemo
SetPaneSize
MenuSubSet
But in any of the projects, CFormView is not embedded in CDockablePane.
There is a sample of the feature pack that does this.
However, what I do is the following: I made a CDialog-derived class that I put in the DockablePane. Then I make a CFormView-derived class and make an instance of that a member variable of the dockable pane. Every function that I'm interested in (most likely UpdateView() or whatever it's called), I forward to the CDialog-derived class. That way I can sidestep the difficulties of shoehorning the doc/view structure into my application and still get the benefits.
Actually there are a few ways of doing this.
If you derive your own CFameWnd class and then put an instance of that class in the CDockable pane you now can put whatever type of framework that you want inside of that CFrameWnd derived class.
The trick is to make sure that you are doing the creation in the correct order. If you try to call it to early then your internal views will never be created.
Probably this cab be a clue.
http://www.codeproject.com/KB/toolbars/sizecbar.aspx
Although it doesn't use CDockablePane, concept behind it is same.
I didn't try CDockablePane and CFormView work like the one explained in the page yet, but by taking a glance at it, I feel that things are similar.