Rare Historical Photos, And the story behind them…

Rare Historical Photos, And the story behind them…

Conrad Schumann was immortalized in this photograph as he leapt across the barricade that would become the Berlin Wall. The photo was called “The Leap into Freedom”. It became an iconic image of the Cold War.

Born in Zschochau, Saxony during the middle of World War II, he enlisted in the East German state police following his 18th birthday. Since he had always shown himself to be a loyal and hardworking young citizen of the German Democratic Republic, local military officials offered him an elite position in the paramilitary Bereitschaftspolizei or BePo (“riot police”), which was specifically conceived to suppress rebellion.

On 15 August 1961, the 19-year-old Schumann was sent to the corner of Ruppiner Strasse and Bernauer Strasse to guard the Berlin Wall on its third day of construction. At that time, the wall was only a low barbed wire fence. At the same spot, on the West Berlin, was standing the 19 year old photographer Peter Leibing. For more than an hour, Leibing stood watching the nervous young non-commissioned officer as he paced back and forth, his PPSh-41 slung over his shoulder, smoking one cigarette after another. “Come on over, come on over!” (Komm’ rüber!) the West Berlin crowd on Bernauer Strasse chanted. “He’s going to jump!” one passerby remarked. And at four p.m. on August 15, 1961, Leibing got lucky. Schumann tossed aside his cigarette, then turned and ran for the coil of barbed wire that marked the boundary between East and West. He jumped, flinging away his gun as he flew, and Leibing clicked the shutter. A nearby newsreel cameraman captured the same scene on film.

Immediately Schumann was driven away from the scene by the West Berlin police. Then he was brought to a local police station, where he requested a liverwurst sandwich and yet another cigarette. After a thorough interrogation, Schumann was handed a plane ticket for Bavaria – a place as far away from the GDR as he could get. Later he ended up as a winery worker in Bavaria.

www. is not deprecated

www. is not deprecated

Ever since the first traditional media ads began to appear with Web site addresses in them almost 20 years ago, people have been screwing them up. And unless you just got on the Internet yesterday, you’ve almost certainly done the same, and know many people who have as well.

Almost no one knew what http://www.pepsi.com/ meant at the bottom of that TV ad. Those who did almost certainly had mixed feelings about it. Until 1994 commercial activity on the Internet had been prohibited; when this prohibition was lifted many people feared the inevitable commercialization of the net. In hindsight, they were right. Now commerce runs rampant. Overall, though, this isn’t a bad thing. Sure, there are banner ads and spam, but the Internet also brought us Linux and eBay.

The thing is, in 1996 almost everyone on the Internet knew how to type in a URL. Now, in 2016, almost no one knows. They guess, and the browser makes its best attempt to find what the user had intended. Back then, virtually everyone dutifully typed http://www.pepsi.com/ into Mosaic or Netscape to see just what it was that Pepsi had put online. These days, many people will just type in http://www.pepsi.com or even pepsi.com or, believe it or not, just pepsi.

More people than you realize will take a URL, go to their favorite search engine, and type the URL into the search engine’s search field, never realizing they can actually edit the contents of the address bar above, or perhaps not even noticing it. I’ve even seen a few pathological cases where, given a URL, they will type http://www.google.com or another search engine into the address bar, and then type the URL they actually want to go to into Google’s search field!

I paint this bleak picture primarily for the benefit of Internet veterans who have been around the block a few times and actually understand a fairly good deal about how the technology underlying the Internet works, and who don’t deal with “normal” users on a regular basis. If my description of “normal” users above surprised, shocked or disappointed you, you’re the target audience.

What does all this have to do with www. in URLs?

Remember that some people always use it, some don’t, and some only use it if it was in the URL they were given. The source of this confusion is the simple fact that users today don’t understand two things. First, they don’t understand why the www. is (or isn’t) there, and second, they don’t understand that the Web is not the whole of the Internet.

The main non-technical reason I argue for leaving the www. in URLs is that it serves as a gentle reminder that there are other services than the Web on the Internet. Some of these, such as FTP and DNS, users typically use transparently without even realizing it. Others, such as e-mail, users access through separate applications. Even so, I know of many users who will claim with a straight face that e-mail is not part of the Internet.

