IST  

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

  1. Choose New from the Project menu.

    Press the Browse button in order to locate the directory containing the X-Designer generated source files.

  2. 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.

  3. 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'.

  4. 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.

  5. 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.

  6. From the Options menu, choose Project.

    Make sure that you have selected Use Microsoft Foundation Classes. Press the Compiler button.

  7. 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.
  8. 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.
  9. Press OK for these two dialogs.

  10. 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.

  11. 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.
  12. 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

  1. Go to File Menu and select "NEW"
  2. Enter the Project Name and the Sub-directory (if any) you want the application to be created in
  3. Change the project type to "Application"
  4. Select "Create"
  5. Use the "Directories" search box to locate the directory in which you have stored the files copied to the PC
  6. To include files in the project, either double click the filename or highlight the filename and select "Add"
  7. 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
  8. Select "Close" and Visual C++ 2.0 opens the new project
  9. Before you can begin building you have to set the MFC toggle
  10. Open the Project menu:
  11. Go to "Settings"
  12. Select the drop down list for Microsoft Foundation Classes and choose the "MFC Shared dll" option and select OK
  13. Select the Project menu
  14. Select Build "Your Application" or press [ALT][F8] together

Go to top of this page


Microsoft Visual C++ version 4.x

  1. Go to the "File" menu and Select "New"
  2. Select "Project Workspace"
  3. Select "Application" from Project Type and enter the name of the application
  4. Move to the "Insert" menu, select "Files into project" and use the dialog to locate your files
  5. 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
  6. Select the "OK" button
  7. Go to the "Build" menu and select settings
  8. Change the "Microsoft foundation class" option menu so it uses shared dll
  9. Go to the "build" menu again
  10. Select "Build <Your project name>" or press [F7] from the development area

Go to top of this page


Microsoft Visual C++ version 5.x

  1. Go to the "File" menu and select "New"
  2. Select the "Projects" tab of the dialog
  3. Select "Win32 Application" from the list of available options and enter a project name
  4. Go to the "Project" menu and select "Add to Project", then select "Files"
  5. 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
  6. Select the "OK" button
  7. After adding the files, select the "Project" menu again and select "Settings"
  8. Change the "Microsoft Foundation Class" option menu so it uses shared dll.
  9. Go to the "Build" menu
  10. Select "Build <your project name>" or press [F7] from the development area
  11. You can run your application using ALT and F5

Top of Page COPYRIGHT ©1995-2017 IST Reading Ltd. ALL RIGHTS RESERVED Legal Info | Privacy | Contact Us