Throwing MFC Out of Windows

For years, Qt has advertised itself as a better MFC than MFC. Thanks to the Qt 4 Visual Studio Integration, it is now easier than ever for a Windows developer to develop cross-platform, high-performance C++ graphical user interface applications from his favorite IDE.

For years, Qt has advertised itself as a better MFC than MFC.
Thanks to the Qt 4 Visual Studio Integration, it is now easier than
ever for a Windows developer to develop cross-platform,
high-performance C++ graphical user
interface applications from his favorite IDE.

Qt is a C++ application development framework developed by
Trolltech, a Norwegian software company. While Qt mainly focuses on
enabing the development of graphical user interfaces, it also
provides excellent support for networking, multithreading,
SQL operations (including "i">ODBC), XML, and "i">Unicode.

For Windows developers, Qt offers the following advantages:

*Enhanced
C++performance.
Qt is written in C/C++ (with parts in
assembly language) and is highly-optimized to minimize memory usage
and maximize speed. Applications based on Qt are native, compiled
C++ applications that outperform those applications developed with
Java and C#.

* "b">Stability. Since its introduction in 1995, Qt has been
actively developed and maintained by Trolltech. The current
version, Qt 4.1, was released in December
2005 and supports advanced features, such as semi-transparent
controls, antialiased drawing, and bidirectional text
rendering.

*Ease of
use.
Qt has a clean, object-oriented, C++ design, and
provides a powerful signal and slot
mechanism similar to C#’ s events and delegates. Signals and
slots are flexible, fully object-oriented and implemented in C++
through a separate tool called moc (the meta-object compiler).

* "b">Portability. Qt provides a uniform application
programming interface for Microsoft Windows, from "i">Windows 98 to Windows XP, Mac OS X,
Linux, Solaris, HP-UX, IRIX, AIX,
and many other
Unix variants. Qt’s” write once,
compile everywhere” philosophy lets you develop applications on
Windows and deploy them later on other platforms.

Internally, Qt emulates the various platforms’ controls
using platform-specific APIs such as GDI+
and the Windows XP theming engine. This enables Qt to accurately
reproduce the look-and-feel of each supported platform, and allows
programmers to extend or customize Qt’s built-in controls by
re-implementing virtual functions. It’s even possible to
implement a custom style to give all controls a custom
look-and-feel, and to distribute it as a plug-in.

Although Qt is cross-platform, it includes a few
Windows-specific modules, notably an MFC-to-Qt migration framework
and a COM/ActiveX integration (to create and embed ActiveX
controls). Today, Qt is used by companies as diverse as AT& T,
IBM, NASA and Xerox, and mass-market applications such as Adobe
Photoshop Album and Google Earth are developed using it. In
addition, the open source edition of Qt is the foundation of KDE,
one of the two major Linux/Unix desktop environments.

Overview of the Qt 4 Visual Studio
Integration

The Visual Studio integration, introduced with Qt 4.0, takes
advantage of Visual Studio’s highly extensible architecture
to make C++ application development on Windows faster, easier, and
more intuitive than ever before. The integration includes the
following features:

*Fully
integrated form editor with layout support.
Since version
2.2, Qt includes a powerful visual user interface design tool
called Qt Designer, with support for
automatic layouts and dynamic, XML-based user interfaces. The
integration encapsulates Qt Designer in Visual Studio, with Qt
properties displayed in the standard Property Browser (see
Figure One).

*Wizards for
creating new Qt projects.
The wizards let you specify the Qt
modules you want to use and generate skeleton classes to get you
started (see Figure 2).

*Automated
build setup for Qt-specific build steps.
Qt includes three
tools that generate C++ code behind the scenes: "i">moc (the meta-object compiler), "i">uic (the user interface compiler), and "i">rcc (the resource compiler). These are invoked
automatically by the integration when necessary.

*An integrated
resource management system.
Adding new resources to a Qt
project is comparable to adding resources to a standard C++
project. The main difference is that cross-platform "i">.qrc files (Qt resource files) are used rather than
Windows .rc files.

*Integrated Qt documentation.
Qt’s comprehensive API documentation is integrated with the
Visual Studio online help (see Figure
Three
).

A Regular Expression Tester

To illustrate how the Visual Studio integration works,
let’s create a very small application to let the user try a
regular expression against a string. The application, depicted in
Figure Four, is a dialog box with three
QLabels, three "i">QLineEdits, and two QPushButtons.
The user can enter a regular expression pattern and some text on
which the regular expression is run; the part of the text that
matches is shown in the bottom-most QLineEdit.

