I play with Eclipse + wxWidgets + wxFormBuilder
I use wxFormBuilder for GUI-design. It generates 2 classes: first is base class; second inherits first to implement functionality like button clicks. But both of this files are regenerated every time I have changes in wxFormBuilder.
I wonder how to add some code to inherited class. For example, I have listbox, button and menu item. I want to do same action (add some string to listbox) when user presses button or selects menu item. For this reason I want to implement common function 'action'. I'll call this functuion in button and menu item handlers. Where I should declare this function and its implementation to avoid erasing manual code?
Thanks.
wxFormbuilder has the ability to generate a derived class for you. Located under Tools->Generate Inherited Class.
This code is only generated when you invoke this tool, so most probably only once. It is derived from the automatically generated class. You use this class and can implement your stuff inside of it.
So, the usual workflow is like this:
build your frame/panel in formbuilder
generate inherited class
implement your handling code in inherited class
make changes to form/panel in wxFormbuilder -> will only affect generated class, not inherited class
There is my own code generator for wxFormBuilder inherited classes which preserves manual code wxFUp455
Related
Background
I am woefully inexperienced with MFC and C++.
I have a set of dialogs that all have a small section with the same set of controls and extremely similar code.
I would like to separate that small section of controls from all dialogs move the code from all the dialog classes into a single class.
Problem
I'm not sure how to go about it. All my ideas all seem to have their own problems because I am so inexperienced.
Could I make a super class these dialogs inherit from that creates the controls dynamically given an (x, y) and that hooks up all the connections and communicates the few specifics through virtual methods?
The problem is I don't know the specifics:
Where would the super class inherit from? (CWnd? CDialog?)
Where would I create the controls in the super class? (OnInit? Constructor?)
Where would I initialize the super class in its subclasses? (OnInit? Constructor?)
Would I just have two message maps? One for the super class and one for the sub class?
Are there any other pitfalls I should watch out for?
The small section that you want to reuse can be an ordinary modeless dialog, derived from CDialog. You can create its controls with the resource editor - just like any other dialog - so they won't have to be created dynamically. The trick is to turn off the dialog's titlebar style (in the resource editor) so it will not be visually apparent that this section is a separate dialog. It will blend right in with the parent dialog.
For each place you want to reuse this dialog just create it and place it on the parent dialog with (x, y) coordinates using SetWindowPos.
I have created a traditional Qt (widget based) GUI, something like this: MainWindow::MainWindow(parent) : QMainWindow(parent)
This is designed by Qt Creator as forms (mainwindow.ui), aka Design Mode. Everything works fine. But the GUI code with all widgets, initializing the corresponding models, and functionality gets quit long. I'd like to refactor to small units. Things I came up with:
I tried using specialized (derived) widgets. Example: A created MyTableView::QTableView contains the specialized model, as well the signal/slot handling between model and widget. This reduces the amount of code in MainWindow. However, I do loose the capability to design the GUI via Qt Creator's Design mode.
The best thing I came up with so far, was to spilt the source code (multiple cpp files). It still represents one class, but less code in one file.
So, how could I better partition my GUI class?
If you still want to uncouple the initialization of widgets by derived widgets, you can use "promote to ..." option in Qt designer. Steps:
class MyTableView : public QTableView {}, and so initialization of table view is moved to the constructor of MyTableView.
In Qt Designer, open the ui form (MainWidow.ui), and drag and drop a QTableView on it;
Right mouse click the QTableView, in prompt menu, there's a "promote to" option, open it
In the dialog of "promoting widget", specify your custom QTableView's class name and header file, say MyTableView, MyTableView.h. This step requires existing custom class and header file.
Borrowed a picture:
You could create your own Qt widgets and register them with QtDesigner. Then will you be able to use them on forms as mere QLabels and friends. See this link
In a recent project, we had pretty restrictive uncoupling requirements (especially not to be too strongly linked to Qt). What we used to do based on MVC-like pattern is:
Implement a controller that controls the application workflow
Add a GUI "adapter" class per screen that communicates with the controller. Let's say HomeScreen class, SecondScreen class
Each adapter class contains a given number of widgets: TimelineWidget, FormWidget
Each widget is composed of a ui member (Ui::TimelineWidget ui) that is generated from a .ui file designd with Qt designer
Note that this structure might not be suitable for small projects.
I've derived a custom control from ATL::CWindowImpl<CMyCustomControl> and declared DECLARE_WND_CLASS(_T("CMyCustomControl")).
I've also made a dialog resource with a custom control with the class name CMyCustomControl.
How do I go about registering the control properly so I can display it on the dialog?
There are thre typical way to create custom controls in WTL.
DECLARE_WND_CLASS/DECLARE_WND_SUPERCLASS + RegisterClassEx API to register class by name + custom control reference in dialog template to instantiate control through class name
Implement window class, esp. inheriting from CWindowImpl, and create control manually, esp. from OnCreate/OnInitDialog
Implement window class, instantiate standard control through dialog template, and subclass the control instance to alter its behavior (e.g. static with hyperlinks, custom list view, edit control with color highlighting etc)
With all three you need to do more than just a macro in class definition. You will find great examples here: http://www.viksoe.dk/code/all_wtl.htm under "Controls" section.
Certainly the fourth method is implementing an ActiveX control.
I added a activex control to my MFC project, I don't use the dialog editor to add the control, I just used MFC to generate a wrapper class for the control, and call the "create" member in the wrapper class to create the control programmatically, the code is more or less like:
class CMyView
{
CCalendar m_ctl;
//other members.....
}
int CMyView::OnCreate
{
m_ctl.create("",WS_CHILD|WS_VISIBLE,this,CRect(50,50,100,100));
//.....
}
But I found that the wrapper class provide no way for me to change the control's property, so if I want to change the control's property programmatically, what should I do? Can I achieve this through a wrapper class? Or can it be done programmatically at all? Or is it only can be done via a dialog editor? Thank you.
Yes, wrapper only includes functions, if you create it via class wizard.
To change properties, i.e. variables, you could instantiate ActiveX in a form or a dialog and you would have the ability to modify values of properties in properties window.
If you want to do it on-the-run, you can right click to activeX object and then click on add variable. You will see that it will also create wrapper class for the object. This class will automatically include getters and setters for the activex, visible in the newly generated header file.
If you have already created a wrapper class for your activex, it may not work, try this in a fresh project. You can then copy generated .cpp and .h files to your own project afterwards.
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.