(此问题是在使用 g++ 编译器的 Win32API 上下文中提出的)。 我无法理解为什么以下代码行不起作用
wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
wndclass是WNDCLASSEX结构的实例,Windows API明确规定 它的成员 hbrBackground 的类型是 HBRUSH。此外,HBRUSH 只是 HANDLE 的类型定义,而 HANDLE 又是 void* 的类型定义。因此,HBRUSH 应该是 void* 类型。 现在,GetStockObject 函数的返回类型是 HGDIOBJ,它也被类型定义为 HANDLE,因此是 void*。
Windows 数据类型 http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx
获取股票对象 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
为什么编译时会出现如下错误:
invalid conversion from 'HGDIOBJ {aka void*}' to 'HBRUSH' [-fpermissive]
如果我显式转换 GetStockObject 的返回值,它就可以工作
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
感谢您的帮助。
最佳答案
这是因为 void*
的隐式转换在 C++ 中是不允许的(与 C 不同)。
函数
HGDIOBJ GetStockObject(int fnObject);
返回定义为void*
的HGDIOBJ
:
typedef void NEAR* HGDIOBJ;
您正在将其分配给 HBRUSH,它是指向 struct
的指针的 typedef
struct HBRUSH__;
typedef struct HBRUSH__ *HBRUSH;
(参见 windef.h
)
虽然这样的赋值在 C 中工作得很好,但在 C++ 中你应该显式地强制转换:
wndclass.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
参见:void pointers: difference between C and C++
编辑:
正如 jensa 在评论中指出的那样,文章 Windows Data Types 已经过时了。这是委婉的说法。我不记得具体是什么时候发生的,但是 STRICT Type Checking
几十年来一直默认启用。这篇文章大概写于上个世纪(20世纪)。
这里引用 yic81
来自 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
您还可以在此处了解有关 STRICT
及其优势的更多信息:STRICT Type Checking
下面是它在 windef.h
中的样子:
DECLARE_HANDLE(HBRUSH);
在 DECLARE_HANDLE
下面的某处定义为:
#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
默认情况下,我们使用第 6 行的 DECLARE_HANDLE
。使用 NO_STRICT
-- 第 9-10 行。
关于c++ - 从 HGDIOBJ 到 HBRUSH 的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26815415/