自從打算開發一個框架之后,我就沒睡好過覺,需要學習思考的東西太多,尤其是水平比較低的時候更加難了。目前雖然開發出來些東西,感覺思路還是有些亂,慢慢都發出來,請教各位高人吧,還是那句話:千里之行始于足下。
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的世界,一個我目前還比較陌生的世界,一邊學習一邊前進吧 ^_^