C++ 如何最好地封装窗口句柄?

C++ 如何最好地封装窗口句柄?,c++,opengl,encapsulation,direct3d,hwnd,C++,Opengl,Encapsulation,Direct3d,Hwnd,我正在开发一个由许多独立子系统组成的系统。其中两个子系统是Window和GraphicsAdapter子系统 GraphicsAdapter需要一个低级窗口句柄(HWND或X11窗口句柄,具体取决于操作系统),窗口子系统是抽象这些特定于操作系统的API的一种方法 如果窗口子系统允许访问低级API句柄,那么封装就有可能被破坏 如果它允许windows全屏显示和返回,但必须触发事件来警告系统这些更改,并且在它不知情的情况下使用低级句柄切换到全屏显示,该怎么办 我如何确保手柄能够安全地从窗口子系统移动

我正在开发一个由许多独立子系统组成的系统。其中两个子系统是Window和GraphicsAdapter子系统

GraphicsAdapter需要一个低级窗口句柄(HWND或X11窗口句柄,具体取决于操作系统),窗口子系统是抽象这些特定于操作系统的API的一种方法

如果窗口子系统允许访问低级API句柄,那么封装就有可能被破坏

如果它允许windows全屏显示和返回,但必须触发事件来警告系统这些更改,并且在它不知情的情况下使用低级句柄切换到全屏显示,该怎么办

我如何确保手柄能够安全地从窗口子系统移动到GraphicsAdapter而不被滥用,并且仍然具有足够的灵活性,允许以后添加GraphicsAdapter等其他子系统,同时保持类型安全

有没有一种方法可以封装句柄,使Direct3D和OpenGL能够从句柄访问足够的内容,从而正常工作

--编辑

除了安全地将手柄从一个子系统运送到另一个子系统之外,知道子系统可以由不同的编码团队编写,例如,是否有任何方法提醒他们手柄的使用方式


注释是显而易见的选择,但编译器强制执行的东西才是我真正想要的…

通过虚拟函数公开句柄上的操作:

class GenericHandle
{
    public:
        virtual void some_operation() = 0;
};

// Windows API
class WindowsHandle : public GenericHandle
{
    public:
        virtual void some_operation()
        {
            WndOperation (handle_);
        }
    private:
        HANDLE* handle_;
};

// Some X system API
class XHandle : public GenericHandle
{
    public:
        virtual void some_operation()
        {
           XOperation (handle_);
        }
    private:
        XVOID* handle_;
};
配置
图形适配器的一种可能方法是:

GraphicsAdapter* ga = new GraphicsAdapter(GenericHandleFactory::get_handle(SYSTEM_ID));

HWND和X11窗口句柄都是指针类型。你可以利用这个优势。这样做:

struct WindowHandleImpl;
typedef WindowHandleImpl *WindowHandle;
C++允许您使用指向不完整类型的指针—只是不在任何地方定义
WindowHandleImpl
的内容,
WindowHandle
是一种完全不透明的类型,应用程序可以在不透露任何实现细节的情况下传递

由于
HWND
、X11
Window
WindowHandle
都是指针类型,因此您可以在它们之间自由无损地强制转换。因此,每当您需要将包装好的窗口句柄返回到应用程序时,您都会执行一个
静态转换(some\u hwnd)
,当您需要将指定的应用程序
窗口句柄
转换为实际的平台类型时,同样的技巧也会反过来工作


如果需要移植到不使用指针类型来表示窗口句柄的平台,可以将其包装在结构/类中,并返回指向该结构/类的指针

记录您希望使用它的方式

相信你团队中的其他程序员


不要写一堆代码试图直接让你的团队按照你想要的方式编码。更多的代码意味着需要维护的代码越多,出现错误的机会就越多,下一个看到这段代码的人就会感到困惑,想知道它到底在做什么。

我会将它封装在wxWidgets或Qt或GTK中,或者……如果我只想有一个空白窗口来呈现内容,为什么我要使用wxWidgets、Qt或GTK或任何完整的GUI库呢?此外,如果我想在OpenGL/D3D上进行渲染,我仍然需要访问某种_nativeHandle()来选择句柄并将其放在OpenGL/D3D上,所以这不是我想要的。我想要一个新的解决方案。GraphicsAdapter需要这个句柄的作用是什么?为什么你不能相信GraphicsAdapter代码?@Alf:他已经说过:这样他就可以初始化OpenGL/D3D,这两个都需要目标窗口的句柄。问题是OpenGL和Direct3D根本不理解什么是WindowsHandle或XHandle或其他什么。它需要Windows HWND或X11窗口句柄。实际上,更准确地说,OpenGL需要Windows下的设备上下文来创建其渲染上下文。不过,Direct3D需要HWND。这两种情况都很难封装,尽管像往常一样,D3D的情况要戏剧性得多,因为它消耗的资源远远超过了渲染所需的资源(一个完整的窗口句柄,而不是它真正需要的绘制位置)。@n2liquid:在所描述的情况下,无法避免向下投射。在GraphicsAdapter中的GenericHandle上使用RTTI获取原始数据或您需要的特定功能。为了安全起见,我可能会首先将其包装在结构中。。我不相信微软会把HWNDs当作手柄。可能有一些模糊的
#define
出于某种原因将其重新定义为其他东西。如果没有,那么添加它只是时间问题+1但是,因为您对这两种情况都描述得很好,这是一个很好的解决方案。@jalf:嗯,他们坚持使用Win16、Win32和现在的64位的指针类型。除了切换到其他平台等剧烈变化之外,这几乎是不可能改变的,因为这会破坏二进制兼容性,而且每个Windows应用程序(控制台应用程序除外)都依赖于user32.dll的二进制接口。如果有疑问,请保持简单。如果您确实不确定以后是否需要更改它,请编写两个助手函数
WindowHandleFromHWND
HWNDFromWindowHandle
,并让它们执行类型转换。这样,如果您需要,只有两个地方可以编辑。文档放在您获取HWND的地方。稍后,您可以来回传递它很多次,以至于没有人知道它应该使用文档记录的方式。它不再是一个get函数:它是一个自由变量。不应该是这样的。OOP正是反对这种哲学。应该有一种方法让他们玩得很好,OOP方法。如果我找不到路,我当然会把它记录下来。