(This question is asked in the context of Win32API using the g++ compiler). I have a trouble with understanding why the following line of code won't work
wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
wndclass is an instance of the WNDCLASSEX structure, and the Windows API clearly specifies that the type of its member hbrBackground is HBRUSH. Further, HBRUSH is just a typedef for a HANDLE, which in turn is a typedef for void*. Hence, HBRUSH should be of type void*. Now, the GetStockObject function's return type is HGDIOBJ, which is also typedefed as a HANDLE, hence a void*.
Windows Data Types http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx
GetStockObject http://msdn.microsoft.com/en-us/library/dd144925(v=vs.85).aspx
WNDCLASSEX http://msdn.microsoft.com/en-us/library/windows/desktop/ms633577(v=vs.85).aspx
Why then do I get the following error upon compilation:
invalid conversion from 'HGDIOBJ {aka void*}' to 'HBRUSH' [-fpermissive]
If I explicitly cast the returned value from GetStockObject it works
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
Thank you for any help.
It's because implicit conversions from void*
are disallowed in C++ (unlike C).
Function
HGDIOBJ GetStockObject(int fnObject);
returns HGDIOBJ
which is defined as void*
:
typedef void NEAR* HGDIOBJ;
You are assingning it to HBRUSH which is a typedef
to pointer to struct
struct HBRUSH__;
typedef struct HBRUSH__ *HBRUSH;
(see windef.h
)
While such assignment works fine in C, in C++ you should explicitly cast :
wndclass.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
See: void pointers: difference between C and C++
As jensa noted in comments, the article Windows Data Types is wildly outdated. This is putting it mildly. I don't remember when it's happened exactly, but STRICT Type Checking
was enabled by default since decades. This article was probably written in the last century (a 20th one).
Here is the quote of the comment by yic81
from 10/7/2012
This article needs reviewing. When was it last reviewed? 15 years ago? The statement typedef HANDLE HINSTANCE; is totally incorrect, as many other typedef HANDLEs. Vast majority of them are now DECLARE_HANDLE() structs. Please review and fix this article. See this KB83456 http://support.microsoft.com/kb/83456 (last updated November 1999) for more details
You can also learn more about STRICT
and it's advantages here: STRICT Type Checking
And here is how it looks like in windef.h
:
DECLARE_HANDLE(HBRUSH);
And somewhere below DECLARE_HANDLE
defined as:
#ifdef STRICT
typedef void *HANDLE;
#if 0 && (_MSC_VER > 1000)
#define DECLARE_HANDLE(name) struct name##__; typedef struct name##__ *name
#else
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
#endif
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif
By default, we are using DECLARE_HANDLE
from line 6. With NO_STRICT
-- lines 9-10.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With