Feature Comparison

team bbl


We continue with a selection of topics to show how MFC constructs can be ported to wxWidgets.

Application Initialization

Like MFC, a wxWidgets application is driven by an application class: wxApp instead of CWinApp. The CWinApp::InitInstance override is replaced by wxApp::OnInit, which returns a boolean value to indicate that the event loop should be started. Application cleanup is done in wxApp::OnExit instead of CWinApp::ExitInstance.

wxWidgets applications require the IMPLEMENT_APP declaration to be placed in the application class implementation file, for example:

 IMPLEMENT_APP(MyApp) 

MFC applications access the command line with the m_lpCmdLine string member of CWinApp (or GetCommandLine), whereas in wxWidgets, you access the argc and argv members of wxApp, which are in the same format as the parameters of the traditional C main function. To help convert your existing command-line parsing code, use the wxCmdLineParser class explained in Chapter 20, "Perfecting Your Application."

Message Maps

Where MFC has message maps, wxWidgets uses event tables. (wxWidgets can also route events dynamically, using a different syntax.) The principle of event tables should be immediately familiar to MFC programmers. Although message handler functions can have an arbitrary number of parameters, wxWidgets event handlers always take a single event argument, through which information can be passed in and out of the event handler. As with MFC, event tables can be placed in a window or in the application class, and in document and view classes when using the document/view framework. Let's compare an MFC message map with a wxWidgets event table. Here's the application class and message map in MFC (note that the class declaration and message map would normally be in separate files):

 // // MFC message map // class CDemoApp: public CWinApp { public:     CDemoApp();     // Overrides     virtual BOOL InitInstance(); // Implementation     afx_msg void OnAppAbout();     afx_msg void OnFileSave();     afx_msg void OnStretchMode();     afx_msg void OnUpdateStretchMode(CCmdUI* pCmdUI); // Attributes private:     int      m_stretchMode;     MyFrame *m_mainFrame;     DECLARE_MESSAGE_MAP() }; BEGIN_MESSAGE_MAP(CDemoApp, CWinApp)         ON_COMMAND(ID_APP_ABOUT, CDemoApp::OnAppAbout)         ON_COMMAND(ID_FILE_SAVE, CDemoApp::OnFileSave)         ON_COMMAND(ID_STRETCH_MODE, CDemoApp::OnUpdateStretchMode)         ON_UPDATE_COMMAND_UI(ID_STRETCH_MODE, OnUpdateStretchMode) END_MESSAGE_MAP() void CDemoApp::OnAppAbout() {     m_mainFrame->MessageBox(_T("Demo App (c) 2005"), _T("About Demo App")); } void CDemoApp::OnFileSave() {     CFileDialog fileDialog(false, _T("txt"), NULL, NULL, OFN_OVERWRITEPROMPT,       _T("Text files (*.txt)|*.txt"), m_mainFrame);     if (fileDialog.DoModal() == IDOK)     {         CString fullPath = fileDialog.GetPathName();         ...     } } void CDemoApp::OnStretchMode() {     m_stretchMode = !m_stretchMode; } void CDemoApp::OnUpdateStretchMode(CCmdUI* pCmdUI) {     pCmdUI->SetCheck(m_stretchMode);     pCmdUI->Enable(true); } 

In wxWidgets, the equivalent class declaration and event table are as follows:

 // // wxWidgets event table // class CDemoApp: public wxApp { public:     wxApp();     // Overrides     virtual bool OnInit(); // Implementation     void OnAppAbout(wxCommandEvent& event);     void OnFileSave(wxCommandEvent& event);     void OnStretchMode(wxCommandEvent& event);     void OnUpdateStretchMode(wxUpdateUIEvent& event); // Attributes private:     int      m_stretchMode;     MyFrame *m_mainFrame;     DECLARE_EVENT_TABLE() }; BEGIN_EVENT_TABLE(CDemoApp, wxApp)         EVT_MENU(ID_APP_ABOUT, CDemoApp::OnAppAbout)         EVT_MENU(CDemoApp::OnFileSave)         EVT_MENU(CDemoApp::OnUpdateStretchMode)         EVT_UPDATE_UI(ID_STRETCH_MODE, CDemoApp::OnUpdateStretchMode) END_EVENT_TABLE() void CDemoApp::OnAppAbout(wxCommandEvent& event) {     wxMessageBox(wxT("Demo App (c) 2005"), wxT("About Demo App")); } void CDemoApp::OnFileSave(wxCommandEvent& event) {     wxFileDialog fileDialog(m_mainFrame, wxT("Choose a file"),         wxEmptyString, wxEmptyString, wxT("Text files (*.txt)|*.txt")),         wxSAVE|wxOVERWRITE_PROMPT);     if (fileDialog.DoModal() == IDOK)     {         wxString fullPath = fileDialog.GetPath();         ...     } } void CDemoApp::OnStretchMode(wxCommandEvent& event) {     m_stretchMode = !m_stretchMode; } void CDemoApp::OnUpdateStretchMode(wxUpdateUIEvent& event) {     event.Check(m_stretchMode);     event.Enable(true); } 

