从HGDIOBJ转换为HBRUSH

Conversion from HGDIOBJ to HBRUSH

本文关键字:HBRUSH 转换 HGDIOBJ      更新时间:2023-10-16

(这个问题是在使用g++编译器的Win32API的上下文中提出的)。我很难理解为什么下面的代码行不起的作用

wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);

wndclass是WNDCLASSEX结构的一个实例,Windows API明确指定其成员hbrBackground的类型为HBRUSH。此外,HBRUSH只是HANDLE的一个typedef,而HANDLE又是void*的typedef。因此,HBRUSH应为void*类型。现在,GetStockObject函数的返回类型是HGDIOBJ,它也被类型化为HANDLE,因此是一个void*。

Windows数据类型http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx

GetStockObjecthttp://msdn.microsoft.com/en-us/library/dd144925(v=vs.85).aspx

WNDCLASSEXhttp://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);

谢谢你的帮助。

这是因为在C++中不允许从void*进行隐式转换(与C不同)。

功能

HGDIOBJ GetStockObject(int fnObject);

返回定义为void*:的HGDIOBJ

typedef void NEAR* HGDIOBJ;

您正在将其发送到HBRUSH,HBRUSH是指向structtypedef指针

struct HBRUSH__;
typedef struct HBRUSH__ *HBRUSH;

(见windef.h

虽然这样的赋值在C中很好,但在C++中,您应该显式地强制转换:

wndclass.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));

请参阅:void指针:C和C++之间的区别

编辑:

正如jensa在评论中指出的那样,文章"Windows数据类型"已经过时了。这是委婉的说法。我不记得具体是什么时候发生的,但STRICT Type Checking已经默认启用了几十年。这篇文章可能写于上个世纪(20世纪)。

以下是10/7/2012yic81的评论

这篇文章需要复习。上次审查是什么时候?15年前?语句typedef HANDLE HINSTANCE;完全不正确其他typedef句柄。其中绝大多数现在都是DECLARE_HANDLE()结构。请审阅并修复这篇文章。参见本KB83456http://support.microsoft.com/kb/83456(上次更新于1999年11月)更多详细信息

你也可以在这里了解更多关于STRICT及其优点:STRICT类型检查

以下是它在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++术语中,可以说GetStockObject返回一个GDIBase*,它需要转换为适当的派生类(例如,假定HBrushGDI)。因此,你必须打字。

class GDIBase;
class HBrushGDI : GDIBase;
GDIBase* GetStockObject(int);

HBrushGDI* pBrush;
pBrush = static_cast<HBrushGDI*>GetStockObject(WHITE_BRUSH);

它与从GetProcAddress返回的函数指针的类型转换相同。因此,将类型转换为适当的类型是安全的(假设您知道正确的类型)。