我一直在使用C++和Win32(非MFC/ATL)我正在编写自己的类库来包装某些Win32对象(特别是HWND).
在创建窗口时,我发现"RegisterClassEx/CreateWindowEx"方法非常笨拙.这种设计使得编写简单的类包装器变得困难(必须采用thunk,或TLS或其他一些复杂的机制).
在我看来,让应用程序在窗口创建时指定窗口过程和用户数据指针会更简单.
这里的设计选择是否有任何明显的原因?有一种非常简单有效的方法吗?
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)