The first step is to create a skeleton project. Invoke the New
Project dialog in Visual Studio and click the Qt Projects folder
(see Figure Five). Next, select the Qt
Application item and type” RegExpTexter” as the project name. This
pops up the wizard shown in Figure Two.

The wizard includes a page to specify which Qt modules you want
to link against, followed by a page that enables you to specify the
name of the skeleton class to be generated by the wizard. For this
example, change the base class of the generated class so that
it’s QDialog, not QMainWindow, because the application is a
simple dialog-style application with no menus or toolbars.

We’ll now design the dialog using the integrated Qt
Designer form editor. To invoke the form editor, we click on the
regexptester.ui file in the Visual Studio Solution Explorer. Then
we drag the controls we need from the Qt Toolbox onto the form and
position them approximately as shown in Figure 6. (Qt’s
layout system will lay them out precisely later on.)

The next step is to edit the controls’ properties using
the Property Browser. Table One lists the
properties that need to be set.

TABLE ONE:
Setting the controls’
properties
Control Property Value
First label ObjectName “patternLabel”
Text “Pattern:”
Second label ObjectName “textLabel”
Text “Text:”
Third label ObjectName “resultLabel”
Text “Result:”
First line edit ObjectName “patternLineEdit”
Second line edit ObjectName “textLineEdit”
Third line edit ObjectName “resultLineEdit”
Editable false
First button ObjectName “resetButton”
Text “Reset”
Second button ObjectName “closeButton”
Text “Close”

You need to add layouts to the form to make it look better and
to make it resizable. First, add a horizontal layout to position
the Reset and Close buttons side by side. You also need a spacer to
push the buttons to the right of the layout. To add a spacer, drag
the Vertical Spacer item from the Qt Toolbox onto the form, next to
the push buttons. Then select the spacer and the buttons and click
Form Editor|Layout Horizontally from the Qt entry in the menu
bar.

The entire window also needs a layout that will take care of
positioning the other controls as well as the button sub-layout. To
add this layout, select the labels, the line edits, and the button
layout, then click Form Editor& gt; Layout in a Grid. This
gives the form shown in Figure Seven.

Qt’s layouts automatically assign reasonable positions and
sizes to the controls they are responsible for, based on their
needs. This is especially useful in internationalized applications:
With fixed sizes and positions, the translation text is often
truncated; with layouts, the child widgets are automatically
resized. Layouts can also run right-to-left, to accommodate
languages such as Arabic and Hebrew.

You can click Form Editor& gt; Preview Form at any time to
preview the form without compiling it. If you build the application
now, the result is the dialog depicted in Figure
Four.

However, the dialog is inoperative. Let’s start by making
the Close button work. You can connect the button’s
clicked() signal to the form’s
accept() slot. This can be done through the
form editor.

1.Click the Edit Connections
toolbar button to enter the connection mode.

2.Click the form’s Close
button and hold the left mouse button pressed, then move the cursor
to an empty area of the form and release the mouse button (see
Figure Eight). This invokes the Configure
Connection dialog, which lists the available signals and slots.

3.Choose the "c">clicked() signal and the accept()
slot and click OK.

Qt controls emit” signals” when state changes take place, for
example when the text changes in a line edit, or when a new item is
selected in a list box. These signals can be” connected” to slots
(member functions), so that when a signal is emitted, any slots it
is connected to are called. Controls that are connected to one
another are independent components since they don’t need to
know anything about each other.

If you build and run the application now, the Close button
closes the window and causes the application to terminate.

More Fun With Dialogs

Let’s continue and implement the rest of the dialog
functionality. The contents of the Result line need to be updated
whenever the user edits the text in one of the two other line
edits. This is achieved by adding a slot called "c">updateResult() to the form and by connecting the two
line edits’ textChanged() signals to
that slot. The signals are emitted whenever the text changes; the
connection ensures that the slot is invoked to recompute the Result
line edit’s contents based on the new text in the Pattern and
Text fields.

For that, you must edit the "i">regexptester.h and "i">regexptester.cpp files that were generated by the Qt
Application wizard. Listing One shows the
header file after adding the slot declaration. Notice the
particular syntax for declaring a slot; this is Qt-specific and is
converted into standard C++ by the C++ preprocessor.

