C++ GUI Programming for MS Windows

The previous post, Win32 or UWP? looked at some of the advantages and disadvantages of developing C++ applications for either of those two frameworks. This post provides a high-level look at a number of toolkits for GUI programming in C++ for those frameworks. I have no intention of covering all toolkits, only the ones I have used, or contemplated using for more than a few minutes. See Wikipedia for a larger list of GUI toolkits.

MS Windows-Only APIs and Toolkits

Microsoft has provided a number of toolkits and APIs for developing C++ applications on Win32 and UWP. The oldest ones are for Win32 development and the newest ones are for UWP. Because Win32 has been around a much longer time, there are more toolkits for developing Win32 applications than for developing UWP applications. Let’s look at a few.

Win32

Any mentions of Win32 in this post also refer to Win64, the 64-bit equivalent of Win32.

Windows API

The Windows API (sometimes referred to as Win32 API) is a C-based library that has been around since the days of Windows 1.0 (originally Win16). This was the first toolkit used to build Windows applications and still remains somewhat popular today, especially for C applications. However, being a C interface, it tends to be long-winded; for example, the first Hello World application built using Win16 required only 150 lines of code.

I would recommend looking at one of the C++ toolkits instead.

MFC

MFC, the Microsoft Foundation Classes, was released in 1992 as a very thin wrapper around the Windows API. MFC is still available in various versions of Visual Studio, though it was previously not included in Visual Studio Express versions.

While some people still develop applications using MFC, and of course there is a large number of legacy MFC applications, there are now better choices available for developing new applications.

WTL

WTL, the Windows Template Library, was developed originally for use internally by Microsoft, and was later released as an unsupported add-on to Visual Studio. WTL provides a light-weight alternative to MFC.

I have not used WTL so I can’t comment on it, other than it is now available as a download from Sourceforge.

Others

A number of other Win32-specific toolkits have come and gone. As an alternative to any of the toolkits mentioned above, you may wish to consider one of the cross-platform toolkits which are listed in a section below.

UWP

Universal Windows Platform is Microsoft’s new framework for building Windows programs. Unlike Win32, which is limited to running on x64/x64 processors, UWP applications can also be built to run on ARM processors. This opens UWP applications up to running on desktops, laptops, tablets, XBox systems, HoloLens systems, Windows phones, and any other hardware that runs Windows 10.

UWP uses the Windows RunTime architecture (WinRT). WinRT provides a set of APIs that expose all of the functionality of Windows 10 to developers. See the Wikipedia entry for more information. .Net and the Common Language Runtime (CLR) are a subplatform of the Windows Runtime.

C++/CX

C++/CX is a set of extensions to Visual C++ for building UWP applications. This greatly reduces the amount of plumbing code required to interface to WinRT, but at the expense of unfamiliar code syntax. All functionality exposed by WinRT can be programmed using C++/CX. C++/CX supports using XAML to define a program’s user interface.

WRL

The Windows Runtime C++ Library (WRL) provides a low-level interface to the Windows Runtime. There is more boiler-plate code than in C++/CX, but at least it is standard, though not modern C++. For example, there are no modern types and no move semantics.

C++/WinRT

C++/WinRT is a standard C++ language projection implemented entirely as a set of header files. It does not use language extensions like C++/CX does, and avoids the complexity, verbosity, and tediousness of WRL.

One disadvantage is that XAML is not currently supported; XAML will be provided in a later version.

Cross Platform Toolkits

All of the toolkits mentioned below have been under active development for 20 or more years. They were started before C++98; to support backwards compatibility, they all suffer from a number of limitations. For example:

  • No namespaces;
  • Use raw pointers rather than smart pointers; and
  • Pass parameters as raw pointers rather than references.

There are many other limitations, but you get the idea.

wxWidgets

wxWidgets is the only toolkit that uses native libraries to create and display windows and widgets. On Windows, wxWidgets uses Win32, on OSX it uses Cocoa, and on Linux and other Unix-like systems it uses gtk+. Attempts were made to produce ports for both Android and iOS, but they never got past the pre-alpha stage.

gtkmm

gtkmm is a C++ wrapper around gtk+. gtk+ is the C API that is used on the Gnome desktop for Linux and Unix-like operating systems. It has been ported to Windows and OSX, and generally works well but with a few limitations on the fringes. For example, see my comments about printing and printer properties in Adventures in Cross-Platform GUI Programming and Printing.

Qt

Qt is available for the largest number of operating systems: Win32 and WinRT, OSX, Linux and many Unix-like OSes, Android, iOS, and embedded operating systems. Qt is the API used for the KDE desktop which runs on Linux and many Unix-like OSes. It is the oldest and best supported of the cross-platform toolkits. It is under constant development.

fltk

The Fast Light Toolkit is the lightest of the toolkits mentioned here. It provides only GUI functionality and does not provide helper classes like the toolkits mentioned above. The look and feel of its widgets is somewhat reminiscent of Motif from the 1990’s.

fltk is available for Win32, OSX, and Linux.

Others

Other toolkits are either lesser known or created for specific purposes, such as toolkits for gaming and toolkits that use and are designed for use with OpenGL, and in some cases, Vulkan.

What Have I Used?