The ultimate goal here is to reach at least a few of these people and turn some of the lights on in their heads.

(Technical reasons to use www are available as well.)

Please note that I am in complete agreement with the no-www people that a domain’s main Web site should be accessible through both example.com and http://www.example.com. I argue, however, that http://www.example.com is the preferred form and that users going to example.com should be redirected to http://www.example.com.

van Bevern propiedades

van Bevern propiedades

URUGUAY IM ÜBERBLICK

Ländername: República Oriental del Uruguay (= Republik östlich des Uruguay)
Fläche: 176.220 km² (etwa halb so groß wie die Bundesrepublik Deutschland)
Einwohner: 3,3 Mio. Ew. (fast 50 % davon leben in der Hauptstadt Montevideo)
Klima: gemäßigt-warm
(durchschnittlich + 25 Grad im Sommer und + 10 Grad im Winter)
Landessprache: Spanisch
Währung: Peso (allerdings große Akzeptanz von US-$ und Euro)
Telefonvorwahl: 00598

ALLGEMEINE INFOS

Uruguay ist geprägt von einer flachwelligen, von Flüssen durchzogenen Hügellandschaft.

Wegen seines Wasserreichtums bietet das saftige, grüne Grasland zusammen mit dem gemäßigt-warmen Klima ideale Bedingungen für Land-, Forst- und Viehwirtschaft. So dient das Weideland größtenteils der Rinder- und Schafzucht, während die Ackerflächen für Mais, Soja und Sonnenblumen bzw. für den Weinanbau genutzt werden. Weit mehr als 80 % der Landesfläche ist agrartauglich.

Immerhin realisierte dieser Sektor im Jahr 2005 ein Wachstum von rd. 11 % und trägt mit einem Anteil von 60 % wesentlich zum Export bei, vor allem mit Fleisch sowie auch Leder.

Deutschland gilt als Exportland Nr. 4 nach Brasilien, Argentinien und USA und ist damit wichtigster, europäischer Handelspartner.

Uruguays Rindfleisch hat hervorragende Qualität, denn das Vieh profitiert ganzjährig von dem frischen Weidegras. Hinzu kommt, dass Uruguay bis heute frei von Maul- und Klauenseuche und BSE geblieben ist.

Ebenfalls erwähnenswert und sicherlich zukunftsträchtig ist der Weinanbau, für den es hier die idealen klimatischen Bedingungen – Wärme, Licht und Niederschlag – gibt. Führend in Uruguay ist die Tannat-Rebe, eine widerstandsfähige, taninreiche Traube, die extraktbetonte, robuste, schwarzrote Weine mit Pflaumenaroma und teils Himbeerduft ergibt.

Der Anbau von Eukalyptusbäumen in der Forstwirtschaft dient der Herstellung von Zellulose und Ölen.

Allgemein lässt sich sagen, dass Uruguay ein typisches Einwanderungsland ist. Die Einwohner sind überwiegend spanischer und italienischer Abstammung. Kultur, Bildung und Lebensweise sind daher sehr europäisch geprägt.

Das Land weist keine außergewöhnlich hohe Kriminalität auf und gilt als eines der sichersten Länder Südamerikas.

Qt Documentation

Qt Documentation

Getting Started Guides
What’s New in Qt 5
Qt Licensing
Examples and Tutorials

Qt Reference Documentation
Development Topics
Supported Platforms
Qt Tools
Qt Cloud Services

Officially Supported Platforms
Qt for Device Creation
Emulator
Qt Charts
Qt Quick Extras
Qt Quick Compiler
Qt Data Visualization
Qt Purchasing
Qt Virtual Keyboard
Qt Quick 2D Renderer

Qt Creator
Qt Designer
Qt Linguist
Qt Assistant
Qt Installer Framework
Build Tools: qmake
Build Tools: Qbs
Build Tools: CMake
Qt Visual Studio Add-in

MFC to Qt Migration – Walkthrough

MFC to Qt Migration – Walkthrough

MFC contains a checkpoint-based memory leak detection mechanism. This mechanism does not handle well Qt’s system of allocating global static objects. The result is that when running applications that combine Qt and MFC (like the examples below) from within Visual Studio, one will get a report about leaked objects upon application exit. These warnings can safely be ignored.