As you can see, wxWidgets has an equivalent of MFC's user-interface updating, discussed in Chapter 9, "Creating Custom Dialogs."

Converting Dialogs and Other Resources

Resource Files

wxWidgets uses Windows RC files to include only a small number of essential resources, not for an application's dialogs and menus. Instead, wxWidgets has the XRC resource system, whose files can be written by a variety of commercial and open source dialog designers (refer to Appendix C, "Creating Applications with DialogBlocks," and Appendix E, "Third-Party Tools for wxWidgets"). You can also choose to have a designer tool generate C++ code to create the dialogs and menus.

With Windows resource files, most of an application's resources are bound with the executable (by linking the binary RES file). If you use wxWidgets' XRC files, you can load resources dynamically, or you can use the wxrc utility to convert your XRC files into a zip file, or C++ code that can be compiled into the application. However, bitmap files are not included in this process. You can consider converting small bitmaps to XPM files, which are supported on all platforms, or putting them in a zip archive with any other application files (refer to Chapter 20).

A wxWidgets application's RC file typically looks like this:

 aaaaaa ICON "myapp.ico" #include "wx/msw/wx.rc" 

The only purpose of the "aaaaaa" icon is to ensure that Windows shows the correct application icon in the Explorer, desktop, or Start menu. The name reflects the fact that the alphabetically first icon is used. The icon in your Windows resources is not generally used for setting a frame icon in wxWidgets application code. Instead, an icon is provided by loading XPM images into a wxIconBundle object and associating it with the window. You may want to edit icons in a bitmap editor capable of saving PNG files with transparency information and convert these files to XPM using an application such as Anthemion Software's ImageBlocks. For creating the application icon (myapp.ico), you can paste images into an icon editor, such as PC Magazine's IconEdit32.

Re-Creating the Dialogs

Faced with the task of converting many MFC dialogs, there is bad news, and there is good news. The bad news is that there is no way to fully automate the conversion. The good news is that there are tools to help make the task much easier, and the similarities between the wxWidgets API and the MFC API make conversions straightforward.

With a dialog editor (or RAD tool), you can rapidly re-create and surpass your MFC dialogs: your dialogs will be resizable, they will adapt to changes in label lengths due to translation, and they will adapt to controls of different sizes on different platforms. In addition, DialogBlocks has a resource import function that can do a first-pass conversion of RC-based dialogs into wxWidgets dialogs. Because these still use absolute positioning, it's recommended that you use the resulting dialogs only for reference and that you copy and paste the controls to a sizer-based dialog.

One possible strategy for converting your dialogs is to first re-create the dialogs visually, getting the UI appearance and resize behavior working and adding event handler "stubs." Then refer back to the MFC code and see how the existing message handlers can be adapted to the event handlers. The code will need to be changed, but in many cases, not by much.

Another strategy is to first rework your MFC code so that the user interface is separated from the functionality as far as possible. Write new classes encapsulating the desired functionality that are independent from toolkit-specific classes and invoke the new functions from the UI code, which should now be much simpler. Test that it works under MFC and then reuse the new classes inside your wxWidgets code. This method can work especially well if you have a period of transition where the MFC application must be maintained in parallel with the new wxWidgets port. Some #ifdef-ing will probably be required to deal with differences in data structure classes between the two toolkits.

Dialog Data Exchange and Validation

MFC employs a function DoDataExchange, a class CDataExchange, and DDX (dialog data exchange) functions such as DDX_Check to connect a data variable and the control. DDV (dialog data validation) functions are used to do validation. wxWidgets provides the virtual functions transferDataToWindow and transferDataFromWindow, but you don't normally need to implement these directly. You can use the more elegant concept embodied by the wxValidator class. To associate a variable with a control, you associate a validator with the control, for example:

 FindWindow(ID_TEXT)->SetValidator(wxTextValidator(& m_strText)); 

