Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
444 views
in Technique[技术] by (71.8m points)

winapi - What is an efficient way to wrap HWNDs in objects in C++?

I have been working with C++ and Win32 (non MFC/ATL) I am playing around with writing my own class library to wrap certain Win32 objects (HWNDs in particular).

When it comes to creating windows, I find the "RegisterClassEx / CreateWindowEx" method very awkward. This design makes it hard to write simple class wrappers (one must resort to thunks, or TLS or some other complicated mechanism).

It seems to me it would have been simpler to just let the application specify the window procedure and a user-data pointer at window creation time.

Is there any obvious reason I'm missing for the design choice here? Is there a really simple and efficient way for this to work?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

ATL's CWindow and CWindowImpl are your friends.

CWindowImpl makes takes care of the RegisterClass/CreateWindow awkwardness that you speak of.

CWindow is a basic "wrapper" class for an HWND with all the win32 functions abstracted out.

The reason I prefer ATL over MFC. ATL is a very lightweight set of classes with all the source code provided. It's a simple #include with no extra libraries or runtimes to deal with. After rolling my own WndProcs and window encapsulation classes for many years, I've found CWindowImpl a joy to work with. You have to declare a global AtlModuleExe instance in your code to use it, but besides that, ATL stays out of the way.

Links to documenation for these classes below: CWindow: http://msdn.microsoft.com/en-us/library/d19y607d.aspx

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

Update: Here's some sample code I dug up for you:

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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...