毫無疑問,Windows的流行推動(dòng)了圖形界面的發(fā)展,從最原始的Win32界面庫到MFC,再到最近UWP界面庫,Windows界面庫的發(fā)展也代表了界面庫和整個(gè)軟件行業(yè)的發(fā)展方向。本文就簡單梳理下整個(gè)Windows界面庫的發(fā)展歷程和現(xiàn)狀。
Windows 整個(gè)系統(tǒng)的圖形界面是建立在Win32圖形界面接口上的,它提供了Windows界面編程的基本模型——顯示管理窗口和消息循環(huán)分發(fā)事件。Win32是C接口形式,一個(gè)典型的窗口程序如下,可以看到就是按照通用界面庫模型來的,不再贅述,對(duì)此感興趣的可以看Petzold的《Windows程序設(shè)計(jì)》。Win32需要考慮細(xì)節(jié)太多,目前實(shí)際編程很少再用原生win32了,一般是第三方界面庫基于Win32包裝或其他語言通過包裝Win32來提供基本界面功能。
- #include <windows.h>
- LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
- int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
- {
- static TCHAR szAppName[] = TEXT ("窗口類名稱");
- HWND hwnd;
- MSG msg;
- WNDCLASSEX wndclassex = {0};
- //設(shè)計(jì)窗口類
- wndclassex.cbSize = sizeof(WNDCLASSEX);
- wndclassex.style = CS_HREDRAW | CS_VREDRAW;
- wndclassex.lpfnWndProc = WndProc;
- wndclassex.cbClsExtra = 0;
- wndclassex.cbWndExtra = 0;
- wndclassex.hInstance = hInstance;
- wndclassex.hIcon = LoadIcon (NULL, IDI_APPLICATION);
- wndclassex.hCursor = LoadCursor (NULL, IDC_ARROW);
- wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
- wndclassex.lpszMenuName = NULL;
- wndclassex.lpszClassName = szAppName;
- wndclassex.hIconSm = wndclassex.hIcon;
- //注冊(cè)窗口類
- if (!RegisterClassEx (&wndclassex))
- {
- MessageBox (NULL, TEXT ("RegisterClassEx failed!"), szAppName, MB_ICONERROR);
- return 0;
- }
- //產(chǎn)生窗口
- hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW,
- szAppName,
- TEXT ("窗口名稱"),
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL,
- NULL,
- hInstance,
- NULL);
- //顯示窗口
- ShowWindow (hwnd, iCmdShow);
- UpdateWindow (hwnd);
- //啟動(dòng)消息循環(huán)泵循環(huán)獲取消息分配到窗體過程函數(shù)處理
- while (GetMessage (&msg, NULL, 0, 0))
- {
- TranslateMessage (&msg);
- DispatchMessage (&msg);
- }
- return msg.wParam;
- }
- //窗體過程函數(shù)
- LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- HDC hdc;
- PAINTSTRUCT ps;
- switch (message)
- {
- case WM_CREATE:
- return (0);
- case WM_PAINT:
- hdc = BeginPaint (hwnd, &ps);
- EndPaint (hwnd, &ps);
- return (0);
- case WM_DESTROY:
- PostQuitMessage (0);
- return (0);
- }
- return DefWindowProc (hwnd, message, wParam, lParam);
- }
可以看到Win32創(chuàng)建一個(gè)簡單的界面需要大段的代碼,既然是遵循相同的模型,恰好適逢C++技術(shù)發(fā)展,微軟借助C++技術(shù)將界面編程抽象成許多類,包裝諸多細(xì)節(jié),最明顯的兩個(gè)特征:
1.簡化窗口創(chuàng)建,窗口創(chuàng)建和類綁定,創(chuàng)建的公共操作封裝到基類中
2.窗口過程統(tǒng)一勾到一個(gè)處理函數(shù)中,然后分發(fā)到對(duì)應(yīng)的每個(gè)窗口類中(可以參考我的這篇文章)
這樣開發(fā)者只需要重寫部分虛函數(shù),填充消息消息響應(yīng)表實(shí)現(xiàn)響應(yīng)函數(shù)即可,大大減少了開發(fā)者的工作量,而且結(jié)合VC提供的可視化功能,能夠快速的完成界面代碼的生成。但是MFC封裝臃腫了,繼承層次過多,且當(dāng)時(shí)的C++標(biāo)準(zhǔn)尚未完善為了彌補(bǔ)有很多hack設(shè)計(jì),但是MFC經(jīng)過這么多年的發(fā)展已經(jīng)相當(dāng)穩(wěn)定了,所以現(xiàn)在主要用在工業(yè)領(lǐng)域,算是工業(yè)領(lǐng)域的一個(gè)標(biāo)準(zhǔn)了,一些小公司和小工具也還是在用MFC,感興趣的入門可以看看孫鑫《VC++深入詳解》,提高可以看侯捷的《深入詳解MFC》和David《Visual C++ 技術(shù)內(nèi)幕》。
因?yàn)镸FC的臃腫,微軟的一個(gè)開發(fā)小組業(yè)余開發(fā)了WTL,并且逐漸被大家接受,WTL主要基于C++ 模板技術(shù),封裝很輕量級(jí),而且兼具M(jìn)FC的諸多優(yōu)點(diǎn),還可以和MFC混用。但是因?yàn)閃TL技術(shù)上相對(duì)MFC要求較高,目前主要是一些大廠(360、金山等)在用,而且由于WTL的封裝很易于擴(kuò)展,國內(nèi)大多數(shù)Windows C++界面庫都是基于WTL開發(fā)的,接下來關(guān)于界面庫的編寫也主要基于WTL講解。
WTL出來的相對(duì)較晚,微軟也沒有大力宣傳過,市面上講解的書不多,詳細(xì)了解WTL可以看看WTL for MFC Programmers系列文章,這是中文版本鏈接。
qt并非微軟的界面庫,他是一個(gè)跨平臺(tái)的C++界面庫,最早由諾基亞開發(fā)用于手機(jī)界面展示,現(xiàn)在由奇趣公司維護(hù)。之所以把Qt放在這里講,是因?yàn)镼t在Windows上使用非常廣泛,而且引入了非常多新的設(shè)計(jì)。如果把原生Win32比作界面庫1.0,MFC/WTL比作界面庫2.0,那么Qt Widget可以算是界面庫3.0。它引入了xml布局界面,支持Qss樣式,支持非常多系統(tǒng)組件,非常易于編寫現(xiàn)代化的DirectUI界面,現(xiàn)在Qt被廣泛的用在了工業(yè)領(lǐng)域,互聯(lián)網(wǎng)產(chǎn)品比如WPS,YY語音等也都是基于Qt編寫??梢哉f如果需要一種跨平臺(tái)的C++界面庫,那么Qt是最好的選擇??梢詤⒖紩甁asmin 《C++ GUI Qt 4編程(第2版)》,這本書有點(diǎn)老,可以結(jié)合現(xiàn)在文檔一起看,Qt的文檔寫的非常好。
winform并非C++界面庫,但是微軟后期的主要精力在于推廣自己的C#語言,因此winform可以看做是微軟界面庫發(fā)展的延續(xù)。Winform是基于Win32封裝,屏蔽了很多細(xì)節(jié),擁有超多組件,結(jié)合VC編寫所見即所得界面非常簡單。但是打包發(fā)布Winform窗體程序時(shí),一般需要帶上對(duì)應(yīng).Net 運(yùn)行時(shí),因此程序體積比較大,但是勝在開發(fā)效率快和COM、數(shù)據(jù)庫集合非常好,很多企業(yè)化辦公和管理系統(tǒng)都是基于Winform來編寫的。
Winform主要還是基于win32界面庫,在新的互聯(lián)網(wǎng)時(shí)代DirectUI的誕生讓開發(fā)者可以編寫更加現(xiàn)代化更加炫酷支持更多自定義的界面,為此微軟大力推出了WPF。DirectUI技術(shù)某種程度上其實(shí)就是在客戶端界面編程做到類似Web前端開發(fā),通過聲明式的類xml和css控制顯示,通過類腳本控制界面動(dòng)作和效果,做到顯示和邏輯分離。
WPF曾是微軟大力推的界面技術(shù),它引入了很多革新的概念——xaml布局、數(shù)據(jù)綁定技術(shù)等等,支持更加復(fù)雜的繪制和特效,和Qt Widget類似,但是更加強(qiáng)大,進(jìn)一步提高了開發(fā)效率,可以看做界面庫3.5。但是由于WPF最開始基于CPU渲染,有很大的性能問題,現(xiàn)在某種程度上已經(jīng)得到了很好的優(yōu)化,然而和winform一樣有依賴.net運(yùn)行時(shí)的問題,而許多互聯(lián)網(wǎng)公司的產(chǎn)品都是需要支持Window XP(比如QQ、360安全衛(wèi)士等),所以WPF不是桌面應(yīng)用程序界面開發(fā)首選,WPF現(xiàn)在還是主要用在企業(yè)化辦公和管理系統(tǒng)。
在移動(dòng)互聯(lián)網(wǎng)的路上,微軟并沒有走的很好,為了打出差異,推出了手機(jī)/平板/PC一體的Win8,隨之推出的是號(hào)稱一次編寫到處運(yùn)行UWP應(yīng)用,其實(shí)UWP很像WPF,但是界面編寫方式更貼近Web前端。UMP應(yīng)用市場(chǎng)正在逐漸完善,但是畢竟操作體驗(yàn)和傳統(tǒng)PC windows有差別,且很多地方還是處于一種混合的方式,只能等待微軟改進(jìn)和時(shí)間磨合了,具體前途怎樣現(xiàn)在很難說,依賴于.Net的問題同樣是現(xiàn)階段的一個(gè)制約,微軟馬上要停止Win7的支持,可能有利于UWP的發(fā)展,國內(nèi)的一些大廠都推出了自家的UWP應(yīng)用(比如QQ、愛奇藝等)做提前布局。UWP可以看做界面庫4.0,當(dāng)然這是我個(gè)人的排序,僅做參考,感興趣的可以直接看官方MSDN文檔,示例非常全。
Qt QML和UWP很像,同時(shí)支持PC/平板/應(yīng)用編寫,編寫方式也很類似Web前端,如果之前就是Qt Widget開發(fā)者可以很快入門,特別是有一些有跨平臺(tái)需求多系統(tǒng)支持的場(chǎng)合應(yīng)用較多,感興趣的可以看看Qt官方文檔。
前面說過因?yàn)閃eb前端的方式真正做到了顯示和邏輯分離,PC界面庫越來越模仿Web前端的方式,與其模仿Web前端不如直接就用Web前端來寫界面。之前介紹過通過內(nèi)嵌IE瀏覽器來編寫桌面應(yīng)用的程序,但是因?yàn)槲④浉鱾€(gè)版本的IE對(duì)現(xiàn)代化Web前端的支持有限,只能做有限的工作。得益于Google開源的Chromium項(xiàng)目,開發(fā)者們基于Chromium改造提供基于Web瀏覽器的界面庫libcef/node-webkit/electron:
1.libcef打包了一部分Chromium常用功能,封裝成庫,開發(fā)者可以在程序中直接調(diào)用就完成了瀏覽器的嵌入
2.node-webkit/electron更甚,直接基于 Chromium 和 Node.js打造一套完整框架, 讓你可以使用 HTML, CSS 和 JavaScript 構(gòu)建應(yīng)用
越來越多的應(yīng)用開始采用這種方式,比如網(wǎng)易云音樂、網(wǎng)易云筆記甚至微軟自家產(chǎn)品VS Code,唯一限制這種方式流行的是需要打包很多Chromium庫,安裝包體積較大,但是在現(xiàn)在這種寬帶和磁盤體積下,似乎也不是什么大問題。
這種方式支持跨平臺(tái),支持老系統(tǒng),且直接使用現(xiàn)有Web前端開發(fā)人員即可完成開發(fā),減少學(xué)習(xí)成本,可以說是一個(gè)非常好的方式,這也是我強(qiáng)烈推薦的現(xiàn)階段桌面應(yīng)用構(gòu)建方式。當(dāng)然它也不是萬能的,如果你想寫個(gè)簡單工具,或者系統(tǒng)優(yōu)化應(yīng)用最好還是用傳統(tǒng)的方式。
Windows界面庫的發(fā)展就介紹到這里,基本上整個(gè)脈絡(luò)如此,由于主要討論的是一般PC桌面應(yīng)用開發(fā),相關(guān)的其他技術(shù)比如DirectX、OpenGL、SiverLight不在討論范圍,感興趣的可以自行查找下相關(guān)資料。
聯(lián)系客服