WTL学习(一)窗口框架

wtl这个开发框架在开发win32程序方面有很多应用 ,现在chrome和金山等都是用的这个库,所以我要好好学习一下,故写此博客,以推动自己学习。

开始

我从都开始建立一个win32的窗口程序,然后一步一步的添加wtl中的模块,以求达到熟悉win32中的各个api和wtl中类的目的。

首先,包含一下atlapp.h这个头文件。这个头文件中包含了CMessageLoop,这个类主要是用来管理win32的消息循环的(具体的以后再仔细分析吧);CAppModule这个类封装了一个程序中的所有的线程消息循环 。

class CAppModule : public ATL::CComModule
{
public:
DWORD m_dwMainThreadID;
ATL::CSimpleMap
<DWORD, CMessageLoop*>* m_pMsgLoopMap;
ATL::CSimpleArray
<HWND>* m_pSettingChangeNotify;
。。。。。。。。。。。
}

其中,m_dwMainThreadID是程序主线程的线程ID,m_pMsgLoopMap中维护着所有线程,m_pSettingChangeNotify我还不清楚,在看吧。

在项目中添加一个类CmfMainFrame,然后继承自CWindowImpl<CmfMainFrame>, CWindowImplWTL中所有的窗口封装类的一个实现模板里,封装了基本的窗口相关的api调用。如果要从CWindowImpl类继承,我们必须要定义如下两个宏:

    BEGIN_MSG_MAP(CmfMainFrame)

    END_MSG_MAP()

其中BEGIN_MSG_MAP的定义如下,封装了一个ProcessWindowMessage函数,这个函数是CWindowImpl中的一个虚函数,我们通过在子类中实现出这个函数,才能够实例化它。

#define BEGIN_MSG_MAP(theClass) \
public: \
BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT
& lResult, DWORD dwMsgMapID = 0) \
{ \
BOOL bHandled
= TRUE; \
(hWnd); \
(uMsg); \
(wParam); \
(lParam); \
(lResult); \
(bHandled); \
switch(dwMsgMapID) \
{ \
case 0:

win32中的编程知识可知,我们要创建一个窗口,必选在定义然后注册这个窗口,然后创建显示,开始程序中的消息循环。CwindowImpl中封装了定义和注册窗口,还有创建和显示。我的CmfMainFrame类得代码如下:

class CmfMainFrame:

    public CWindowImpl<CmfMainFrame>

{

public:

    BEGIN_MSG_MAP(CmfMainFrame)

    END_MSG_MAP()

};

 

然后主程序的代码如下:

int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
{
CMessageLoop theLoop;
_Module.AddMessageLoop(
&theLoop);

CmfMainFrame wndMain;

if(wndMain.Create(NULL, CWindow::rcDefault, L"KO", WS_OVERLAPPEDWINDOW) == NULL)
{
ATLTRACE(_T(
"Main window creation failed!\n"));
return 0;
}

wndMain.ShowWindow(nCmdShow);

int nRet = theLoop.Run();

_Module.RemoveMessageLoop();
return nRet;
}


int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
HRESULT hRes
= ::CoInitialize(NULL);
ATLASSERT(SUCCEEDED(hRes));


AtlInitCommonControls(ICC_COOL_CLASSES
| ICC_BAR_CLASSES | ICC_USEREX_CLASSES);

hRes
= _Module.Init(NULL, hInstance);
ATLASSERT(SUCCEEDED(hRes));

AtlAxWinInit();

int nRet = Run(lpstrCmdLine, nCmdShow);

_Module.Term();
::CoUninitialize();

return nRet;
}

此时,运行程序就可以显示一个窗口了。我们要是点击窗口的X关闭按钮后,不能够结束程序,只是窗口消失了。问题在于我们没有处理WM_DESTROY消息。我们在BEGIN_MSG_MAP中添加一个MESSAGE_HANDLER代码如下:

    BEGIN_MSG_MAP(CmfMainFrame)
MESSAGE_HANDLER(WM_DESTROY, onDestroy)
END_MSG_MAP()

LRESULT onDestroy(UINT
/*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
PostQuitMessage(
0);
return 0;
}

此时我们点击窗口的关闭按钮后,我们就可以退出程序了。

至此一个简单的窗体就显示出来了。












posted on 2011-08-06 19:53  一颗麦粒  阅读(1914)  评论(0编辑  收藏  举报

导航