Getting Started

Load the project file qtmfc1.dsp into a Workspace in Visual Studio and make sure that everything is set up correctly by building and running the project.

The MFC application has an interface to use dialogs provided by an external DLL that will be explicitly loaded. The interface is fairly simple: the DLL must export a C function called showDialog that can take a window handle parent. The DLL must show its dialog modally, and when the function returns the DLL is unloaded again.

The code that does this in the MFC application is in the OnAppAbout command handler.

 void WindowsApp::OnAppAbout()
 {
     HMODULE mod = LoadLibrary( "qtdialog.dll" );
     if ( mod ) {
         typedef BOOL(*pShowDialog)(HWND parent);
         pShowDialog showDialog = (pShowDialog)GetProcAddress( mod, "showDialog" );
         if ( showDialog )
             showDialog( theApp.m_pMainWnd->m_hWnd );

         FreeLibrary( mod );
     } else {
         CAboutDlg aboutDlg;
         aboutDlg.DoModal();
     }
 }

If the DLL can be loaded and exports the showDialog symbol the exported function is called, otherwise a default MFC about dialog is displayed.

Plugin extension

The project in the qtdll example directory implements the plugin interface using the QMessageBox class. To use this class a QApplication object must exist in the current process, and the Qt events must be processed in addition to the standard event dispatching performed by the running MFC application.

The DLL also has to make sure that it can be loaded together with other Qt based DLLs in the same process (in which case a QApplication object will probably exist already), and that the DLL that creates the QApplication object remains loaded in memory to avoid other DLLs using memory that is no longer available to the process.

All these issues are handled by the QMfcApp::pluginInstance() function. This function creates a QApplication object and installs a message hook that merges the Qt event loop with the existing standard Win32 message pump of MFC. If an instance to the DLL is passed as a parameter the function will also increase the DLL’s reference count so that it is not unloaded before the process exits.

This function can be used in an implementation of the DllMain entry point function when the DLL is loaded. A static bool variable is used to remember whether this DLL is responsible for the QApplication object, and when the DLL is unloaded the QApplication object, accessible through the global qApp pointer, can be deleted.

To use the function and the other Qt classes involved we also need to include a few header files.

 #include <qmfcapp.h>
 #include <qwinwidget.h>

 #include <QtGui/QMessageBox>
 #include <windows.h>

 BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpvReserved*/ )
 {
     static bool ownApplication = FALSE;

     if ( dwReason == DLL_PROCESS_ATTACH )
         ownApplication = QMfcApp::pluginInstance( hInstance );
     if ( dwReason == DLL_PROCESS_DETACH && ownApplication )
         delete qApp;

     return TRUE;
 }

The DLL interface is then implemented using an exported C function called showDialog. The QWinWidget class is used to provide the proper placement and stacking of the Qt dialog.

 extern "C" __declspec(dllexport) bool showDialog( HWND parent )
 {
     QWinWidget win( parent );
     win.showCentered();
     QMessageBox::about( &win, "About QtMfc", "QtMfc Version 1.0\nCopyright (C) 2003" );

     return TRUE;
 }

Linking against Qt

To use Qt classes directly in the MFC application we must link the application against the Qt libraries, and add the location of the Qt header files to the compiler’s include directories.

The step2 directory includes a .pro file that generates a proper .dsp file that has all the required settings. Run c{qmake -tp vc} in the directory to generate that .dsp file, and check the settings necessary in case you want to modify the Visual Studio project manually.

Replacing the MFC event loop

To be able to use Qt, we need to create a QApplication object. The QApplication class controls the event delivery and display management for all Qt objects and widgets.

In the original MFC project the wizard generated WindowsApp class, a subclass of CWinApp, runs the event loop in the default implementation of Run(). The MFC event loop is a standard Win32 event loop, but uses the CWinApp API PreTranslateMessage() to activate accelerators.

In order to keep MFC accelerators working we must use the QApplication subclass QMfcApp that is provided by the Windows Migration framework and which merges the Qt and the MFC event loops.

