WarmGUI(2) 类CWndApp山寨CWinApp

自从打算开发一个框架之后,我就没睡好过觉,需要学习思考的东西太多,尤其是水平比较低的时候更加难了。目前虽然开发出来些东西,感觉思路还是有些乱,慢慢都发出来,请教各位高人吧,还是那句话:千里之行始于足下。

MFC中CWinApp类主要做程序的初始化和终止前的清理,并且继承了CWinThread,
class CWinApp : public CWinThread

CWinThread处理与线程相关的一些事务,例如创建线程、挂起和恢复线程、设定线程的优先级,向一个线程发送消息,等等。

而CWinThread又从CCmdTarget继承,
class CWinThread : public CCmdTarget

CCmdTarget处理OLE,TypeLib这样的一些事务。

但是我并不打算让App类做这样的继承,理由是
1. 作为一个普通的WinApp,可能没有机会处理线程或者OLE的事务,
2. 并不一定需要用继承的关系,用组合的关系或许更好,用@溪流 的话来说,没事不用继承的好,
3. 快速的迭代开发

因此上我把CWndApp的功能暂时局限在初始化和退出应用两个函数上,线程是很重要的,我打算以后实现一个CThread类,而OLE,TypeLib之类的事务,也放在以后来实现,并且可以借鉴@溪流 现在对原生OLE的探索工作。这样看来CWndApp非常简单,但是他和CWindow类配合应该能够满足最小的应用框架:

 1 class WARMGUI_API CWndApp
 2 {
 3 public:
 4     CWndApp(void);
 5     virtual ~CWndApp(void);
 6 
 7     int UniqueInstance(TCHAR * appname);
 8 
 9     virtual int InitialApp(HINSTANCE hInstance, int nCmdShow);
10 
11     virtual void CleanupApp();
12 
13 protected:
14     HANDLE _hInstanceMutex;
15     HINSTANCE _hInstance;
16 };

其中UniqueInstance函数保证这个应用只运行一个实例,他的实现代码是这样的:
 1 int CWndApp::UniqueInstance(TCHAR * appname)
 2 {
 3     //an instance exists already
 4     _hInstanceMutex = OpenMutex(SYNCHRONIZE, TRUE, appname);
 5     if (_hInstanceMutex)
 6         return (-1);
 7 
 8     //create new instance
 9     _hInstanceMutex = CreateMutex(0, FALSE, appname);
10     if (!_hInstanceMutex)
11         return (-2);
12 
13     return (0);
14 }

InitialApp是一个虚函数,用来初始化应用,例如下面的实现可以保证使用CListView,设置堆信息,初始化COM接口,另外获得一个ID2D1Factory的实例,这是让Direct2D的初始化,在下一次给出这个类的代码。先看InitialApp的示例:
 1 int CWndApp::InitialApp(HINSTANCE hInstance, int nCmdShow)
 2 {
 3     INITCOMMONCONTROLSEX InitCtrls;
 4     InitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX), InitCtrls.dwICC = ICC_LISTVIEW_CLASSES;
 5     BOOL b = InitCommonControlsEx(&InitCtrls);
 6 
 7     // Ignoring the return value because we want to continue running even in the
 8     // unlikely event that HeapSetInformation fails.
 9     HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
10     CoInitialize(NULL);
11 
12     CDxFactorys::GetInstance()->InitDxFactory();
13     return (0);
14 }

CleanupApp用来做app退出之前的清理工作,针对上面的InitialApp,ClanupApp类似这样释放Direct2D的资源:
1 void CWndApp::CleanupApp()
2 {
3     CDxFactorys::GetInstance()->ReleaseResource();
4     CoUninitialize();
5 }

现在一个简单的应用看起来是这样的:
 1 int APIENTRY _tWinMain(HINSTANCE hInstance,
 2                      HINSTANCE hPrevInstance,
 3                      LPTSTR    lpCmdLine,
 4                      int       nCmdShow)
 5 {
 6     CWndApp app;
 7     if (app.UniqueInstance(L"MyTestWndApp"))
 8         return (0);
 9 
10     app.InitialApp(hInstance, nCmdShow);
11 
12     CMyWindow mainwnd;
13     TCHAR szTitle[MAX_LOADSTRING] = L"MyFirstWindow";
14     TCHAR szClassName[MAX_LOADSTRING] = L"WARMGUIWNDCLASS";
15 
16     BOOL r = mainwnd.InitInstance(hInstance, hPrevInstance, lpCmdLine, nCmdShow, szClassName, szTitle);
17     if (r)
18         mainwnd.RunMessageLoop(0);
19     
20     app.CleanupApp();
21     return (r) ? 0 : -1;
22 }

现在确实很简单,或许应该增加更多的函数,不过貌似一个典型的Win32 App的应用框架已经有点样子了。 现在还有很重要的HDC, Bitmap, Font, Brush等绘图的一大坨东西,不过我并不打算封装他们到类里来,因为这不是WarmGUI的重点,因为即将开始进入DirectX的世界,一个我目前还比较陌生的世界,一边学习一边前进吧 ^_^

posted on 2012-09-16 21:35 毕达哥拉斯半圆 阅读(1898) 评论(2)  编辑 收藏 引用

评论

# re: WarmGUI(2) 类CWndApp山寨CWinApp 2012-09-17 13:14 Enic

一开始不要做框架,先考虑做成基础库。
基础库成熟了,框架就呼之欲出了。应为你现在还不够了解这里边的道道,所以直接去做框架是很可能南辕北辙的。
可以先参考QT WTL MFC的设计思想,然后以实际项目为导向。
如果是做界面有一本老书推荐给你:《道法自然》

还有如果你定位是windows平台,可以考虑用ATL包装窗口,ATL的窗口循环hack已经做好了,而且做稳定了。  回复  更多评论   

# re: WarmGUI(2) 类CWndApp山寨CWinApp 2012-09-18 14:37 毕达哥拉斯半圆

@Enic
多谢指点,虽然现在是在windows下,但不想局限在这上,我学习一下 QT,多谢啦!  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2012年9月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

导航

统计

常用链接

留言簿(3)

随笔档案

相册

contact

搜索

最新评论

阅读排行榜

评论排行榜