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>, CWindowImpl是WTL中所有的窗口封装类的一个实现模板里,封装了基本的窗口相关的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; }
此时我们点击窗口的关闭按钮后,我们就可以退出程序了。
至此一个简单的窗体就显示出来了。
来源:https://www.cnblogs.com/kwliu/archive/2011/08/06/2129633.html