• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-341  評(píng)論-2670  文章-0  trackbacks-0
                從某種意義上來(lái)說(shuō),做圖形也好,做GUI也好,做編譯器也好,大概都是一種情結(jié)。其實(shí)只要稍微想一想就知道,能把它們?nèi)哂袡C(jī)統(tǒng)一起來(lái)的,就只有游戲。我很久以前的確是為了想開(kāi)發(fā)游戲才對(duì)編程產(chǎn)生興趣的,而學(xué)習(xí)游戲開(kāi)發(fā)占據(jù)了我前六年的時(shí)間。雖然現(xiàn)在不做了,不過(guò)偶爾總是會(huì)覺(jué)得手癢。但是做游戲沒(méi)美工做不好怎么辦呢?就只好寫(xiě)游戲代碼了。但是沒(méi)有資源寫(xiě)出來(lái)的游戲又不好玩,于是就只好寫(xiě)庫(kù)。那寫(xiě)什么庫(kù)呢,自然就只有渲染器、界面引擎和腳本引擎了。我的博客的大部分文章也是圍繞著這三件事情建立起來(lái),而且在中間不斷切換的。

                撒,所以今天就輪到GUI了。我一直很想做出一個(gè)自繪的GUI出來(lái),無(wú)奈一直設(shè)計(jì)不出一個(gè)好的架構(gòu)。后來(lái)嘗試用原生API,但是卻又很不喜歡MFC的設(shè)計(jì),就嘗試自己照著.NET Framework和Delphi那套VCL的樣子封裝了一個(gè)控件庫(kù)出來(lái)。無(wú)奈原生API細(xì)節(jié)無(wú)敵多,后來(lái)沒(méi)做把所有的功能都全部做完。因此后來(lái)一段時(shí)間凡是需要界面我都直接用C#做。然后CEGUI出了,WPF和Silverlight也出了,我發(fā)現(xiàn)如今要做一個(gè)漂亮的GUI非自繪已經(jīng)做不到了,所以我又做了一次嘗試。

                去年在美帝的時(shí)候曾經(jīng)試圖再設(shè)計(jì)一次,得到了一些結(jié)果。后來(lái)我發(fā)現(xiàn)其實(shí)根本沒(méi)辦法為GDI、DirectX、OpenGL和其它繪圖設(shè)備抽象一個(gè)公用的接口,否則就會(huì)遭遇大量性能問(wèn)題。因?yàn)樵诤芏嗉?xì)節(jié)上,譬如說(shuō)渲染文字,為了達(dá)到較高的性能,OpenGL和DirectX需要使用幾乎相反的策略來(lái)做。因此這次我又換了一個(gè)方法,而且在Vczh Library++ 3.0的Candidate目錄下已經(jīng)checkin了一個(gè)試驗(yàn)品。

                我把一個(gè)自繪的GUI分成了下面若干個(gè)層次。
                1、NativeWindow。NativeWindow表示的是一個(gè)頂層窗口的實(shí)現(xiàn)。譬如說(shuō)我們想用Windows的窗口作為自繪窗口的頂層窗口(游戲里面的很多頂層窗口是繪制在游戲窗口里面的,所以頂層窗口并不一定是Windows的窗口)。
                2、控件庫(kù)。控件庫(kù)包含了這個(gè)自繪GUI庫(kù)的所有預(yù)定義控件。控件本身包含對(duì)用戶輸入的相應(yīng)邏輯,但是每一個(gè)控件的繪制以及鼠標(biāo)點(diǎn)中測(cè)試不在此范圍內(nèi)。
                3、控件皮膚接口。每一個(gè)最終控件都會(huì)擁有一個(gè)控件皮膚接口。每當(dāng)控件的狀態(tài)發(fā)生了變化,控件會(huì)調(diào)用皮膚接口更新控件的當(dāng)前狀態(tài)。每當(dāng)控件需要知道某一個(gè)點(diǎn)是否位于一個(gè)控件里面的時(shí)候,他也會(huì)去調(diào)用該控件的皮膚獲得結(jié)果。因此控件皮膚接口包含了一切關(guān)于繪制(因此理所當(dāng)然也就包含了點(diǎn)中測(cè)試)的邏輯。

                為了達(dá)到最高的性能,一套皮膚的實(shí)現(xiàn)只能綁定在某種繪圖設(shè)備上,也就是說(shuō)缺省狀態(tài)下一套為GDI設(shè)備設(shè)計(jì)出來(lái)的皮膚是不能直接使用在DirectX設(shè)備上面的。當(dāng)然我這個(gè)框架的設(shè)計(jì)也是足夠開(kāi)放的,如果你非得用同一套代碼來(lái)實(shí)現(xiàn)不同繪圖設(shè)備上的皮膚,那么你是可以自己動(dòng)手豐衣足食,做到給GDI和DirectX設(shè)計(jì)一個(gè)公共接口并插入我的GUI框架的(只不過(guò)這種做法一般情況下都會(huì)慘死)。

                那么如何添加繪圖設(shè)備呢?目前NativeWindow有一個(gè)基于Windows窗口的實(shí)現(xiàn),并且NativeWindow的接口要求該實(shí)現(xiàn)在創(chuàng)建、銷毀、接收到很多窗口事件的時(shí)候都調(diào)用某一個(gè)回調(diào)對(duì)象。我們可以通過(guò)注冊(cè)一個(gè)全局回調(diào)對(duì)象或者具體窗口的回調(diào)對(duì)象來(lái)獲得NativeWindow狀態(tài)的變更。基于Windows窗口的NativeWindow實(shí)現(xiàn)還提供了一個(gè)額外函數(shù),可以讓你獲得一個(gè)NativeWindow的HWND(但這個(gè)函數(shù)并不被控件庫(kù)依賴)。現(xiàn)在我還實(shí)現(xiàn)了一個(gè)基于HWND+HDC的繪圖設(shè)備,主要方法就是先注冊(cè)全局回調(diào)對(duì)象,每當(dāng)知道一個(gè)NativeWindow被創(chuàng)建了,我就會(huì)注冊(cè)一個(gè)NativeWindow的回調(diào)對(duì)象,用來(lái)維護(hù)一個(gè)窗口里面的一塊32位DIBSections位圖緩沖區(qū)。窗口的大小如果變化了,我也會(huì)在適當(dāng)?shù)臅r(shí)候重新創(chuàng)建一塊合適的緩沖區(qū)。不過(guò)為了避免每一次大小變化都會(huì)創(chuàng)建新的緩沖區(qū),我創(chuàng)建的緩沖區(qū)的大小總會(huì)比窗口大一點(diǎn)。然后這個(gè)GDI繪圖設(shè)備就暴露了一個(gè)函數(shù),可以獲得一個(gè)NativeWindow的HDC和WinGDIElementEnvironment。

                WinGDIElementEnvironment是基于HWND+HDC的這一套實(shí)現(xiàn)上專有的、為了GDI皮膚設(shè)計(jì)出來(lái)的一個(gè)公共的資源庫(kù)(譬如用來(lái)保存各種面向業(yè)務(wù)邏輯的pen啊brush什么的,比如說(shuō)disable的時(shí)候什么顏色,選中的時(shí)候什么顏色等等)。如果你想設(shè)計(jì)一個(gè)基于HWND+DirectX的皮膚,那么類似WinGDIElementEnvironment的這套東西要重新做一次——因?yàn)闉榱诉_(dá)到相同的性能。具體細(xì)節(jié)相差太大。當(dāng)然HWND+HDC上面可以有多套皮膚,WinGDIElementEnvironment是公用的。WinGDIElementEnvironment要求繪制是通過(guò)一個(gè)具體的WinGDIElement對(duì)象達(dá)到的,而一套皮膚可以有自己的一套WinGDIElement的實(shí)現(xiàn)。WinGDIElement被設(shè)計(jì)成面向業(yè)務(wù)的、一套皮膚的基本元素組成部分,譬如說(shuō)按鈕邊框啦、焦點(diǎn)長(zhǎng)方形啦、文字啦,而不是帶有pen和brush的長(zhǎng)方形啊,文字啊,各種亂七八糟的最低等級(jí)的繪圖元素。舉一個(gè)例子,按鈕邊框跟菜單邊框很像,都可以用Rectangle來(lái)組成。但是Element里面就直接是按鈕邊框和菜單邊框,而不是一個(gè)可以讓你自由修改顏色的Rectangle。因?yàn)椴煌目丶蚕砼渖桨福渖桨甘怯蓸I(yè)務(wù)邏輯+空間狀態(tài)的集合實(shí)現(xiàn)的,因此WinGDIElement還是一個(gè)比較高層次的概念。當(dāng)一個(gè)WinGDIElement被渲染的時(shí)候,他會(huì)給你一個(gè)HDC,然后你根據(jù)被設(shè)置的狀態(tài)來(lái)調(diào)用GDI函數(shù)繪制到HDC指向的32位DIBSections位圖緩沖區(qū)上面。

                那么,當(dāng)我們使用HWND+HDC的實(shí)現(xiàn),創(chuàng)建了一個(gè)布滿了控件的窗口,那實(shí)際上是發(fā)生了什么事情呢?首先控件自己會(huì)組成一棵樹(shù)。其次,控件的皮膚也會(huì)組成一棵樹(shù)。現(xiàn)在就有控件樹(shù)跟皮膚樹(shù)兩顆樹(shù)了。控件樹(shù)負(fù)責(zé)所有用戶輸入變更狀態(tài)的邏輯部分,而皮膚樹(shù)負(fù)責(zé)繪圖和點(diǎn)中測(cè)試。而一個(gè)HWND+HDC實(shí)現(xiàn)的皮膚樹(shù),會(huì)在皮膚組合成樹(shù)的時(shí)候,在底下又組合出了一顆WinGDIElement樹(shù)。因此大局上就是:
                控件樹(shù)(負(fù)責(zé)相應(yīng)輸入變更狀態(tài))--> 皮膚樹(shù)(負(fù)責(zé)儲(chǔ)存控件狀態(tài)的可視部分并決定什么時(shí)候需要刷新)-->WinGDIElement樹(shù)(負(fù)責(zé)繪圖整個(gè)窗口)

                這個(gè)時(shí)候,如果我們僅僅需要簡(jiǎn)單的重新繪制窗口的話,那么控件樹(shù)跟皮膚樹(shù)都不需要被訪問(wèn)到,底層僅需要讓W(xué)inGDIElement樹(shù)重新繪制一遍即可。而WinGDIElement的粒度實(shí)際上也不小,因此不會(huì)每一個(gè)圖元都有一個(gè)WinGDIElement從而使得創(chuàng)建出了一大堆對(duì)象的。

                最后一個(gè)設(shè)計(jì)就是在什么時(shí)候才重繪窗口的問(wèn)題。假設(shè)說(shuō)我們現(xiàn)在收到了一個(gè)WM_KEYDOWN消息,最終傳播到了控件樹(shù)里面去,然后修改了10個(gè)控件上面的文字。每當(dāng)你修改文字的時(shí)候?qū)嶋H上都需要重繪,那如何將無(wú)數(shù)次不可控的重繪合并成一次呢?SendMessage(WM_PAINT)是立刻執(zhí)行的,所以Windows自帶的合并WM_PAINT的方法在這個(gè)時(shí)候是無(wú)效的。我所采取的解決方法就是:反正控件樹(shù)的所有消息來(lái)源都是從NativeWindow里面來(lái)的,那實(shí)際上控件樹(shù)發(fā)出一個(gè)重繪請(qǐng)求的時(shí)候,我就會(huì)把NativeWindow的HWND實(shí)現(xiàn)里面的一個(gè)bool變量設(shè)成true,然后當(dāng)NativeWindow每一個(gè)傳播到控件樹(shù)的消息結(jié)束傳播之后,才讀一次那個(gè)變量,如果是true,那么就調(diào)用WinGDIElement進(jìn)行重繪并把變量設(shè)計(jì)成false。壞處是每一個(gè)傳播到控件樹(shù)的消息在處理完之后都必須檢查是否需要重繪,好處是這個(gè)東西被封裝在了NativeWindow的HWND實(shí)現(xiàn)里面里面,無(wú)論是控件樹(shù)、皮膚樹(shù)還是WinGDIElement樹(shù)也好,都在也不需要關(guān)心繪圖時(shí)機(jī)的事情了。

                因?yàn)镚UI被分割成了很多層,而且每一層的都關(guān)心業(yè)務(wù)邏輯的不同部分,所以他們都是可以被替換的。譬如說(shuō)我們可以做成:
                HWND+HDC實(shí)現(xiàn):最普通的方法
                HWND+DirectX:WPF和Silverlight地方法
                單一HWND+多個(gè)虛擬窗口+DirectX:可以在游戲里面用

                無(wú)論下面的繪圖設(shè)備和窗口實(shí)現(xiàn)如何發(fā)生變化,GUI控件的邏輯部分都跟這些實(shí)現(xiàn)嚴(yán)格分離,因此不會(huì)受到影響。而且大部分情況下,我們是不需要擁有一個(gè)跨繪圖設(shè)備的皮膚庫(kù)的,譬如說(shuō)游戲和應(yīng)用程序,外表總不能做成一樣的。對(duì)于那些需要同時(shí)在DirectX和OpenGL上面運(yùn)行的程序(譬如說(shuō)3dsmax),它已經(jīng)有DirectX和OpenGL的公共接口了,因此這些軟件可以利用它們的公共接口來(lái)實(shí)現(xiàn)GUI的繪圖設(shè)備部分,從而在上面構(gòu)造起來(lái)的皮膚自然是可以跨DirectX和OpenGL的。

                這比起一年前作的GUI實(shí)現(xiàn)又進(jìn)了一大步。上一次的GUI嘗試為不同的繪圖設(shè)備抽象一套公共接口,后來(lái)慘死。不知道這次實(shí)際上做出來(lái)的效果如何,拭目以待吧。
            posted on 2011-04-29 19:50 陳梓瀚(vczh) 閱讀(5637) 評(píng)論(13)  編輯 收藏 引用 所屬分類: 2D

            評(píng)論:
            # re: GUI真TAMA難做啊 2011-04-29 21:45 | 千暮(zblc)
            - -bnr 嗯?那個(gè)“press me!” .........  回復(fù)  更多評(píng)論
              
            # re: GUI真TAMA難做啊 2011-04-30 07:43 | misserwell
            老實(shí)說(shuō),以我的能力可以做開(kāi)發(fā),但是我總不愿意去嘗試, 游戲我總覺(jué)得是誤人子弟, 浪費(fèi)別人的時(shí)間無(wú)異于圖財(cái)害命, 不知你可有同感  回復(fù)  更多評(píng)論
              
            # re: GUI真TAMA難做啊 2011-04-30 08:49 | 千暮(zblc)
            @misserwell
            并非都如此 游戲是思維的潤(rùn)滑劑和情感的高密度模擬(好的劇情游戲能讓你用最短時(shí)間體會(huì)到峰回路轉(zhuǎn)以及學(xué)會(huì)站在不同人的角度考慮問(wèn)題 在一種模擬情景 下去發(fā)揮你的判斷的極限能力:你可以不用付出代價(jià)就在一定程度上訓(xùn)練人腦置信策略系統(tǒng))

            古代沒(méi)有計(jì)算機(jī)游戲,但不見(jiàn)得就因此不浪費(fèi)時(shí)間而高效;現(xiàn)代有了游戲,但信息獲取更加便捷,這時(shí)候需要的是在吸收的同時(shí)不斷使大腦適應(yīng)不同的思維和反應(yīng)方式,游戲能夠一定程度上滿足此點(diǎn)


            PS:不過(guò)話說(shuō),vczh這次做的GUI不是游戲GUI,通用GUI要比游戲GUI難做  回復(fù)  更多評(píng)論
              
            # re: GUI真TAMA難做啊 2011-04-30 08:50 | 陳梓瀚(vczh)
            @misserwell
            玩Portal2吧,這個(gè)游戲會(huì)改變你對(duì)游戲的定義的。  回復(fù)  更多評(píng)論
              
            # re: GUI真TAMA難做啊 2011-04-30 08:51 | 千暮(zblc)
            @陳梓瀚(vczh)
            你到處跟人推銷此款游戲 - -bnr 收取了多少好處費(fèi)  回復(fù)  更多評(píng)論
              
            # re: GUI真TAMA難做啊 2011-04-30 08:54 | 陳梓瀚(vczh)
            @千暮(zblc)
            可見(jiàn)該游戲的好玩程度令我愿意免費(fèi)推銷  回復(fù)  更多評(píng)論
              
            # re: GUI真TAMA難做啊 2011-05-16 23:02 | simfe
            簡(jiǎn)單點(diǎn) ,有各duilib可以看看  回復(fù)  更多評(píng)論
              
            # re: GUI真TAMA難做啊 2012-05-21 16:31 | clonne
            您好,對(duì)于GUI庫(kù),我是這么看的:

            現(xiàn)在已經(jīng)是2012年了,我發(fā)覺(jué)整個(gè)軟件行業(yè)都在急速改變,現(xiàn)代的軟件風(fēng)格明顯和以前的不一樣了,在GUI庫(kù)中,我認(rèn)為微軟的WTL庫(kù)非常值得參考,C++的模板就是一個(gè)減輕大量細(xì)節(jié)復(fù)雜度的強(qiáng)力工具。

            根據(jù)我的看法,樓主完全可以不用任何本地控件,不用本地的事件消息系統(tǒng),不用調(diào)用太多本地API,所有的繪制工作都使用3D加速:DirectX/OpenGL,如果是這樣,那么GUI庫(kù)的架構(gòu)就是:

            [GUI]
            |
            [交互]
            ...
            [渲染]
            |
            [接口] - [DirectX|OpenGL]

            當(dāng)然,我沒(méi)描述好,但是可以顯示出,如果按照這種方式,那么基本上就是和游戲差不多了。你只要封裝一些“虛擬控件”的繪制就行了,甚至可以達(dá)到很多絢麗的效果而還不影響性能(3D的性能是操作系統(tǒng)的API所不能比的)而且你根本就不用封裝Win32的消息處理、窗口創(chuàng)建等等,這些甚至直接可以讓DirectX/OpenGL幫你完成,而GUI的交互這些都是有API給你提供的!

            為什么我推介你用這種方式,是因?yàn)槿绻阆肟鏸nux/Win32/FreeBSD/Debian/..等等平臺(tái)使用,即使你能做好一個(gè)通用抽象架構(gòu),也是會(huì)為大量的細(xì)節(jié)所擊倒的。而使用3D庫(kù),你只要處理DirectX/OpenGL的調(diào)用就行了,現(xiàn)在的計(jì)算機(jī)行業(yè)流行的3D庫(kù)就這2個(gè),有大量的擴(kuò)展能使用。

            這是我個(gè)人的看法,我自己現(xiàn)在都不用GUI庫(kù)了,Qt越來(lái)越臃腫,GTK不方便發(fā)行,其他庫(kù)不想學(xué),所以我直接自己調(diào)用本地API,或者封裝下。我也很想把我設(shè)想的GUI庫(kù)做出來(lái)。  回復(fù)  更多評(píng)論
              
            # re: GUI真TAMA難做啊 2012-05-21 16:38 | clonne
            接LS

            樓主,我現(xiàn)在即使是調(diào)用本地的API,也有一個(gè)原則:只創(chuàng)建一個(gè)窗口!不使用Win32的資源、不使用Win32的控件。這讓我減輕了很多細(xì)節(jié)上的煩惱,以前做界面,需要學(xué)習(xí)控件使用、大量的莫名其妙的細(xì)節(jié)問(wèn)題等等等等。而我現(xiàn)在根本就不理系統(tǒng),除了那個(gè)必要的窗口外,所有的"控件"都是我自行繪制(自己繪制控件的開(kāi)發(fā)時(shí)間還沒(méi)有以前掌握那些控件的時(shí)間多)。現(xiàn)在是調(diào)用的系統(tǒng)API來(lái)繪制,以后想開(kāi)始做這個(gè)GUI庫(kù)了,那就是完全使用3D了。  回復(fù)  更多評(píng)論
              
            # re: GUI真TAMA難做啊 2012-05-22 09:10 | 陳梓瀚(vczh)
            @clonne
            我真的只創(chuàng)建窗口剩下的都用Direct2D的說(shuō),而且我的菜單和下拉框也是真的可以彈出窗口外的……不過(guò)盡管如此,架構(gòu)也是十分復(fù)雜的。我倒是不怕復(fù)雜,因?yàn)閣in32那套我也封裝過(guò)。我之所以想這么干,就是因?yàn)閃PF功能那么強(qiáng)大本地C++卻用不了太不爽了,所以我重做一個(gè)——當(dāng)然也就跟你說(shuō)的一樣了。  回復(fù)  更多評(píng)論
              
            # re: GUI真TAMA難做啊 2012-05-22 09:15 | 陳梓瀚(vczh)
            @clonne
            新版本已經(jīng)放倒了gac.codeplex.com  回復(fù)  更多評(píng)論
              
            # re: GUI真TAMA難做啊 2012-05-22 17:31 | 三國(guó)殺
            感覺(jué)是大一統(tǒng)思想,這么多庫(kù)有必要搞成統(tǒng)一接口嘛?舍棄一些有什么不好的!  回復(fù)  更多評(píng)論
              
            # re: GUI真TAMA難做啊[未登錄](méi) 2012-05-22 23:20 | 陳梓瀚(vczh)
            @三國(guó)殺
            那不舍棄有什么不好?  回復(fù)  更多評(píng)論
              
            青青青国产精品国产精品久久久久 | 国产成人无码精品久久久久免费| 99精品久久久久久久婷婷 | 香蕉久久影院| 久久久噜噜噜久久熟女AA片| 久久不见久久见免费视频7| 欧美777精品久久久久网| 伊人久久一区二区三区无码| 国产精品一区二区久久国产| 久久久久无码国产精品不卡| 婷婷久久久亚洲欧洲日产国码AV | 四虎久久影院| 久久久久亚洲Av无码专| 久久精品国产亚洲精品| 国内精品伊人久久久久777| 国内精品久久久久久久亚洲| 国产精品美女久久久| 国产精品久久久久久五月尺| 久久综合九色综合欧美狠狠| 亚洲国产精品久久久天堂| 人人狠狠综合88综合久久| 久久精品国产一区| 午夜精品久久久久久久| 久久婷婷五月综合97色直播| 97精品久久天干天天天按摩| 亚洲va久久久噜噜噜久久狠狠| 久久国产三级无码一区二区| 欧美日韩中文字幕久久伊人| 久久久久无码精品国产不卡| 欧美精品国产综合久久| 亚洲精品无码久久久| 国产精品丝袜久久久久久不卡| 国产精品99久久久久久人| 久久精品无码专区免费青青| 嫩草伊人久久精品少妇AV| 久久综合亚洲色HEZYO社区| 欧美与黑人午夜性猛交久久久 | 精品蜜臀久久久久99网站| 中文字幕无码精品亚洲资源网久久 | 精品国产一区二区三区久久蜜臀| 久久美女人爽女人爽|