The first step of the Qt migration is to reimplement the Run() function in the WindowsApp class. We can either use the wizard to add a reimplementation of Run(), or add the reimplementation ourselves to the class declaration in the qtmfc.h header file:

 class WindowsApp : public CWinApp
 {
 public:
         WindowsApp();

 // Overrides
         // ClassWizard generated virtual function overrides
         //{{AFX_VIRTUAL(WindowsApp)
         public:
         virtual BOOL InitInstance();
         virtual BOOL Run();
         //}}AFX_VIRTUAL

 // Implementation

 public:
         //{{AFX_MSG(WindowsApp)
         afx_msg void OnAppAbout();
         //}}AFX_MSG
         DECLARE_MESSAGE_MAP()
 };

The implementation of this function is in the qtmfc.cpp source file. To use the QMfcApp API we need to #include the qmfcapp.h header file.

 #include "stdafx.h"
 #include "qtmfc.h"

 #include "mainframe.h"

 #include <qmfcapp.h>

 BOOL WindowsApp::Run()
 {
     return QMfcApp::run( this );
 }

The implementation uses the static run() function of the QMfcApp class to implicitly instantiate a QApplication object, and run the event loops for both Qt and MFC:

The code in the plugin DLL does not need to be modified: Since we have a QApplication object created in the application itself the pluginInstance() function will do nothing, and the DLL will open the message box in the exported function just like before.

Replacing a Dialog

Instead of using the Qt plugin DLL we will now replace the MFC About Dialog directly in the application source code. Using the Visual Studio integration toolbar we could quickly create a new QDialog with Qt Designer from scratch. Or convert the existing dialogs from Microsoft resource files into Qt Designer .ui files by using a conversion tool such as KDAB’s KNUT tool. But for a basic dialog as the one in this example, it is even easier to use the QMessageBox::about() function as we did in the plugin code shown earlier.

 #include "stdafx.h"
 #include "qtmfc.h"

 #include "mainframe.h"

 #include <qmfcapp.h>
 #include <qwinwidget.h>
 #include <QtGui/QMessageBox>
To use the QMessageBox API we must include the appropriate header. Since we need to create the QMessageBox as a child of the MFC based main window we also need to use the QWinWidget class again and include that header as well.

 // WindowsApp message handlers

 // App command to run the dialog
 void WindowsApp::OnAppAbout()
 {
     QWinWidget win( theApp.m_pMainWnd );
     win.showCentered();
     QMessageBox::about( &win, "About QtMfc", "QtMfc Version 1.0\nCopyright (C) 2003" );
 }

We can remove the class declaration and implementation of the CAboutDlg class from the source file, and use the QWinWidget and QMessageBox API in the implementation of the WindowsApp::OnAppAbout() command handler.

A QWinWidget object is created on the stack, using the MFC application's main window as the parent window. The showCentered() API is used to make sure that the Qt message box, which uses the QWinWidget object as its parent, will open centered over the main window.

New Functionality with Qt

We can now add new functionality to the MFC application using Qt. We will add a Qt based user interface to the MFC child view, and add an additional modeless options dialog created with Qt Designer.

Creating Qt widgets

To be able to create Qt widgets in the initialization of the MFC application we must first create an instance of QApplication. The current use of the static QMfcApp::run() API creates the QApplication object in the Run() reimplementation of the CWinApp subclass, while the GUI is already being created in the InitInstance reimplementation.

 BOOL WindowsApp::InitInstance()
 {
         // Standard initialization

 #if _MFC_VER < 0x0700
 #ifdef _AFXDLL
         Enable3dControls();                     // Call this when using MFC in a shared DLL
 #else
         Enable3dControlsStatic();       // Call this when linking to MFC statically
 #endif
 #endif

         // Change the registry key under which our settings are stored.
         SetRegistryKey(_T("Local AppWizard-Generated Applications"));

         // Qt initialization
         QMfcApp::instance(this);

         MainFrame* pFrame = new MainFrame;
         return true;
 }

To create the QApplication object in the InitInstance implementation we must use the static function QMfcApp::instance().

 BOOL WindowsApp::Run()
 {
     int result = QMfcApp::run(this);
     delete qApp;
     return result;
 }

QMfcApp:run() will then use that instance, which must then be deleted explicitly using the global qApp pointer.

