WTL流程分析

本文详细分析了WTL(Windows Template Library)中窗口从创建到销毁的过程,包括winmain函数、Run函数的作用,窗口类的注册,以及消息循环的运行。特别讨论了CMainFrame类的创建,窗口类的注册过程,窗口创建的关键步骤,以及消息如何从StartWindowProc传递到ProcessWindowMessage进行处理。WTL利用模板和静态成员函数实现了类似虚函数的功能,提高了效率。
摘要由CSDN通过智能技术生成

一个窗口从创建到销毁,有这么几个主要过程。

winmain

  • 注册窗口类
  • 创建窗口
  • 进入消息循环

wndproc

  • 处理消息

现在我们就是要挖掘出wtl中在何处处理这些东西,怎么处理的。首先:

winmain在哪里?

winmain在和工程名相同的cpp文件中。名字叫做_twinmain

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)

{

       HRESULT hRes = ::CoInitialize(NULL);

// If you are running on NT 4.0 or higher you can use the following call instead to

// make the EXE free threaded. This means that calls come in on a random RPC thread.

//     HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);

       ATLASSERT(SUCCEEDED(hRes));

       // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used

       ::DefWindowProc(NULL, 0, 0, 0L);

       AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES);  // add flags to support other controls

       hRes = _Module.Init(NULL, hInstance);

       ATLASSERT(SUCCEEDED(hRes));

       int nRet = Run(lpstrCmdLine, nCmdShow);

       _Module.Term();

       ::CoUninitialize();

       return nRet;

}

从这个函数中,看不出什么,基本上实质上的内容都被分配在别的函数中处理了。这里所说的别的函数就是Run(lpstrCmdLine, nCmdShow);这个函数是我们自己写的,就在这个_twinmain的上面。

Run的作用

int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)

{

       CMessageLoop theLoop;

       _Module.AddMessageLoop(&theLoop);

       CMainFrame wndMain;

       if(wndMain.CreateEx() == NULL)

       {

              ATLTRACE(_T("Main window creation failed!/n"));

              return 0;

       }

       wndMain.ShowWindow(nCmdShow);

       int nRet = theLoop.Run();

       _Module.RemoveMessageLoop();

       return nRet;

}

从名字MessageLoopCreateEx就可以猜测到这个Run就是创建窗口并进入消息循环的地方。所以

winmain进行必要的初始化,主要的工作在Run中进行

Run创建窗口并进入消息循环。

窗口的创建

很容易就可以知道这么一段完成了窗口的创建

       CMainFrame wndMain;

       if(wndMain.CreateEx() == NULL)

       {

              ATLTRACE(_T("Main window creation failed!/n"));

              return 0;

       }

CMainFrame定义在MainFrm.h中。

class CMainFrame : public CFrameWindowImpl<CMainFrame>, public CUpdateUI<CMainFrame>,         public CMessageFilter, public CIdleHandler

可见这里使用了多继承,这是一个普遍行为。主要继承于CFrameWindowImpl,而且这个是模板,提供的参数就是CMainFrame。后面可以发现,这个参数在基类中用于强制类型转换,算是向下转换。

创建调用的是wndMain.CreateEx(),这个函数在CMainFrame中找不到,自然在其基类中有。这个是CFrameWindowImpl中的CreateEx()

       HWND CreateEx(HWND hWndParent = NULL, _U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)

       {

              TCHAR szWindowName[256];

              szWindowName[0] = 0;

              ::LoadString(_Module.GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, 256);

              HMENU  hMenu=::LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));

              T* pT = static_cast<T*>(this);

              HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);

              if(hWnd!=NULL)

                     m_hAccel=::LoadAccelerators(_Module.GetResourceInstance(),MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));

              return hWnd;

       }

等等,我们在这里发现了一个奇异的行为。

T* pT = static_cast<T*>(this);

这是什么,强制类型转换,而且是基于模板参数的类型转换。嗯ÿ

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值