The Regression of Flat UIs

Beauty is in the eye of the beholder, and I wholeheartedly prefer “classic” nice 3D colorful rich user interfaces to those “modern” flat bland UIs.

In other words, those “modern” flat UIs are a regression to me.

Just consider how nice is Visual Studio 2010’s UI if compared to the Visual Studio 2015’s one (you can click the screenshots to see them in full size):

Visual Studio 2010 and Windows 7 UI Style
Visual Studio 2010 and Windows 7 UI Style
Visual Studio 2015 Flat UI Style
Visual Studio 2015 Flat UI Style

Also Windows 7 icons (from the previous VS2010 screenshot) look much better to me than those dumbed-down bland icons of Window 10:

Windows 10 Flat Icons
Windows 10 Flat Icons

Don’t get me wrong: there are important improvements under the hood in Windows 10, and the Visual Studio 2015’s C++ compiler and standard libraries are better than those that ship with Visual Studio 2010, but this more recent UI look seems a regression to me.

To make everyone happy, why not just implementing a UI style theme selector, and providing both the “rich” and the “flat” styles, so that users can choose their favorite UI style?

 

The Chinese Dictionary Loading Benchmark Revised

Available here on GitHub.

[…] All in all, I’d be happy with the optimization level reached in #2: Ditch C++ standard I/O streams and locale/codecvt in favor of memory-mapped files for reading files and MultiByteToWideChar Win32 API for UTF-8 to UTF-16 conversions, but just continue using the STL’s wstring (or CString) class!

Unicode UTF-16/UTF-8 Encoding Conversions: Win32 API vs. C++ Standard Library Performance

In this MSDN Magazine article, I showed how to convert Unicode text between UTF-16 and UTF-8 encodings using direct Win32 API calls (in particular, I discussed in details the use of the MultiByteToWideChar API).

In addition to that, the C++ standard library offers some classes to perform such conversions.

For example, you can combine std::codecvt_utf8_utf16 with std::wstring_convert to convert from a UTF-16-encoded std::wstring to a UTF-8 std::string:

#include <codecvt>  // for codecvt_utf8_utf16
#include <locale>   // for wstring_convert
#include <string>   // for string, wstring

...
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conversion;
std::wstring utf16 = L"Some UTF-16 string";
std::string utf8 = conversion.to_bytes(utf16);

I developed some C++ code to convert many strings and measure the time spent for the conversions using the aforementioned C++ standard library classes vs. direct Win32 API calls, and the result is clearly in favor of the latter (code compiled with VS2015 in release build):

STL: 1050 ms

Win32: 379 ms  << — Clearly wins

 

MSDN Magazine article on Unicode Encoding Conversions with STL Strings and Win32 APIs

Another C++ article of mine was published on MSDN Magazine (in the 2016 September issue):

“Unicode Encoding Conversions with STL Strings and Win32 APIs”

Check it out!

Thanks to my editor Sharon Terdeman for her excellent editing work, and to my tech reviewers David Cravey and Marc Gregoire for their useful suggestions and feedback.

EDIT (2016-SEP-02): A Visual Studio solution containing C++ code based on this article can be found on GitHub here.

 

 

Conflicting overloads with STL’s wstring and ATL’s CStringW

If you want to overload a function with both STL’s wstring and ATL’s CStringW, you’ll end up with a compiler error:

#include <iostream>  // for cout
#include <string>    // for wstring
#include <atlstr.h>  // for CStringW

using std::cout;

void f(const std::wstring& ws)
{
    cout << "f(const wstring&)\n";
}

void f(const CStringW& cs)
{
    cout << "f(const CStringW&)\n";
}

int main()
{
    f(L"Connie");
}

VS2015 emits a message like this:

error C2668: ‘f’: ambiguous call to overloaded function
could be ‘void f(const ATL::CStringW &)’
or ‘void f(const std::wstring &)’
while trying to match the argument list ‘(const wchar_t [7])’

The problem is that the raw L”Connie” string (which is a “const wchar_t[7]”) can be used to initialize both an ATL::CStringW and a std::wstring, since both those string classes have a (non-explicit) constructor overload taking raw C-style NUL-terminated string pointers as input (i.e. “const wchar_t*”).

This ambiguity can be fixed providing another ad hoc overload for the error-generating function:

void f(const wchar_t* psz)
{
    cout << "f(const wchar_t*)\n";
}

Or maybe just try to stabilize your code on one string class, or just use functions with different names when you have to deal with both CStringW and wstring.