MFC's window creation infrastructure is rather complicated, and we must add a message handler for the WM_CREATE and WM_DESTROY messages to be able to add children only when the creation of the MFC window is complete, and to delete the children before the MFC window is destroyed.

 // ChildView window

 class QWinWidget;

 class ChildView : public CWnd
 {
 // Construction
 public:
         ChildView();
 ...
         // Generated message map functions
 protected:
         //{{AFX_MSG(ChildView)
         afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
         afx_msg void OnDestroy();
         afx_msg void OnPaint();
         //}}AFX_MSG
         DECLARE_MESSAGE_MAP()

 private:
         QWinWidget *widget;
 };

We can again use Visual Studio's wizards, or simply add the code ourselves. We also add a forward declaration of the QWinWidget class, and add a pointer to that class as a member of the ChildView.

 #include "stdafx.h"
 #include "qtmfc.h"
 #include "childview.h"

 #include <qwinwidget.h>
 #include <QtGui/QLabel>
 #include <QtGui/QLineEdit>
 #include <QtGui/QLayout>
We include the headers for the Qt widget we want to use, as well as the header for the QWinWidget class.

 ChildView::ChildView()
 : widget( 0 )
 {
 }

We initialize the pointer to the QWinWidget member to zero. We cannot create it yet, since the MFC window has not yet been created. This happens only when the MainWindow::OnCreate() message handler calls the Create function, which then calls our ChildView::OnCreate implementation.

 BEGIN_MESSAGE_MAP(ChildView,CWnd )
         //{{AFX_MSG_MAP(ChildView)
         ON_WM_CREATE()
         ON_WM_DESTROY()
         ON_WM_PAINT()
         //}}AFX_MSG_MAP
 END_MESSAGE_MAP()
The message handlers are added to the message map.

 int ChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
 {
     if (CWnd::OnCreate( lpCreateStruct ) == -1 )
         return -1;

The implementation of the OnCreate message handler calls and verifies the parent class function and returns an error code if an error occurred.

     widget = new QWinWidget( this );
     QHBoxLayout *hbox = new QHBoxLayout( widget );

     QLabel *label = new QLabel( "Enter text:", widget );
     QLineEdit *edit = new QLineEdit( widget );
     hbox->addWidget( label );
     hbox->addWidget( edit );

     widget->move( 0, 0 );
     widget->show();

     return 0;
 }

Now we can create the QWinWidget instance with this CWnd instance as a parent window, and use that instance as a parent to the QWidgets we want to use to create the user interface. Since QWinWidget is a proper QWidget it can be laid out, and we move the Qt GUI to the upper left corner of the MFC child and show() the user interface immediately.

 BOOL ChildView::PreCreateWindow(CREATESTRUCT& cs)
 {
         if (!CWnd::PreCreateWindow(cs))
                 return FALSE;

         cs.dwExStyle |= WS_EX_CLIENTEDGE;
         cs.style &= ~WS_BORDER;
         cs.style |= WS_CLIPCHILDREN;
         cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
                 ::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL);

         return TRUE;
 }

Since the ChildView class of MFC was not supposed to be a container for other windows we now see some bad flickering whenever we resize the main window. The QLabel widget is obviously painted over by the ChildView window on every resize before it has a chance to fill its own background. To prevent this we must change the style of the window to include the CS_CLIPCHILDREN flag.

 void ChildView::OnDestroy()
 {
     delete widget;
     widget = 0;

     CWnd::OnDestroy();
 }

In the OnDestroy message handler we delete the QWinWidget instance, which deletes all other QWidgets we have created as children.

A new Qt Dialog

To add a new dialog we use the Visual Studio integration toolbar's "New Qt Dialog" button. We add a Qt Designer .ui file "optionsdialog.ui" to the current project, and add the required build steps to generate a C++ class from that file.

MFC projects have the precompiled header option turned on by default, and since Qt or Qt Designer cannot rely on the compiler used supporting precompiled headers the respective preprocessor directives are missing from the generated .cpp files. We must turn the precompiled headers option off for those files, but we can just as well turn them off for the complete project.
To be able to invoke the dialog we add a new entry to the MFC menu using the Visual Studio resource editor. The menu entry is called "Options", and has the ID ID_EDIT_OPTIONS.

 class WindowsApp : public CWinApp
 {
 public:
  ...
 // Implementation

 public:
         //{{AFX_MSG(WindowsApp)
         afx_msg void OnAppAbout();
         afx_msg void OnAppOptions();
         //}}AFX_MSG
         DECLARE_MESSAGE_MAP()
 };

