In MFC program, how to pass data between different dialog? - c++

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.

Related

Is it possible to create a dynamic room by passing in variables?

I am attempting to create a framework where I can have multiple events all use the same room.
For example, the player triggers an event and the event builds the room with the passed in variables.
I am having trouble making the room dynamic. I want the room and the objects in the room be reusable for every event. This includes the buttons as well.
Is this possible to do?; OR
Do I have to create separate rooms for each unique event I wish to create?
The game is mostly menu based (like the game "Long Live The Queen") if that helps.
To answer simply, yes it is possible.
There are a lot of cases where I have been able to fit a lot of stuff into a single room in Game Maker. Here are a few ways to achieve this "dynamic" game creation:
Files and Scripts. You can use a single room to hold a variable number of levels by storing walls, floors, player positions, events, etc inside of a file. You can make a script that takes the filename (your "passed in" variable) and then let it simply create all of the instances inside the level for you in that room. You can also have a function that cleans up the room to prepare for another level to load. The side effect though is that your uniqueness is limited to what information can be stored in those files. You can store menu options and text dialog too if you wish.
"Unique" Objects. Game Maker is an IDE. There is nothing stopping you from making new objects in the editor for a unique case and then adding a handler in another object to create it on demand. You have to manage switching between them though.
Make a "manager" object. It can handle all of the events of something happening in-game (and in that room, for that matter). Plus also it can be used by objects to store non-global variables before being destroyed. For instance, if a character dies, it can set a variable in a manager object to "true", which would trigger a boss to appear.
In terms of manipulating object events dynamically though, unless you are running something like Game Maker 8, that is no longer possible. I say this because prior to GameMaker:Studio, object, sprites and others can be created dynamically in game via functions like "object_add()". Of course, these are obsolete and can no longer be used. Nevertheless, there are always ways around it.

Save Workspace MFC C++ MDI

I have a MFC MDI application. The app can have 2 or more dialogs open. I want to implement the "Save Workspace" feature so that the user, when opening the workspace next time, opens the dialogs that were opened when he saved and closed the workspace. How to do this?
The functionality is built into the CMDIFrameWndEx implementation. SaveMDIState stores the current setup, while LoadMDIState restores it. The documentation also explains, how to persist the position and size of the frame window itself, in case that's something you want, too.
Generally this is accomplished by storing the current state of the application into some sort of persistent store. Depending on your architecture this could be a local configuration file (xml, json, etc) stored under the Windows User's profile directory (you could also use the Windows Registry), a remote store such as a database could be used or perhaps such state could be stored into cloud storage. Just depends on how the application currently handles configuration and how universal you want to make the state storage.
You will want to implement some sort or running history of UI state. Storing the currently open windows and their locations when they are loaded, closed and moved. Inject a history tracker into each MDI child that is created. This could be a singleton type in the MDI parent. It should have facility to look up a window by its handle and should store the relevant information in a structure that makes sense for serialization. In each of the afore mentioned events add calls to the tracker with the appropriate changes. The tracker should persist along whatever rules you determine are appropriate.
The load process then requires that the MDI parent interrogate the tracker after it has initialized with what ever stored state existed. Using the stored information (window type and location (and data?)) the MDI parent then opens up the appropriate children at the appropriate locations.

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.

How to collect data and pass it around

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.

How do I get the PowerBuilder graphicobject for a given HWND handle?

In my (PowerBuilder) application, I'd like to be able to determine the graphicobject object which corresponds to a given window handle.
Simply iterating over the Control[] array and comparing the value returned by the Handle() function for each of the child controls doesn't work, since not all objects in my application are children of the main window (consider of login dialogs).
Any PowerScript or C/C++ solution would be acceptable.
Is there maybe some window message I could send to window handles, and this message is only understood by PowerBuilder windows, which would the respond with their internal object name, or the like?
Is it a requirement to determine the object from the handle, or do you just want to identify an object, for example to know where the code you need to modify is? I made a tool that does the latter, but it uses object focus, rather than window handles.
(added 2010-06-21) For windows that aren't children of the main window you could explicitly check each of these window class names with isValid(). Then for each valid window, dig through looking for the handle. This should work as long as you only open one instance of the window class at a time. If you open multiple instances, I think you'll need to add a registration mechanism to the open of those windows so the application has a way to access them.