I have a solution and it has two projects in it. When I got the code they told one project handles the visual part and the other has the logic part. Now I added one button to the window. To do that i edited the project which handles the visual part. I am very new to this but creating and adding buttons is fairly straightforward in visual studio 2010. Now the problem is I want to detect if the button is pressed from the other project. I am sure that the projects are sharing some data, but I am not being able to capture it. For now I am changing a value in a file and reading the same data from the other project to check if the button is pressed. But I think there is a better way to do it. Can anyone help?
I don't think the two projects are sharing automatically. You will have to define the interface that the two projects communicates. For instance, in your solution above the "a value in a file" is the "interface" you have defined. What sounds like you are trying to achieve is to separate the controller (logic part) and view (visual part) separately, which seems to indicate that your project is using MVC model.
I would suggest defining an abstract class (interface) that defines the interaction you want between the two projects. All they have to share is a single header file.
For example:
// Solution A (Controller - logic part)
// MyUIHandler.h
class IMyUIHandler //You can also use microsoft's interface keyword for something similar.
{
public:
HRESULT onButtonPressed() = 0; // Note that you can also add parameters to onButtonPressed.
};
HRESULT getMyUIHandler(IMyUIHandler **ppHandler);
Then implement this interface:
// Solustion A (Controller - logic part)
// MyUIHandler.cpp
#include "MyUIHandler.h"
class CMyUIHandler : public IMyUIHandler
{
private:
// Add your private parameter here for anything you need
public:
HRESULT onButtonPressed();
}
HRESULT getMyUIHandler(IMyUIHandler **ppHandler)
{
// There are many ways to handle it here:
// 1. Define a singleton object CMyUIHandler in your project A. Just return a pointer
// to that object here. This way the client never releases the memory for this
// object.
// 2. Create an instance of this object and have the client release it. The client
// would be responsible for releasing the memory when it's done with the object.
// 3. Create an instance of this object and have a class/method in Solution A release
// the memory.
// 4. Reference count the object, for example, make IUnknown the parent class of
// IMyUIHandler, and implement the IUnknown interace (which is boiler plate code).
// Since I don't know your project it's hard for me to pick the most suitable one.
...
*ppHandler = myNewHandler;
...
return S_OK;
}
CMyUIHandler can simply be your existing class that already handles some of the logic.
In solution B you should will call getMyUIHandler in some initialize function, for example the controller of the UI class, save that as your member. Then "Button clicked" event handler that VS creates for you.
// Solution B (View - visual part)
// MyUIView.h
class MyUIView
{
protected:
IMyUIHandler *m_pHandler;
}
// MyUIView.cpp
CMyUIView::CMyUIView(...)
{
...
hr = getMyUIHandler(&m_pHandler);
// error handler, etc...
...
}
// In the function that is created for you when button is clicked (I'm not sure if I get the signature right below.
void OnClick(EventArgs^ e)
{
...
hr = m_pHandler->onButtonPressed();
...
}
Then you can pass any parameter you define for the function onButtonPressed as soon as the button is clicked.
Related
I am a newbie writing MFC code, and I have a problem adding a string to a list box. The code shown works OK when I call the AddString object directly, but not when I add it to my own Test object as shown. WHat do I have to do so that AddString still works from inside another object? Maybe some kind of inheritance problem?
Thanks for bearing with me on this newbie question!
Duncan
void CFileProcessorDlg::Test()
{
m_strFullName1.Format(_T("Starting to process files"));
m_Message1.AddString(m_strFullName1); // Add string to list box
}
void CFileProcessorDlg::OnClickedButtonStart()
{
//Duncan's Stuff
// TODO: Add your control notification handler code here
CFileProcessorDlg dlg;
UpdateData(); // Transfer data from controls to variables
//dlg.ProcessFiles(m_InputFile, m_OutputFile); // Actually process the files here
// Problem 5/22/2017 - this works here, but not if I move it into the Test object.
//m_strFullName1.Format(_T("Starting to process files"));
//m_Message1.AddString(m_strFullName1); // Add string to list box
dlg.Test();
}
Terminology first: the entity you're calling "my own Test object" is actually a method.
That out of the way, you're instantiating a(nother) CFileProcessorDlg object (named dlg) from within your CFileProcessorDlg::OnCickedButtonStart() method.
That dlg object is created, you call its Test() method, and then the object goes out of scope at the end of CFileProcessorDlg::OnCickedButtonStart(), so it would not have any useful effect on the object calling object (this).
I think you want to do something like this:
void CFileProcessorDlg::OnClickedButtonStart()
{
//Duncan's Stuff
// TODO: Add your control notification handler code here
UpdateData(); // Transfer data from controls to variables
//dlg.ProcessFiles(m_InputFile, m_OutputFile); // Actually process the files here
// Problem 5/22/2017 - this works here, but not if I move it into the Test object.
//m_strFullName1.Format(_T("Starting to process files"));
//m_Message1.AddString(m_strFullName1); // Add string to list box
Test(); // more explicitly: this->Test()
}
I left your comments for context, but the net change was to not instantiate a new CFileProcessorDlg object.
Coming from making single-page applications with the visual WYSISWYG editor in JUCE, I'm having a bit of trouble figuring out how to invoke new windows (outside of the main GUI window). I made a test application that just has a small minimal main GUI that I created with the visual editor. It has a button "Make New Window." My goal is to be able to click that button and have a new window pop up and that this new window is a JUCE "GUI component," (AKA, the graphical / visual GUI editor file). Now, I actually have sort of achieved this, however, its throwing errors and assertions, so it would be great to get a very simple, step-by-step tutorial.
I studied the main.cpp file that the Projucer automatically created in order to get a feel for how they are creating a window. Here's what I did.
1) In my project, I added a new GUI Component (which becomes a class) and called it "InvokedWindow."
2) In my main GUI component class header, I added a new scoped pointer of type InvokedWindow: ScopedPointer<InvokedWindow> invokedWindow;
3) I created a new button in the main GUI editor called "Make New Window" and added this to the handler code:
newWindowPtr = new InvokedWindow; so that any time the button is hit, a new object of type InvokedWindow is created.
4) In the InvokedWindow class, in the constructor, on top of the automatically generated code, I added:
setUsingNativeTitleBar (true);
setCentrePosition(400, 400);
setVisible (true);
setResizable(false, false);
Which I sort of got from the main file of the JUCE application.
I also added a slider to this new window just to add functionality to it.
5) I added an overloaded function to let me close the window:
void InvokedWindow::closeButtonPressed()
{
delete this;
}
So, now when I run the app and click the make new window button, a new window does pop up, but I get an assertion:
/* Agh! You shouldn't add components directly to a ResizableWindow - this class
manages its child components automatically, and if you add your own it'll cause
trouble. Instead, use setContentComponent() to give it a component which
will be automatically resized and kept in the right place - then you can add
subcomponents to the content comp. See the notes for the ResizableWindow class
for more info.
If you really know what you're doing and want to avoid this assertion, just call
Component::addAndMakeVisible directly.
*/
Also, I'm able to close the window once and hit the button in the main GUI to create another instance of a newWindow, but closing it a second time leads to an error:
template <typename ObjectType>
struct ContainerDeletePolicy
{
static void destroy (ObjectType* object)
{
// If the line below triggers a compiler error, it means that you are using
// an incomplete type for ObjectType (for example, a type that is declared
// but not defined). This is a problem because then the following delete is
// undefined behaviour. The purpose of the sizeof is to capture this situation.
// If this was caused by a ScopedPointer to a forward-declared type, move the
// implementation of all methods trying to use the ScopedPointer (e.g. the destructor
// of the class owning it) into cpp files where they can see to the definition
// of ObjectType. This should fix the error.
ignoreUnused (sizeof (ObjectType));
delete object;
}
};
This is all a bit over my head. I was figuring it wouldn't be too bad to be able to create a new window, via a button. A new window that I could edit with the graphical GUI editor, but I'm not able to fully figure it out all on my own, through I did try. Could anyone post a step-by-step guide to doing this the correct way? I did post this at the JUCE forums, but due to my lack of GUI programming, I was unable to understand the solutions posted (my own fault), so I'm hoping to get a very simple guide to this. It would be very much appreciated. Thank you.
I figured it out. I needed to create:
A new GUI component (Remember, this is the visual editor in JUCE)
A class (I called it BasicWindow, based on the JUCE demo code) that acts as a shell to run this new window and holds the GUI component.
A JUCE SafePointer that makes a new object of type BasicWindow whenever the button is clicked and sets the attributes to that window.
Here is my code:
Referring to line 3) Inside the handler section of the button to create the new window:
basicWindow = new BasicWindow("Information", Colours::grey, DocumentWindow::allButtons);
basicWindow->setUsingNativeTitleBar(true);
basicWindow->setContentOwned(new InformationComponent(), true);// InformationComponent is my GUI editor component (the visual editor of JUCE)
basicWindow->centreWithSize(basicWindow->getWidth(), basicWindow->getHeight());
basicWindow->setVisible(true);
Referring to line 2) A .cpp file that defines what the BasicWindow is:
#include "../JuceLibraryCode/JuceHeader.h"
class BasicWindow : public DocumentWindow
{
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BasicWindow)
public:
BasicWindow (const String& name, Colour backgroundColour, int buttonsNeeded)
: DocumentWindow (name, backgroundColour, buttonsNeeded)
{
}
void closeButtonPressed() override
{
delete this;
}
};
And referring to line 1) Make the GUI editor component, which this is easy to do. You just right add a new file in the JUCE file manager. "Add New GUI Component," then visually add all your elements and handler code.
My biggest issue was that I was using a JUCE ScopedPointer, so after deleting the object, the pointer pointing to it wasn't being set back to NULL. The SafePointer does this. If any more explanation is needed, I'm happy to help, as this was terrible for someone with not much GUI development "under his belt."
Say I have two main classes, Application and ApplicationGUI. Application does lots of things and can happily run without any knowledge that ApplicationGUI exists. ApplicationGUI is linked to Application in many ways, it has maybe 50 or 100 different knobs that can change Application's behavior.
ApplicationGUI is a hierarchical structure such that it has many instances of ControlGroup, each containing an arbitrary number of Buttons and Knobs, or even another ControlGroup.
Current design: Upon instantiation of the ApplicationGUI (Application was already running with some set of default parameters), I pass pointers of Application's parameters to various components of the GUI. For example:
my_gui.sound_controlgroup.knob.link_to_param(&(my_application.volume));
If I need to do something more complex, say call a member function of Application, my_application.update_something(), how is this done?
The easy answer is to pass a pointer to my_application to my_gui.sound_controlgroup.knob, but if I only ever need to call one of my_application's functions, it seems like I am giving my knob an option to change all kinds of things that it should even know about (my_application.update_something_unrelated(), for instance). What is the cleanest thing to do in this case?
Additionally, this either requires making all subcomponents of ApplicationGUI public or having a function at each stage of the hierarchy to forward that pointer to the bottom level. This leads to quite a lot of functions. Is this a necessary consequence of a UI with a lot of knobs?
Quick Short Answer
In order to implement interaction between your non GUI related Application object and your GUIApplication object I suggest apply the "Property and Method and Event Handler" paradigm.
Extended Complex Answer
G.U.I. development is one of the most practical implementation of the O.O.P. theory.
What is the "Property and Method and Event Handler" paradigm ?
That means build, both Non GUI Classes, and GUI Classes, should have:
Properties
Methods
Event handlers
"Events" (Handlers) are also called "Signals", and are implemented with functions pointers. Not sure, but, I think your "knob" (s) are like Event Handlers.
It's a technique to apply the my_application.update_something_unrelated(), you have in your question.
Since, C++, like Java, does not have property syntax, you may use "getter" and "setter" methods, or use a "property" template.
For example, if your application has a Close method, you may declare something like the following examples.
Note: They are not full programs, just an idea:
// Applications.hpp
public class BaseApplicationClass
{
// ...
};
public class BaseApplicationClientClass
{
// ...
};
typedef
void (BaseApplicationClientClass::*CloseFunctor)
(BaseApplicationClass App);
public class ApplicationClass: public BaseApplicationClass
{
// ...
public:
Vector<BaseApplicationClientClass::CloseFunctor>
BeforeCloseEventHandlers;
Vector<BaseApplicationClientClass::CloseFunctor>
AfterCloseEventHandlers;
protected:
void ConfirmedClose();
public:
virtual void Close();
} Application;
// Applications.cpp
void ApplicationClass::ConfirmedClose()
{
// do close app. without releasing from memory yet.
} // void ApplicationClass::ConfirmedClose()
void ApplicationClass::Close()
{
// Execute all handlers in "BeforeCloseEventaHandlers"
this.ConfirmedClose();
// Execute all handlers in "AfterCloseEventaHandlers"
} // void ApplicationClass::Close()
// AppShells.cpp
public class AppShell: public BaseApplicationClientClass
{
// ...
};
void AppShell::CloseHandler(ApplicationClass App)
{
// close GUI
} // void AppShell.CloseHandler(ApplicationClass App)
void AppShell::setApp(ApplicationClass App)
{
App->BeforeCloseEventHandlers->add(&this.CloseHandler);
} // void AppShell.setApp(ApplicationClass App)
void main (...)
{
ApplicationClass* AppKernel = new ApplicationClass();
ApplicationGUIClass* AppShell = new ApplicationGUIClass();
AppShell.setApp(App);
// this executes "App->Run();"
AppShell->Run();
free AppShell();
free AppKernel();
}
UPDATE: Fixed type declaration from global function pointer (a.k.a. "global functor") to object function pointer (a.k.a. "method functor").
Cheers.
Do you know about the model-view-controller (MVC) paradigm? Think of the Application class as the model, the entire hierarchy of GUI controls as the view, and the ApplicationGUI class as the controller. You don't want Application to know about the controls, and you don't want the controls to know about Application; they should both talk only to the controller, ApplicationGUI.
Using ApplicationGUI as the conduit for communication between controls and Application means that you can test either Application or controls by replacing the other with a mock object, for example. More importantly, you can change either the controls or Application without impacting the other. Individual controls don't need to know anything about Application -- they only need to know where to send their value when it changes. And Application shouldn't care whether an input comes from a knob or a slider or a text field. Keeping those two areas separate will simplify each of them.
Additionally, this either requires making all subcomponents of
ApplicationGUI public or having a function at each stage of the
hierarchy to forward that pointer to the bottom level. This leads to
quite a lot of functions. Is this a necessary consequence of a UI with
a lot of knobs?
A given control shouldn't care what value it manages. It doesn't need to know whether the value determines the number of alien invaders on the screen or the coolant level in a nuclear reactor. It does needs to know things like the minimum and maximum values, label to display, scale to use (linear, log, etc.), and other things that directly impact the way the control works. It also needs to know who to tell when something changes, and it might need some way to identify itself.
With that in mind, ApplicationGUI doesn't need to expose accessors for every possible parameter of Application. Instead, it should have a general method that lets controls send it updates. When a control changes, it should send a message to ApplicationGUI containing the new value(s) along with its identifier, and ApplicationGUI takes care of mapping that identifier to some particular parameter of Application. A control's identifier could be some identifying number that's given to it, or it could just be a pointer to the control.
Of course, sometimes communication has to go the other way, too... a GUI usually has both inputs and outputs, so you'll want some means for ApplicationGUI to get updates from Application and update the state of the GUI. For the same reasons described above, Application should send those updates to ApplicationGUI and let the latter find the actual UI components that need to be changed.
I wasn't really sure how to search for this question.
I'm doing an embedded system design with the following scenario.
I have a main application class that needs to create a bunch of hardware interfaces such as a keypad, display, communication ports, etc... a whole slew of stuff
Now I have all these objets in the main application that I can use which is great
The application class contains a few sub classes that it can go into and stay for a while. One example is a menu class that it enters and runs inside that class until the menu is closed
I need the menu class to also interact with a lot of a hardware objects that were created at the application level
What is the best way to go about this without using global variables? Is there a good solution to this problem?
I could pass each object into the menu class, but I don't want to create a constructor with 20 arguments. My current solution is to put all the objects into a structure and pass that structure into the sub-class constructor. That way they also have access.
The part that bugs me about this approach is that I have to define the structure outside of the application which I don't really like. Something just keeps telling me it's not the best solution.
Open to any suggestions.
Presumably, there is ONE keypad - thus only one "Keypad Interface Object", right? Similarly with Display [ok, there may be two displays, but still].
So my suggestion would be to have a registration and a "container" that holds the registered interfaces something like this:
class KeyPad
{
public:
int getKeyPressed();
};
class Display
{
public:
OutputText(std::string msg);
};
... bunch of other stuff ...
class HardwareRegistry
{
priviate:
Keypad *keypad;
Display *display;
static HardwareRegistry *myself;
public:
Keypad* GetKeypad() { return keypad; }
Display* GetDisplay() { return display; }
void RegisterKeypad(Keypad *akeypad) { keypad = akeypad; }
void RegisterDisplay(Display *adisplay) { display = adisplay; }
static HardwareRegistry* GetHwRegistry()
{
if (!myself) myself = new HardwareRegistry;
ASSERT(myself); // If we don't have a pointer now, panic!
return myself;
}
};
Then you just have a Singleton Pattern to provide your HardwareRegistry, and register the devices as you create them during hardware initialization.
Of course, if you support different kinds of Keypads, Displays, etc, then you would implement those with a "interface baseclass", and the registry returns the KeypadBase type, for example.
So I have this MFC dialog program I am working with. The dialogs are written but now I am having difficulty passing data around from dialog to dialog. I have the following structure _dlgDataHandler set up in a class derived from CWinApp and have have created a "new" statement for a pointer to this type.
//.......SRK.h file
class CSRK_App : public CWinApp
{
public:
CFSB_App();
// added the following data structure for data passing withing the program
typedef struct _dlgDataHandler {
char RepetitionRadio[24];
// another member
// yet another member and so on as necessary
} *dlgDataHandlerPtr;
// extern dlgDataHandlerPtr dlgDataHandler;
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSRK_App)
public:
virtual BOOL InitInstance();
//}}AFX_VIRTUAL
// Implementation
//{{AFX_MSG(CSRK_App)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//....... SRK.cpp A pointer to a new dataHandler created in this block about 2/3 the way down
// CSRK_App initialization
BOOL CSRK_App::InitInstance()
{
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
//SetRegistryKey(_T("Local AppWizard-Generated Aplications"));
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
//CSRK_Dlg dlg;
CDialogMain dlg("SRK - Beta"); // added 12/27 **
m_pMainWnd = &dlg;
//const char* m_pszHelpFilePath = NULL;
//free((void*)m_pszHelpFilePath);
//m_pszHelpFilePath=_tcsdup(_T("c:\SRKHelp.rtf"));
// the following line added to allocate memory for the structure
dlgDataHandlerPtr dlgDataHandler = new _dlgDataHandler;
dlg.SetWizardMode(); // added 12/27 **
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}
In the dialog .cpp files, there are five, I need to be able to get data from the AFX variables "m_" and load them into this dataHandler Structure (or another one like it) so that they can be used in other dialogs and parts of the program, specifically my actual code when all the dialog data collection is done. Someone said to use AfxGetApp() so that I could have a handle on the current instance but I do not understand what they are talking about. And yes I have read about it in many forums, I just don't get it. I further realize this is probably not the best way to do it. I am trying to learn MFC/OOP with what time I have available, but for now, I am just trying to get a handle on the basic process as I can tune it later once I understand how to collect and pass simple data around.
I further don't understand how calling AfxGetApp() will help me get a handle on the members of CSRK_App. It inherited CWinApps public members but AfxGetapp() can't see what CSRK_App has... can it?
First, to explain the AfxGetApp advice you have received. There is some extra hand-waving using 'new' and a pointer, but this is basically using a global variable for the structure that holds your data. This is not the best way to do what you are trying to do. There are many pitfalls.
AfxGetApp() is an MFC call that returns a pointer to your main App class derived from CWinApp.
If you want to use that returned pointer, you need to cast it as a CSRK_App* pointer with:
CSRK_App* pApp = static_cast <CSRK_App*> ( AfxGetApp());
Then you can use pApp->dlgDataHandlerPtr->... to access the variables you need.
Now, for the pitfalls. Someone else may chime in with a reason why the 'new' and the pointer are helpful, but I do not see any advantage to this approach as compared to just having a local variable dlgDataHandler inside your CSRK_App class. That would simplify the code.
The next issue is that all your data is public in a struct. Any dialog class that can call AfxGetApp can read or write any data in that struct. You have no way to control access.
Also, all of your dialog classes must now include SRK_App.h so they know the structure, and have access to all other variables in that App class.
A cleaner, object-oriented approach would be to declare the struct (class) for the data in a separate .h file that could be included in the dialog classes. Then, you would pass a pointer/reference to this data into the constructor of the dialog classes. The dialog class would have no need to know anything about the App class.
For an even higher level of segregation, the dialog classes can be written so they only get a copy of the dlgDataHandler class passed in before calling .DoModal(), and then after the DoModal call returns with IDOK, the App class can have control over which data from the dialog gets updated into the dlgDataHandler class. The advantage of this approach is that it insures that no matter how the dialog class is programed, the user can always "Cancel" the dialog without modifying any data.