We add a command handler for that option to the WindowsApp class and add the mapping to the message map. We also include the generated header file.

 #include <qmfcapp.h>
 #include <qwinwidget.h>
 #include <QtGui/QMessageBox>
 #include "ui_optionsdialog.h"

 BEGIN_MESSAGE_MAP(WindowsApp, CWinApp)
         //{{AFX_MSG_MAP(WindowsApp)
         ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
         ON_COMMAND(ID_EDIT_OPTIONS, OnAppOptions)
         //}}AFX_MSG_MAP
 END_MESSAGE_MAP()

The implementation of the command handler once again uses the QWinWidget class to make sure that the dialog is properly positioned and stacked. Since we want the dialog to be modeless we cannot create the QWinWidget on the stack, since it would be deleted when it leaves the scope, and all its children, including the dialog, would be deleted as well.

 void WindowsApp::OnAppOptions()
 {
     QWinWidget *win = new QWinWidget(theApp.m_pMainWnd);
     win->showCentered();

     QDialog *dialog = new QDialog(win);
     Ui::OptionsDialog ui;
     ui.setupUi(dialog);
     dialog->setAttribute(Qt::WA_DeleteOnClose);
     dialog->show();
 }

Instead we create QWinWidget on the heap, using operator new, and use the WDestructiveClose widget flag when creating the dialog as a child, also with operator new.

Both the QWinWidget object and the modeless dialog will be destroyed when the dialog is closed, e.g. when clicking the OK button.

Removing MFC

We will now turn the complete MFC/Qt hybrid application into a genuine, multiplatform Qt application. To make our application compilable with different compilers for different platforms we need to remove the dependency on Visual C++ and Visual Studio, and replace the Visual Studio project file with a qmake project.

Using the Qt build system

The project file lists all the sources involved.

 TEMPLATE = app
 TARGET   = QtMfc4

 DEFINES -= UNICODE
 DEFINES += _AFXDLL WINVER=0x0500
 QMAKE_LIBS_QT_ENTRY =

 HEADERS = childview.h mainframe.h qtmfc.h stdafx.h
 SOURCES = childview.cpp mainframe.cpp qtmfc.cpp stdafx.cpp
 FORMS   = optionsdialog.ui
 RC_FILE = qtmfc.rc

 include(../../../src/qtwinmigrate.pri)

Until we have completed the transition we must still link against the Windows Migration Framework, compile the Visual C++ resources, set the preprocessor define to pull in the MFC DLL, and turn off UNICODE to avoid library conflicts with the non-UNICODE MFC version. We must also remove the qtmain library which implements the WinMain entry point function to call the multiplatform main entry point.

Running qmake -tp vc on the .pro file will generate a new .dsp file that we can use in Visual Studio to compile and link the application.

Replacing the ChildView

The first MFC class we will move over to Qt is the ChildView class. We replace the old class declaration with the declaration of a QWidget subclass.

 #ifndef CHILDVIEW_H
 #define CHILDVIEW_H

 #include <QtGui/QWidget>

 class ChildView : public QWidget
 {
 public:
     ChildView(QWidget *parent = 0);

 protected:
     void paintEvent(QPaintEvent *);
 };

 #endif

We don't need any creation and destruction message handlers anymore, and the QWinWidget member is obsolete as well. However, we will keep an event handler for paint events as in the original class.

 ChildView::ChildView(QWidget *parent)
 : QWidget(parent)
 {
     QWidget *widget = new QWidget(this);
     QHBoxLayout *hbox = new QHBoxLayout(widget);

     QLabel *label = new QLabel("Enter text:", widget);
     QLineEdit *edit = new QLineEdit(widget);

     hbox->addWidget(label);
     hbox->addWidget(edit);

     widget->move(0, 0);
     setBackgroundRole(QPalette::Base);
 }

 void ChildView::paintEvent(QPaintEvent * /*e*/)
 {
     QPainter painter(this);
 }

The implementation of the class creates the user interface elements directly in the constructor and sets the erase color property to white. The paintEvent does nothing, at least for now.