LISTING ONE:
The form’s header file

#ifndef REGEXPTESTER_H
#define REGEXPTESTER_H

#include <QtGui/QDialog>
#include “ui_regexptester.h”

class RegExpTester : public QDialog
{
Q_OBJECT

public:
RegExpTester(QWidget *parent = 0, Qt::WFlags flags = 0);
~RegExpTester();

private slots:
void updateResult();

private:
Ui::RegExpTesterClass ui;
};

#endif // REGEXPTESTER_H

The RegExpTester class inherits from
QDialog (the class you specified in the
project wizard) and represents the entire dialog.

The first unusual thing to notice about the class definition is
the Q_OBJECT macro. This signifies that the
class has some Qt extensions to C++ that will be discussed shortly.
The private slots are private member functions that can also be
called by Qt’s signals and slots mechanism.

The header file includes a file called "i">ui_regexptester.h. That file is generated by the
uic program based on the "i">regexptester.ui, an XML file that stores the form we
designed using the form editor. The uic-
generated ui_regexptester.h file declares a
class called Ui::RegExpTester. In the
private section of the RegExpTester class,
there is a member variable of type "c">Ui::RegExpTester called ui.

The updateResult() slot needs to be implemented and connected to
the Pattern and Text line edit’s textChanged() signals. This
is done in the regexptester.cpp file, listed in "i">Listing Two. Again, the code that needs to be added to
the wizard-generated skeleton is shown in bold.

LISTING TWO:
The form’s source file

#include “regexptester.h”

RegExpTester::RegExpTester(QWidget *parent, Qt::WFlags flags)
: QDialog(parent, flags)
{
ui.setupUi(this);
connect(ui.patternLineEdit, SIGNAL(textChanged(QString)),
this, SLOT(updateResult()));
connect(ui.textLineEdit, SIGNAL(textChanged(QString)),
this, SLOT(updateResult()));
}

RegExpTester::~RegExpTester()
{
}

void RegExpTester::updateResult()
{
QRegExp regExp(ui.patternLineEdit->text());
if (regExp.indexIn(ui.textLineEdit->text()) != -1)
ui.resultLineEdit->setText(regExp.cap(0));
else
ui.resultLineEdit->setText(“<no match>”);
}

The constructor calls setupUi() on the
Ui::RegExpTester object to create the
form’s controls and layouts. Then, the Pattern line
edit’s textChanged() signal is
connected to the updateResult() slot. The
same is done with the Text line edit.

In the updateResult() slot, the regular
expression pattern is applied to the specified text. If the regular
expression matches, the matched text is shown in the Result line
edit; otherwise, it shows”& lt;no match& gt;”.

The dialog is almost fully functional. The only remaining issue
is that the Reset button still does nothing. The solution is to add
a reset() slot and connect it to the Reset
button’s clicked() signal in the
constructor. The slot is implemented as follows:

void RegExpTester::reset()
{
    ui.patternLineEdit->clear();
    ui.textLineEdit->clear();
    updateResult();
}

This completes the small sample application. But what about
Q_OBJECT, private slots, and other Qt
keywords? The C preprocessor turns them all into pure C++ so the
compiler never sees them. The machinery to handle Qt’s
extensions is generated behind the scenes by "i">moc, which reads your source files and generates some
additional source files to implement what we’ve used.

Goodbye, MFC

Microsoft is giving up MFC and is preparing to replace its
successor, Windows Forms, with the Avalon framework. The
uncertainty surrounding these three APIs has alienated many Windows
developers, who are now looking at Qt as a more stable
alternative.

With the Qt 4 Visual Studio Integration, a Windows developer can
easily leverage his or her existing C++ skills to develop
cross-platform, high-performance object-oriented, GUI
applications.

Jasmin Blanchette is documentation manager at
Trolltech AS in Oslo, Norway, and co-author of C++ GUI Programming
with Qt 3. He graduated in computer science in 2001 from the
University of Sherbrooke, Quebec, Canada. He can be reached at
"emailaddress">jasmin.blanchette@trolltech.com. For more
information about Qt, go to class="story_link">http://www.trolltech.com/ or contact
class="emailaddress">info@trolltech.com.

Fatal error: Call to undefined function aa_author_bios() in /opt/apache/dms/b2b/linux-mag.com/site/www/htdocs/wp-content/themes/linuxmag/single.php on line 62