As we all know, including <windows.h> pollutes all namespaces in C++ by having one preprocessor #define per Win32 API function that can either take multibyte or UTF-16 input. An example is:
#ifdef UNICODE
#define CreateFont CreateFontW
#else
#define CreateFont CreateFontA
#endif
I’ve used the native Win32 API for quite a few years now, but I’m just about giving up! In any non-trivial project there are enough name collisions to make your face turn blue.
Please, oh please can someone come up with a solution which doesn’t require me to #undef such define macros on a case by case basis after the fact? I want to take affirmative action before this causes any bugs.
And I always use Unicode / UTF-16, so in the case of CreateFont, I would call CreateFontW directly in my code; I would not use the macro define. Is there someone who has a solution to this, like a complete header with #undef’s to wrap together with windows.h includes?
An example error that creeps up everywhere, is the fact that a generic name like “GetMessage()” is taken up.
font.cpp(78) : error C2039: 'GetMessageW' : is not a member of 'FontManager'
When all you want is your class to have a member function called void GetMessage().So frustrating.
The cleanest solution is not to call the Windows API functions directly in your program and instead to write an abstraction layer that can call the functions you need. This way, you only need to include the Windows API headers in a handful of source files and the macros are much more manageable.
This also has the added benefit of improving the portability of your code since only a small part of it will rely on the Windows API itself and all the rest of it will call your abstraction layer.
Even if you don’t care about portability, an abstraction layer still has a lot of benefits: your code will be easier to read and more maintainable because the complexity of making the API calls will be encapsulated in the abstraction layer (some of the Windows API functions have a lot of functions that you don’t usually care about).
Since you are using C++, an abstraction layer can also allow you to translate Windows API error codes into exceptions, if you prefer to use exceptions.
An abstraction layer also helps to make your code more easily testable (it’s a lot easier to mock your abstraction layer than it is to mock parts of or all of the Windows API).