All of my programming in the last 3 years or so has been on MS Windows systems, with most programs using wxWidgets for the GUI. In the past, I programmed using gtkmm and the Win32 API. More than 20 years ago I used MFC. I have also programmed GUIs in other languages, but they are not the topic of this post.

Summary

This post has provided a list and overview of a number of toolkits that can be used to program GUIs on computers running MS Windows. Hopefully I have provided sufficient information for you to limit the amount of investigation you need to do to select a GUI toolkit that is appropriate for your new applications.

Additional Information

Additional information on each of the platforms and toolkits may be obtained from the following links:

 

 

 

Adventures in Cross-Platform GUI Programming and Printing

Starting about 12 years ago, I developed and maintained an application related to one of my hobbies. This application designed and printed cards with hobby specific information on them. One of my original criteria for the application was that it run on at least Windows and Linux. Prior to printing, I wanted to display a custom print properties dialog. So my priorities for a programming language and GUI library were:

  1. Must be OS-agnostic; that is, it must run on a number of different OSes, including at least Microsoft Windows and Linux. OS/X would be a bonus, but I didn’t have access to a Mac, so I couldn’t test it anyway.
  2. Must support printing, including the generation of a custom print properties dialog box. To produce the dialog box, values of certain printer properties must be retrieved from the printer driver.

Attempt #1

At that time, as now, Java, with Swing as the GUI library, was popular so I developed the application on a computer running Windows XP. It turned out quite well if I do say so myself. I was very happy with the result.

So now it was time to make sure it worked on Linux. Oops, the program cannot retrieve printer properties. So, I posted a bug report with Java. The response was that Java worked properly and the problem was with the printer driver, so I should contact the person or company that wrote the printer driver. At that time, I owned an HP printer, and HP creates Linux drivers for their printers. So, I contacted HP. Their response was that the driver worked properly, and the problem was therefore with Java.

Stalemate! Neither Sun Microsystems nor HP were willing to budge from their positions and actually determine the cause of the problem.

Attempt #2

Finding this situation unacceptable, I looked for another language and GUI library to redo the program. C# and WPF looked promising. Mono stated that they would be porting WPF to other OSes. Great. Even though WPF was available only on Windows, there was the promise that it would be available at a later date on Linux and other OSes.

I gave away about $250 worth of Java programming books and bought books to learn C# and WPF. I rewrote the application using C# and WPF. The application worked great on my Windows XP system, so I published it to the Internet. There were the usual bugs that come with programs, but in general, all was well.

Then the killer problem occurred. For one user, the program threw an exception while attempting to print. Are you starting to see a pattern here? Debugging on his computer showed that the exception was thrown every time the program attempted to retrieve the list of available fonts from the registry. A number of developers had reported this problem to Microsoft, but there was no fix because Microsoft employees could not reproduce the problem.

Luckily for me, another person had determined that the problem occurred whenever there was an invalid character in a font’s filename as stored in the registry. That person had developed a short program that would remove the bad font entry from the registry. I modified the program and forwarded it to my user with statements that it would probably work, but that I would not be responsible for any system problems that running the program might cause. Anyway, my user ran the program, and my application now worked. Out of more than 1000 users of my program, three people eventually had the font filename problem, all of which the program fixed.

Now back to seeing if I can port to Linux. The port of WPF to other systems was shelved by Mono, so I was stuck with a Windows-only program.

Attempt #3

There are some C++ GUI libraries that are available for a number of operating systems. These include gtkmm, Qt, and wxWidgets. I will have more to say about GUI libraries in a future post.

I decided to look into each of these libraries. I finally chose gtkmm and started to redevelop my application in C++ with gtkmm.

That adventure lasted until I found I was writing code like:

   for(const std::vector<std::string>::iterator iter = vec.cbegin(); iter != vec.end(); ++iter) {}

This was before C++11 and the auto keyword. I was forever trying to determine what the return type for templated class methods were. Seemed just too hard to get anything done.

Attempt #4

Since I had become somewhat familiar with gktmm, the C++ wrapper around the C-based gtk+ library, I tried C# with gtk#. gtk# is a C# wrapper around gtk+. Since I had read a number of times that it was easier to develop an application on Linux and then port it to Windows than it was the other way around, I again rewrote my application, but this time on Linux. Everything worked great.

Then I tried it on Windows. I couldn’t retrieve printer related properties from the printer driver. What worked on Linux did not work on Windows. So, I started to debug gtk+. Buried deep within the gtk+ code is a comment that retrieving these properties was not supported on Windows. Well thanks a lot!

So on to attempt #5. In retrospect, I probably could have kludged together something that would work on Windows, but at the time, I was not into writing operating system, or more properly, GUI window manager specific code. And, it should not have been necessary for a supposedly multi-platform library.

Attempt #5

I looked back at attempt #2. By this time I had given up on having a cross-platform application, so I could continue to use WPF as needed. One of the features of WPF is that it can be used alongside WinForms, with either WPF controls inside WinForms controls, or WinForms controls inside WPF controls.

To fix the font retrieval problem, which is specific to WPF, I had to modify the program to build and display the card using WinForms, and therefore to print the cards using the WinForms printing functionality.

I finally had a program that would work, all be it on Windows only.

I continued to develop and maintain the program for about three years after I had lost interest in its related hobby.

Moral of This Story

The moral of this story is to think at least twice before attempting to develop cross-platform applications that have any special print requirements. And, in fact, be very careful with printing in general.