X-Designer MFC Code Generation
Introduction
X-Designer generates MFC code for Windows. With the release of Windows 95 and Windows NT 4.0, the look
and feel of the windowing system changed to encapsulate client edge or three dimensional objects. X-Designer
has always had a solid foundation for MFC code generation and we hope that these tips will help you create
a better Windows Application.
Our MFC code generation is always under review and we appreciate any input that you would care to make
about functionality that would make your job easier. The generation of three dimensional objects is one of
the major improvements we wish to add to the product. In the meanwhile you can use the 3D tips outlined below.
Tell us what you would like to see by using our
enquiry form or
otherwise.
Go to top of this page
3D Components for Win 95 and NT 4.0
It is quite simple to create three dimensional objects pending the update to X-Designer - the basic create
function needs to be modified to an extended create. The extended create has a larger number of parameters,
but all the information you need is already there, it's just in a slightly different format.
An example to create 3-Dimensional Edit Controls:
Stage 1
- Create the Hierarchy Shell -> Form -> TextField
In the core resources dialog for both the Shell and the Form Set the structure to
"Children Only".
- Make the textfields structure a C++ Class, you can do this by opening the textfields
core resources panel and selecting the code generation page.
- On the same dialog and page, Enter:
Base Class : CEdit
Class Name : New3DEdit
<Whatever you would like to call the new class>
- Select Apply and Close.
- Set the variable name of the textfield to something other than the default.
- Ensure the textfield is selected and go to the widget menu and select
"definition".
The textfield should now have a highlight around it.
- Select the Palette menu and choose "Edit Definitions". With the textfield
still selected, click "Prime" and then "Update"
You should now notice a definition added to the palette.
Stage 2
- Generate a code and externs file for the definition from the generate dialog box which
will be used in the project file in the windows project.
Once the code has been generated, you will need to modify it. (Please note this is only
a single change that you will not need to do everytime you regenerate you main project
which uses the definitions).
- Open the code file and look for the call to the Create function
which should look like this:
Create (WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_BORDER,rect,parent,id);
You will need to change this to the extended create function:
CreateEx (WS_EX_CLIENTEDGE,"Edit","",WS_CHILD|WS_VISIBLE|WS_TABSTOP| WS_BORDER, rect.left, rect.top, rect.Width(), rect.Height(), parent->GetSafeHwnd(),(HMENU) id);
The only change that really needs to be noted here is the "Edit", this
tells MFC from which class this new class of ours is derived. So for example a 3D Client Edge
listbox would need to replace the "Edit" with "ListBox". The X-Y coordinates
of the object have been split into specific X-Y values as well, but as you can see you can
extract these from the variable rect easily enough.
Stage 3
When you have created your design within X-Designer, in which you have substituted the
standard textfield for the textfield definition you have created, you will need to generate
your code and move it across to the Windows platform.
You will also need to move your generated code from the definition across to the windows
machine to include in your C++ project file.
It is often best to set a Module prelude to include the header file for the definitions
code this way it means you do not have to edit the code manually when you have moved it
across the platforms.
- Select "Module"->"Module preludes..." Deselect the Edit in Place
toggle and then select the module prelude toggle held in the dialog.
Type: #include "<your header file>"
Stage 4
You should include all of the files you have generated in a new C++ project. Ensure that
you have set the C++ environment to use MFC (See the section on Configuring
different Visual C++ Versions or the X-Designer User's Guide for specific version
information) and make it.
For your convenience, we have created example files which are freely available for
download from our Web server, they encompass a number of classes in one file to make it
quicker and easier for you to use the definitions.
To get these 3D components example files, download
Example.tar.Z.
Go to top of this page
Compatibility issues with X-Designer 4.0.
If you are running X-Designer Version 4.0 then you will find that your MFC code will not build on
Visual C++ 4.x but will on all versions below Visual C++ 4.0, this is because Visual C++ 4.0 is NOT
backwards compatible.
This incompatibility has been resolved in X-Designer 4.5.
There are two ways to work-around the problem in earlier versions:
Your original code should look something like this:
void some_shell_c::create (CWinApp *win_app, CRect *in_rect)
{ ...
char xd_base_class[] = "AfxFrameOrView";
char xd_wnd_class = ...
Create ( xd_wnd_class, ...) ; ...
} ...
This is what you need to do:
void some_shell_c::create (CWinApp *win_app, CRect *in_rect)
/*The first workaround is to manually MODIFY AfxFrameOrView */
/* This needs to be edited so that the string is AfxFrameOrView40<x>
where <x> is some combination of the following letters,
depending on the flags the compiler is run with :
d debug
u unicode (for windows NT)
s static
*/
{
char xd_base_class[] = "AfxFrameOrView40<x>";
char xd_wnd_class = ...
/* Alternatively, you can MODIFY the first parameter in the
Create command to be <NULL> */
Create ( NULL, ...) ;
}...
Go to top of this page
Get the best layout with X-Designer
Form layout: The way the Motif form functions:
It starts at its leftmost (first) child, then runs down the list attempting to resolve
all attachments and positions down to absolute x, y, width, height values for all managed
children.
Any child which is not managed is not taken into account.
If, at the end of this pass, the form has not resolved all attachments to absolute
locations and sizes, it performs subsequent passes (up to 10,000 passes. If this arbitrary
limit is reached, the form stops attempting to resolve the attachments to avoid a potential
infinite loop).
This has the following implications when laying out a form:
The form will work best if you lay out the children starting from the top left of the
screen and work down towards the bottom right.
When you come to look at porting the form to MFC, you should note that the MFC system
does not have the sophisticated geometry management of Motif. So what X-Designer has to do
is to generate absolute x, y, width, height positions for the widgets, and then create
some geometry management using optional onsize handlers (which do little more than move
and resize widgets depending on how you laid out your form).
However, this has side effects:
Since the form doesn't take into account any children which are not managed when
performing geometry management, any children not managed at point of "generate"
are not necessarily going to have coherent size or positions reported. Hence you may end
up with strange effects for generated MFC of widgets which are initially unmanaged. This
can affect links where forms are managed/unmanaged to show or hide them respectively
within a design.
Since X-Designer is generating absolute values for MFC, it is very important that the
size of your dialog is as large as it needs to be (dynamic display) when you press the
generate button. Just by stretching out your dialog slightly you get different code.
This is the "generate-when-ready" feature.
However, note that if you have hidden portions of the interface and you manage these
in a Motif environment your dialog might grow to reflect the required size, or you might
as a user have to stretch the dialog out slightly to get the right size for the newly
managed widgets. This isn't an option in MFC. If you generate code with a dialog at a
specific size then arrange to manage a hidden portion you will not get the automatic
resize on the dialog because this has been generated with specific geometry.
The "OnSize" handler is for USER resize events - there's no event
propagation internally. So if the dialog isn't the right size to display some
portions of the interface when you hit the generate button, then you are going
to have some problems in the compiled MFC for these.
Therefore, if you have hidden portions, you should always temporarily manage
them to ensure the dialog finds its natural size, keep the size and then rehide
before generating. Then when you do show the hidden portion on MFC, your dialog
is able to handle it.
Resources dos and don'ts:
If you set margins, shadows, border sizes on objects explicitly in Motif you may
run into a few problems with MFC, these attributes do not map exactly to a Windows
equivalent. That is, you can end up with clipped or overlarge labels/pictures
depending on how you set the various attributes. This is because the fonts/images
as rendered on the Windows machine are not necessarily going to map to the same size,
and if you have forced some dimensions onto the object you can end up with poor
rendering.
In general therefore, you should try as much as possible to avoid all explicit
hard coded dimensions on widgets - let them find their natural size in Motif rather
than constraining them. This way, the hard coded values do not form part of the
generated code. About the only dimension you should consider setting explicitly
is the very top level width/height for the whole dialog.
Go to top of this page
Button manipulation in Motif and MFC
Buttons between the platforms are interpreted in different ways, for example if you use
a pixmap button on the Motif base a bitmap button is created within the MFC code. Bitmap
buttons use the whole pixmap as the face of the button and do not per se have a 3D
look and feel. This is something that is being examined for future MFC generation. In the
meantime, the best method to use for button representation is to have a pixmap associated
with the Arm callback i.e. when it's selected it can display a different pixmap which
includes shading that indicates shadow in or shadow out or even a different pixmap.
Making a button insensitive
Within X-Designer you can use the core resources of the button. Select the
settings tab, change sensitive to "No", this will actually create the
button as insensitive within the code generated.
This will generate the following lines in your code:
ac = 0;
XtSetArg(al[ac], XmNsensitive, FALSE); ac++;
<Create etc>
Re-enabling in Motif:
To change the button back to sensitive in your program you need to do the following:
Cardinal ac;
Arg al[1];
ac = 0;
XtSetArg(al[ac], XmNsensitive, TRUE); ac++;
XtSetValues(button1->xd_rootwidget(),al,ac);
Re-enabling in Microsoft MFC
You have to use one of the parent classes functions, i.e.
CWnd::EnableWindow;
To use this within your code to re-enable your button just type:
<button#n>->EnableWindow(TRUE);
e.g button1->EnableWindow(TRUE);
Go to top of this page
Removing the white background on the main application shell
The white background on the main application shell has been causing a number of problems
in presentation of the final application on the Windows platform. Some of the classes that
are used to display labels and 3D components rely on the background colour being the correct
"system" background colour and not the default for a CFrameWnd of White.
A temporary fix for this is to set the xd_wnd_class variable in the generated windows
code to "#32770" instead of NULL.
To demonstrate:
void shell1_c::create (CWinApp *win_app, CRect *in_rect)
{
CRect rect;
if ( in_rect )
rect = *in_rect;
else
rect.SetRect ( 0, 0, 358, 256 );
char *xd_wnd_class = "#32770";
^^^^^^^^^ Change to this from NULL.
m_bAutoMenuEnable = FALSE;
......
}
This solution works perfectly if you do not have any forms or toggle button managers
on the application shell. However, if you do, they will default to the shell's white
background colour. You can simply remove all of the calls associated with the
frame/toggle manager OnEraseBg message map. You need to remove the declaration
in the classes protected section in the ".h" file, the call in the message
map declaration in the main program and the function associated with the message map
in the main application.
This and a number of other problems have been resolved for the 5.0 release of
X-Designer.
Go to top of this page
My main application shell's background is transparent, why?
This will happen if you have specified an "icon pixmap" for the
application shell. X-Designer registers a new window class with the AfxRegisterWndClass
call. The third parameter of the call has been left out of the code generation. To
correct the mistake in the generated code, you can simply replace NULL with the line
(HBRUSH) COLOR_WINDOW.
For Example, change from this:
xd_wnd_class = AfxRegisterWndClass( CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, NULL, NULL, pixmap_resources.MyAppIcon_icon );
To This:
xd_wnd_class = AfxRegisterWndClass(
CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW,
NULL,
(HBRUSH) COLOR_WINDOW,
pixmap_resources.MyAppIcon_icon
);
Go to top of this page
Obtaining Tab Navigation in Dialog Shells
To obtain tab navigation in the dialog shells of your application, you can add the
following resource to the extended create of the dialog:
CreateEx ( WS_EX_CONTROLPARENT, xd_wnd_class, "shell1",
WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME,
rect.left, rect.top, rect.Width(), rect.Height(),
....)
Replacing the 0 that was originally used as the first parameter. This tab navigation
will only work for children of dialog shells, not for the main window.
Go to top of this page
Configuring different Visual C++ Versions
After copying your files to your Windows machine, follow these steps to build your
MFC project.
You can find this information in the Cross Platform Tutorial Chapter of the X-Designer
User's Guide.
Microsoft Visual C++ version 1.52
To create a new Project
- Choose New from the Project menu.
Press the Browse button in order to locate the directory containing the
X-Designer generated source files.
- At the prompt for the filename, type the name of your application with a
`.mak' extension.
This is the makefile, the file which identifies the project. It will be
created for you and updated as you add and delete source files.
Visual C++ creates other files for you too. If you want to know more
about the files Visual C++ wishes to create, look in the Visual C++
documentation.
Alternatively, if you wish to open an existing project, select Open...
from the File menu.
- Use the directory browser on the right to find the directory containing the
files generated by X-Designer. As you are creating a new project, Visual C++ will
ask you to specify the source files.
Check that the File Types list is set to request files of type `.c',
`.cpp' or `.cxx'.
- Press Add All to include all the sources in your project. Note that if you
give a `.c' extension, Visual C++ will not be happy if the file contains c++ code.
- Change the list of file types to `.rc' files. Add the resource file. Note
that Visual C++ will only accept one resource file. If you have more than one, you
should #include them in one file and add that file to the project.
- From the Options menu, choose Project.
Make sure that you have selected Use Microsoft Foundation Classes.
Press the Compiler button.
- Select Memory Model from the category list and choose Large.
This will ensure that the code segment will be large enough for your
application. If you experience problems consult your Visual C++
documentation.
- In the same dialog, select the Listing Files category, then from the
subsequently displayed dialog, deselect Include Local Variables and Browser
Information.
Doing this will speed up the compilation process.
- Press OK for these two dialogs.
- Finally, check that Visual C++ has been installed with the correct list
of directories to search for include files. Choose Directories from the Options
menu.
Make sure that you are including files from the current directory
(this is indicated by a `.'(period)). If the system files are not being
included you should refer to your Visual C++ installation manual.
- Having provided the details of your project, you may now build it. Select
"Build <projectname>.exe" in the Project menu or select the
Build button on the toolbar at the top of the Workbench window.
If this is the first time the project has been built, you will be asked
if you wish Visual C++ to create a definitions file for you. Select Yes.
Visual C++ will then produce a window for you to edit the definitions
file. You will not normally need to alter this file, so simply
close it.
- Select Build again. Visual C++ will ask you if you wish to build all
affected files. Select Yes. All the files you specified as being part of
the project are then built. The output from the compiler is displayed in
the output window.
Once the application has built successfully, you can try it out.
Select "Execute <projectname>.exe" from the Project
menu.
Go to top of this page
Microsoft Visual C++ version 2.0
- Go to File Menu and select "NEW"
- Enter the Project Name and the Sub-directory (if any) you want the
application to be created in
- Change the project type to "Application"
- Select "Create"
- Use the "Directories" search box to locate the directory in
which you have stored the files copied to the PC
- To include files in the project, either double click the filename or
highlight the filename and select "Add"
- To remove unwanted files from those you have included, select the
filename in the "files in group" box and select the remove
button or double click the filename
- Select "Close" and Visual C++ 2.0 opens the new project
- Before you can begin building you have to set the MFC toggle
- Open the Project menu:
- Go to "Settings"
- Select the drop down list for Microsoft Foundation Classes and choose
the "MFC Shared dll" option and select OK
- Select the Project menu
- Select Build "Your Application" or press [ALT][F8] together
Go to top of this page
Microsoft Visual C++ version 4.x
- Go to the "File" menu and Select "New"
- Select "Project Workspace"
- Select "Application" from Project Type and enter the name of the
application
- Move to the "Insert" menu, select "Files into project"
and use the dialog to locate your files
- Highlight the files required by clicking on the first in the list then
press shift and then click on the last of the files in the list
- Select the "OK" button
- Go to the "Build" menu and select settings
- Change the "Microsoft foundation class" option menu so it
uses shared dll
- Go to the "build" menu again
- Select "Build <Your project name>" or press [F7] from
the development area
Go to top of this page
Microsoft Visual C++ version 5.x
- Go to the "File" menu and select "New"
- Select the "Projects" tab of the dialog
- Select "Win32 Application" from the list of available
options and enter a project name
- Go to the "Project" menu and select "Add to
Project", then select "Files"
- Highlight all the files by clicking on the first in the list then
press shift and then click on the last of the files in the list
- Select the "OK" button
- After adding the files, select the "Project" menu again
and select "Settings"
- Change the "Microsoft Foundation Class" option menu so
it uses shared dll.
- Go to the "Build" menu
- Select "Build <your project name>" or press [F7]
from the development area
- You can run your application using ALT and F5
|
 |