c++ - 从 HGDIOBJ 到 HBRUSH 的转换

标签 c++ winapi g++

(此问题是在使用 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/

相关文章:

c++ - 用于纹理上传的OpenGL PBO,无法理解一件事

c - 将字符串发送到另一个应用程序的最简单方法是什么? (赢得API)

linux - 遗留系统上新 libstdc++ 中的段错误

c++ - Windows中的管道句柄如何关闭? (_pclose() 的 fclose())?

c++ - 连接 Haskell 和 C++

linux - G++:链接器似乎没有正确链接

c++ - 这里需要 `std::move` 吗?

c++ - 按值排序的 std::find 和 std::any_of

c++ - matlab 内置函数是用某种低级语言编写的吗?

winapi - Windows 关闭时,VB 6.0 系统托盘应用程序无法正常关闭