在C++中将HWND包装在对象中的有效方法是什么?

Mar*_*tin 3 c++ winapi

我一直在使用C++和Win32(非MFC/ATL)我正在编写自己的类库来包装某些Win32对象(特别是HWND).

在创建窗口时,我发现"RegisterClassEx/CreateWindowEx"方法非常笨拙.这种设计使得编写简单的类包装器变得困难(必须采用thunk,或TLS或其他一些复杂的机制).

在我看来,让应用程序在窗口创建时指定窗口过程和用户​​数据指针会更简单.

这里的设计选择是否有任何明显的原因?有一种非常简单有效的方法吗?

sel*_*bie 7

ATL的CWindow和CWindowImpl是你的朋友.

CWindowImpl负责处理您所说的RegisterClass/CreateWindow尴尬.

CWindow是HWND的基本"包装器"类,其中抽象出了所有win32函数.

我更喜欢ATL而不是MFC的原因.ATL是一组非常轻量级的类,提供了所有源代码.这是一个简单的#include,没有额外的库或运行时来处理.在滚动我自己的WndProcs和窗口封装类多年之后,我发现CWindowImpl很愉快.您必须在代码中声明一个全局AtlModuleExe实例才能使用它,但除此之外,ATL仍然不受影响.

下面这些类的文档链接:CWindow:http: //msdn.microsoft.com/en-us/library/d19y607d.aspx

CWindowImpl:http: //msdn.microsoft.com/en-us/library/h4616bh2.aspx

更新:这是我为您挖出的一些示例代码:

class CMyApp : public CAtlExeModuleT<CMyApp>
{
public:
    static HRESULT InitializeCom()
    {
        CoInitialize(NULL);
        return S_OK;
    }
};

CMyApp g_app;

class CMyWindow : public CWindowImpl<CMyWindow>
{
public:
    CMyWindow();
    ~CMyWindow();
    BEGIN_MSG_MAP(CMyWindow)
        MESSAGE_HANDLER(WM_PAINT, OnPaint);
        MESSAGE_HANDLER(WM_CLOSE, OnClose);
    END_MSG_MAP();

    LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled);
    LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled);
};

LRESULT CMyWindow::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled)
{
   // your WM_PAINT code goes here
}

LRESULT CMyWindow::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled)
{
    PostQuitMessage();
}

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdline, int nCmdShow)
{
    // 640x480 window
    CMyWindow appwindow;
    RECT rect = {0, 0, 640, 480};
    RECT rectActual = {0};
    appwindow.Create(NULL, rect, L"App Window", WS_OVERLAPPEDWINDOW);
    appwindow.ShowWindow(SW_SHOW);

    {
        MSG msg;
        while (GetMessage(&msg, 0, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    // app shutdown

    appwindow.DestroyWindow();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)