Now when the transferDataToWindow function is called (automatically from the default window initialization event handler), all controls call a function in the validator to transfer the data to the control. Similarly, when transferDataFromWindow is called (from the default wxID_OK event handler, for example), another validator function is called to transfer the data back from the control. A similar process happens for validation (checking for valid values), which is initiated by wxWindow::Validate.

So, use validators instead of DoDataExchange. Most of the time, the two built-in validators, wxTextValidator and wxGenericValidator, will suffice, but for special validation and transfer needs, you can write your own wxValidator-derived class or implement it within overridden transferDataToWindow and transferDataFromWindow functions.

Documents and Views

Broadly, the MFC and wxWidgets document/view mechanisms are very similar. These are some of the key differences:

  • Document manager: In wxWidgets, you need to create a wxDocManager object in your application initialization before you can start creating template objects. There is no equivalent in MFC.

  • Serialization: In MFC, documents may be loaded and saved by implementing the Serialize function. In wxWidgets, you can implement LoadObject and SaveObject, which take wxInputStream and wxOutputStream arguments. Just as with MFC, you can override OnOpenDocument and OnSaveDocument with file name arguments if you want to avoid using streams.

  • Views: In MFC, CView and its derivatives are window classes. In wxWidgets, wxView derives from wxEvtHandler, and you provide a window object separately. The view class manages the window object.

  • Command processing: Each wxDocument can contain a wxCommandProcessor object, which together with the wxCommand class helps an application implement undo/redo. MFC has no equivalent. This facility is optional.

Please refer to Chapter 19, "Working with Documents and Views," for more information.

Printing

In MFC, printing is tied to the CView class, and the application overrides functions in this class such as OnPrint, OnPreparePrinting, OnPrepareDC, OnBeginPrinting, and OnEndPrinting. In wxWidgets, printing is separated out from the document/view framework, and you derive from the wxPrintout class. Objects of this class are passed to the wxPrinter class to initiate printing or wxPrintPreview to initiate previewing. Override wxPrintout functions such as GetPageInfo, HasPage, OnBeginDocument, OnPreparePrinting, OnPrintPage and so on.

wxHtmlPrintout is a useful predefined printout class, controlled by the wxHtmlEasyPrinting class. This family of classes makes it straightforward to print simple HTML documents without requiring specific printing code to be added to an application.

String Handling and Translation

Replacing CString with wxString will work for most code, but if you find that too much conversion to wxString syntax is required, you could derive a class CString from wxString and emulate some of the missing functions.

Literal strings and characters that are enclosed in the _T macro don't have to be changed, but you have the option of using the synonym wxT.

A translated MFC application will normally have a different string table for each language. wxWidgets doesn't have string tables and instead uses message catalogs. A message catalog provides a mapping between the strings in the application and the strings in the target language. You can either implement your own system to store and load string tables, or you can convert your code to use message catalogs. If the latter, you could put quotation marks around the identifiers and use them as indexes into the message catalogs, or you could put the strings back into the application, such that no message catalog is required for the native language. Here are examples of two ways to use message catalogs:

 // Original MFC code to access IDS_WELCOME="Welcome!" CString str; str.LoadString(IDS_WELCOME); // wxWidgets solution (1) // "IDS_WELCOME" is replaced by a value in the message catalog wxString str(_("IDS_WELCOME")); // wxWidgets solution (2) // "Welcome!" is replaced by a value in the message catalog wxString str(_("Welcome!"));  

Database Access

If you currently use Data Access Objects (DAO), you might consider using the Windows-only wxDao library from Koan Software, which can be downloaded from http://www.koansoftware.com/it/prd_svil_wxdownload.htm.

You can also use ODBC directly or by using wxWidgets' wxODBC classes.

Configurable Control Bars

wxWidgets doesn't natively support toolbars and menu bars that can be repositioned and undocked, but you can use the third-party wxDockIt library (refer to Appendix E, "Third-Party Tools for wxWidgets") or the unsupported Frame Layout library in contrib/src/fl in your wxWidgets distribution. Other solutions are under development, so please see the Contributions page of the wxWidgets web site for the latest information.

    team bbl



    Cross-Platform GUI Programming with wxWidgets
    Cross-Platform GUI Programming with wxWidgets
    ISBN: 0131473816
    EAN: 2147483647
    Year: 2005
    Pages: 262

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net