Replacing the MainFrame

The next MFC class we will move over to Qt is the MainFrame class. We could use Qt Designer to generate a main window in a visual environment, but it's just as easy to add the few elements manually.

 #ifndef MAINFRAME_H
 #define MAINFRAME_H

 #include <QtGui/QMainWindow>

 class ChildView;

 class MainFrame : public QMainWindow
 {
     Q_OBJECT
 public:
     MainFrame(QWidget *parent = 0);

 protected Q_SLOTS:
     void editOptions();
     void helpAbout();

 private:
     ChildView *view;
 };

 #endif

The class implements the constructor, and keeps a reference to the ChildView object. The Q_OBJECT macro is used to allow this class to declare signals and slots. We add two slots, editOptions and helpAbout.

 MainFrame::MainFrame(QWidget *parent)
 : QMainWindow(parent)
 {
     QMenu *filePopup = menuBar()->addMenu("&File");
     filePopup->addAction("&Exit", this, SLOT(close()));

     QMenu *editPopup = menuBar()->addMenu("&Edit");
     editPopup->addAction("&Undo", 0, 0, Qt::CTRL + Qt::Key_Z);
     editPopup->addSeparator();
     editPopup->addAction("Cu&t", 0, 0, Qt::CTRL + Qt::Key_X);
     editPopup->addAction("&Copy", 0, 0, Qt::CTRL + Qt::Key_C);
     editPopup->addAction("&Paste", 0, 0, Qt::CTRL + Qt::Key_V);
     editPopup->addSeparator();
     editPopup->addAction("&Options...", this, SLOT(editOptions()));

     QMenu *helpPopup = menuBar()->addMenu("&Help");
     helpPopup->addAction("&About QtMfc...", this, SLOT(helpAbout()), Qt::CTRL + Qt::Key_F1);

     view = new ChildView(this);
     setCentralWidget(view);

     statusBar();
 }

The implementation of the class creates the menu, instantiates the ChildView as the central widget, and adds a status bar.

 void MainFrame::editOptions()
 {
     QDialog *dialog = new QDialog(this);
     dialog->setAttribute(Qt::WA_DeleteOnClose);
     Ui::OptionsDialog ui;
     ui.setupUi(dialog);

     dialog->show();
 }

 void MainFrame::helpAbout()
 {
     QMessageBox::about(this, "About QtMfc", "QtMfc Version 1.0\nCopyright (C) 2003");
 }

The slot implementations are identical to the application command handlers in the Qt/MFC hybrid, but of course don't need to use the QWinWidget class anymore.

Replacing the MFC application

The final step is to remove the WindowsApp class completely, and handle the application startup and initialization in a multiplatform main entry point function.

 TEMPLATE = app
 TARGET   = QtMfc5

 SOURCES += childview.cpp mainframe.cpp qtmfc.cpp
 HEADERS += childview.h   mainframe.h
 FORMS   += ../step4/optionsdialog.ui
 RC_FILE = qtmfc.rc

We can delete the qtmfc.h header file and remove it from the HEADERS section in the qmake .pro file. We can also remove the linking against the Migration Framework library, and the modifications of the preprocessor symbols.

Then we rerun qmake to regenerate the .dsp file. Since we added the Q_OBJECT macro to the MainFrame class declaration we have to make sure that the meta object compiler, moc, is added to the build step for the MainFrame class, and this is also done when running qmake.

The qtmfc.cpp file is completely replaced.

 #include <QtGui/QApplication>
 #include "mainframe.h"

 int main(int argc, char **argv)
 {
     QApplication app(argc, argv);

     MainFrame frame;
     frame.show();

     return app.exec();
 }

All it does now is to include the required headers, and to implement a standard main entry point function.

Cleaning up

Finally we edit the resource script (with a plain text editor, Visual Studio is too powerful for this) and remove the obsolete entries. The only entry we keep is the application icon.

IDR_MAINFRAME ICON DISCARDABLE "res\\QtMfc.ico"
Now we can delete the files that are no longer needed:

StdAfx.h, StdAfx.cpp, qtmfc.h, res/qtmfc.rc2, resource.h
The code we have now does the same job as the MFC based code, is much smaller, has less files to maintain and will compile with different compilers for different platforms.