问题描述
我一直在使用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:
CWindowImpl:
更新:这是我为你挖掘的一些示例代码:
class CMyApp:public CAtlExeModuleT< CMyApp>
{
public:
static HRESULT InitializeCom()
{
CoInitialize(NULL);
返回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)
{
//您的WM_PAINT代码在这里
}
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,LApp 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;
}
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?
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;
}
这篇关于在C ++中的对象中包含HWND的有效方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!