• <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  評論-2670  文章-0  trackbacks-0
             
                圣誕節(jié)人山人海啊,根本不能出去玩什么的,妹紙第二天還要考試,所以就在家里呆著,順便把TreeView給做了。源代碼都在Vczh Library++ 3.0(Candidate\GUI\GUIDemo\GUIDemo.sln)。下面是Direct2D渲染出來的帶反鋸齒的TreeView。





                這個TreeView是通過把ListView進行擴展,替換IItemProvider和IItemStyleProvider而完成的。在這里TreeView仍然使用Virtual List模式。程序員將有機會在用戶展開某個TreeNode的時候才開始加載里面的內(nèi)容。這次仍然可以修改template(控件皮膚)。當程序員提供了一個INodeProvider之后,GacUI已經(jīng)準備了兩個現(xiàn)成的類,將INodeProvider轉(zhuǎn)成IItemProvider,將INodeItemStyleProvider轉(zhuǎn)成IItemStyleProvider,從而將樹形結(jié)構轉(zhuǎn)換成列表結(jié)構而使用ListView進行顯示和操作。這個過程也封裝成了一個GuiVirtualTreeListControl。如果不需要提供自己的虛擬化算法的話,直接提供INodeProvider和INodeItemStyleProvider將可以直接使用GuiVirtualTreeListControl顯示樹形結(jié)構。

                將一個虛擬化的樹形結(jié)構轉(zhuǎn)換成一個虛擬化的列表結(jié)構是比較復雜的,特別是當需要高性能的情況下。因此GacUI內(nèi)置了這個算法的支持。一般情況下程序員不需要修改這個過程,直接使用GuiVirtualTreeListControl就可以實現(xiàn)。這一次內(nèi)置的Windows7皮膚同時實現(xiàn)了跟Windows7資源管理器非常相似的外觀(特別是那些三角形)。DirectX版本有反鋸齒,而GDI版本則沒有。

                現(xiàn)在要完成的功能已經(jīng)剩下下面所示(順序與優(yōu)先級無關):
                1、Ribbon
                2、Visual Studio那樣子的Dock Panel
                3、Canvas
                4、完善鍵盤操作
                5、提供類似簡化后的XAML一樣的結(jié)構來保存界面
                6、基于XML(見5)的界面編輯器,類似簡化后的Expression Blend
                7、具有跟XML內(nèi)一樣外觀的,封裝在DLL里的接口(帶反射,以便實現(xiàn)XML,但是被設計成C++使用時將沒有有性能損失)
                8、內(nèi)置FreeScript3.0的支持,用于方便實現(xiàn)各種高級的皮膚,并且如果愿意的話,可以將整個程序用FreeScript3.0寫
                9、UIAutomation
            posted @ 2011-12-25 06:08 陳梓瀚(vczh) 閱讀(3346) | 評論 (15)編輯 收藏

            (很榮幸被華南理工大學軟件學院邀請撰寫此文,關于畢業(yè)那會兒找工作的一些事情)

            前些日子被華南理工大學軟件學院邀請回去參加一些活動,其中包括跟一些師弟師妹們進行座談。期間就有一個人問,要怎么樣才可以去微軟。其實我從來沒有想過這個問題,所以那個時候的答案自然就是微軟的廣告(編程好,數(shù)學好,態(tài)度好)了。09年大四那會兒,剛好碰上了美帝的次貸危機,令我們這些想去美帝的公司被剝削的這幫人倍感艱辛。所幸后來還是過五關斬六將,最后在實習結(jié)束之后成功留了下來。這其中的因果,顯然不是面試的那幾天所能夠決定的,因此還得從hello world講起。

             

            我有幸從初二開始就學習編程。那個時候世界已經(jīng)處于一個現(xiàn)代化的程度了,操作系統(tǒng)都有虛擬內(nèi)存,有圖形界面,有因特網(wǎng),開發(fā)軟件還有集成開發(fā)環(huán)境可用,跟一些老前輩所描述的編譯一個程序還要換幾次磁盤的日子已經(jīng)完全不一樣了。那個時候正值購買電腦半年,處于看見什么東西都感到十分好奇的時候,再加上父親那個時候不太同意我玩游戲,所以我就在想什么時候也自己做幾個游戲,就可以光明正大的玩了。所以在聽到汕頭華僑中學開Visual Basic 5.0的課的時候,感到比較興奮。但是其興奮程度比起初一為了上第一節(jié)電腦課興奮過度,騎自行車超速以至于留了一大堆血沒了幾顆牙的那一天,已經(jīng)可以忽略了。

             

            那個時候還是21世紀的第一年,正處于上網(wǎng)費用巨貴無比、Google還剛起來沒多久基本沒人知道的時候,學習編程要比現(xiàn)在困難很多。當時想尋找什么知識,因特網(wǎng)基本上是沒什么指望的,所以我就有了一個沒事去書店的愛好。沒過多久我就找到了一本《Visual Studio高級圖形程序設計教程》。這本書我很喜歡,插圖十分漂亮,而且還是使用Visual Basic編程繪制的,更是愛不釋手。可惜內(nèi)容過于高深,所以后來就有了初三的時候自學學會初步的立體解析幾何,以及高三上課不聽講僅憑自己看數(shù)學分析后來還被我看明白了的故事。中間因為試圖使用編程繪制很多復雜的圖形和對圖像進行各種復雜的變換,于是每當寫程序之前都要在紙上推導長長的公式。如果程序的運行結(jié)果不對了,根本無從調(diào)試,只好重新推導,借以希望可以發(fā)現(xiàn)公式的幾個bug以解釋為什么會出現(xiàn)錯誤。從此以后我對符號運算就十分拿手。而且做數(shù)學物理作業(yè)也好,為了編程推導公式也好,需要計算的東西太多懶得到處尋找廢紙,從而便獲得了心算復雜過程的本領(可惜現(xiàn)在已經(jīng)喪失了)。這順帶還給我?guī)砹艘粋€好處,就是高考數(shù)學選擇題在發(fā)卷后不許動筆的10分鐘內(nèi)就被我全部心算出答案,而且全對了。

             

            圖形編程做久了,就想起了當初的理想,于是就搞游戲去了。那會兒看到了成都金點工作組開發(fā)的《圣劍英雄傳》,點燃了我開發(fā)RPG的熱情。在經(jīng)歷了幾次失敗之后,我終于在高二的正月初一那一天完成了《天地傳》的所有編碼工作,沒過多久就上傳到了GameRes的網(wǎng)站上。這是我第一個行數(shù)過萬的程序。為了順利完成它,我悟到了很多道理,包括為什么要面向?qū)ο螅瑸槭裁匆獎澐帜K減少互相依賴。這也成為我后來開發(fā)自繪圖形界面和腳本引擎的契機。后來我試圖用OpenGL3D游戲,但是由于很難找到有共同愛好的美工跟我一起做,便作罷了。但是這卻讓我獲得了很多時間,可以投入到圖形界面和腳本引擎之中去。

             

            后來我就萌發(fā)了解釋高級語言的想法。這是我整個編程歷史上的第一個轉(zhuǎn)折點。那個時候我數(shù)據(jù)結(jié)構只會用鏈表,而且編譯原理也好,設計模式也好,都還沒聽過。那個時候去解釋高級語言自然是比較困難的。因此我經(jīng)過很多天的苦思冥想自己想出了一個如今稱之為一遍編譯(也就是很爛)的方法來把一個簡單的高級語言重新處理成一個簡單的指令集語言,就跟匯編長得差不多。那個時候已經(jīng)高三了,所以其實也沒多少時間可以投入在編程上面,因此做出來的第一個原型是一個簡化后的Pascal的解釋器,用Delphi開發(fā)的。現(xiàn)在想起來,里面肯定有巨多內(nèi)存泄露和性能問題,不過當時根本不知道這些東西是什么。在高中畢業(yè)之后的三個月無所事事的日子里,我就重新把這個東西設計了一遍,得到了一個幾十頁的計劃。由于后來沒來得及做完,就打印出來帶去了華南理工大學。

             

            剛進了大學沒幾天,就聽一個大四的師姐說我們的班主任陳健老師是教編譯原理的,于是我就把這一疊紙拿給了她看。她什么也沒說(現(xiàn)在回想起來,只能是那一份設計實在是不堪入目……),就給了我一本編譯原理的課本。我很快就看完了,然后用了里面的知識做了第一個真正意義上的腳本引擎,語法山寨了Java語言的一些簡單的部分,還添加了一個編譯的時候自動把模板參數(shù)都改成Object類型的語法,起了個名字叫JoveScript。后來上了Java的課,發(fā)現(xiàn)Java竟然真的這么干了,讓我覺得好生奇怪。

             

            后來我陸陸續(xù)續(xù)寫了很多腳本引擎。大一的時候做的JoveScript是第一個我覺得還能見人的腳本引擎。第二個就是大二失敗了一整年吸取了很多教訓之后,于大三開發(fā)出的動態(tài)語言,名字叫FreeScript(可以在我的博客http://www.shnenglu.com/vczh上找到)。最近正在打算將其更新到3.0來配合一個正在開發(fā)中的顯卡加速的GUI類庫GacUI。接下來就是在去微軟上海的WCF Tools組實習的那一段時間里面,利用每天晚上的時間完成的一門純函數(shù)式語言叫KernelFP,這后來成為了我的畢業(yè)設計。提交了畢業(yè)設計之后,我又在畢業(yè)前的幾個月時間里面完成了CMinus。這不是編譯原理課程設計上的那個簡單到?jīng)]法再簡單的CMinus,而是一個完整的C語言編譯器(其中函數(shù)指針的語法被我改掉了,但是仍然支持)。其編譯結(jié)果是保存到內(nèi)存中的一段X86二進制代碼,可以將函數(shù)的起始地址強制轉(zhuǎn)換成函數(shù)指針直接在C++程序中使用,這是因為我在生成指令的時候遵守了Visual C++中的一些在MSDN里描述得很清楚的約定。畢業(yè)后我又雄心勃勃地做了NativeX,是一個帶泛型以及concept mappingC語言。前幾個月我又試圖山寨C#,但是無奈C#實在是太復雜,所以轉(zhuǎn)而去做GacUI。圖形界面(GUI)類庫我也寫了不少。繼高中的時候為RPG而開發(fā)的兩個控件類庫之后,在上大學的過程中使用OpenGL開發(fā)的兩次GUI類庫均告失敗。后來還封裝了一次WindowsAPIVczh GUI),試圖讓其易用性接近VCLWinForm。畢業(yè)后我又嘗試發(fā)了若干次基于渲染的GUI,換了幾次架構,一直到現(xiàn)在正在開發(fā)的GacUI才感覺走上了正軌。我在這個過程中得到的一個結(jié)論就是:Windows Presentation Foundation的設計實在是太完美了……在做這些東西之余,我還開發(fā)了三次三維物體的軟件渲染程序,前兩個是在畢業(yè)前做的,最后一個是一年前因為一下子不知道要如何利用業(yè)余時間來充實生活而開發(fā)出來的,目的是用于打發(fā)時間。

             

            在這里我想可以回答一個月前不能很好地回答師弟師妹們的一個問題了。如何能夠在微軟找到工作?因為我把我上面做的這些東西都寫進了簡歷。同時如果你們到了大四才來問這個,就已經(jīng)太遲了……

             

            值得一提的是,我從大三開始指導一名基礎幾乎是零的、比我低兩個年級的軟件學院的一位學生學習編程。為了讓對方在接受我為期3年的訓練之后有扎實的C++基礎、熟練的單元測試編寫水平以及能夠靠直覺給出一些不算太差的設計,我回顧了許多關于C++的內(nèi)容,特別是給指針的幾節(jié)課備課了好幾天,并且每一天都要出一個作業(yè)。在這個過程中我深刻的感覺到,如果要快速提高自己的編程水平的話,你必須總是去做一些你做得出來,但是難度大到只要再難一點點你就做不出來的事情。再這么堅持好些年之后,肯定會進入高手的行列。因此我在安排作業(yè)的過程中,有意推遲了關于指針的內(nèi)容。首先讓對方接受變量和分支循環(huán),然后要養(yǎng)成一個好的風格(譬如說不能老是用一個字母給變量命名之類),然后學會操作數(shù)組,接下來才是關于沒有強制類型轉(zhuǎn)換的指針的一些操作,并且在一個月之內(nèi)做出一個帶單元測試的字符串類。指針的重點是要對方深刻的理解,“指針本身就是一個指向位置的數(shù)字”這么一個概念。為此我特別設計(但沒有實現(xiàn))了一門只帶有一個全局無限長數(shù)組的匯編語言來講述指針背后一些復雜的概念。之后就是一些關于面向?qū)ο蟮闹R、設計模式的知識、還有跟腳本引擎有關的一些東西。該學生的畢業(yè)設計是一個簡單的動態(tài)語言的腳本引擎,并且該腳本引擎的實現(xiàn)正確地運行了我在上面模仿Linq的一個列表處理函數(shù)庫。這個實現(xiàn)閉包一層套一層,到處都在給一個物體添加刪除函數(shù),創(chuàng)建各種延遲執(zhí)行的迭代器,很是能夠考驗一個腳本引擎的實現(xiàn)。對方畢業(yè)后被網(wǎng)易招去了,并且在待遇上給予了一些人文關懷。

             

            自己的編程歷程不僅包括自己在業(yè)余時間內(nèi)做的這些程序,而且也包括在微軟實習和工作的過程。高中的時候就聽說了華南理工大學有微軟俱樂部的事情,再加上自己對微軟也持有一定的向往,因此在入學之后,除了學院的學生會以外,我就一直在密切關注著微軟俱樂部的招新,并且忽略其它所有社團。不過說實話在學生會和微軟俱樂部的工作也純屬打醬油,沒干過什么正事兒。大二的時候微軟搜索技術中心(STC)來微軟俱樂部收簡歷的時候,我在路上碰到了陳健老師,也就是之前提到的班主任,就跟她說了這個事情。后來由于對方說我年齡太小而作罷,因為其它人全部都是研究生。到了大三的時候,陳健老師就跟我提到她可以找老同學幫我投微軟的實習簡歷,因此我于20083月份接到了微軟上海的電話面試。電話面試有兩次,第一次對方是一位HR,第二次則是一位軟件工程師。在第二次電話面試的過程中,我們聊了上面提到的FreeScript,還針對一些數(shù)據(jù)結(jié)構和框架設計的問題進行了熱情洋溢的討論。沒過幾天,我就收到了面試通知,前往上海閔行區(qū)的紫竹數(shù)碼信息港面試。那是我人生中的第一次面試。

             

            微軟的面試安排精確到秒,這跟某些公司比起來要人性化許多,不會動輒浪費別人數(shù)個小時的時間。實習的面試一共有三輪,對話全部使用英語,盡管里面只有一個是外國人。我還依稀記得被那個年輕的老外面試的時候由于過于緊張,而導致一道簡單的問題沒有給出最優(yōu)解的事情。不過他們最終還是讓我進入微軟位于上海的一個WCF Tools小組實習。

             

            這個小組有一位讓我十分尊敬的軟件開發(fā)主管。主管先生是一位熱愛敏捷并且經(jīng)常投身于實踐中的人。他在我長達4.5個月的實習過程中,教給了我很多軟件工程上的東西,而其中最重要的、讓我受益匪淺的則是關于單元測試的內(nèi)容。除此之外,我也體驗了快速迭代、Scrum會議、結(jié)對編程以及基于源代碼版本管理系統(tǒng)(我們使用的是TFS)進行多人協(xié)作開發(fā)的流程。在經(jīng)歷了為TechEd大會修改PetShop制作WCFDemo、為Visual Studio 2010WCF開發(fā)工具修bug和開發(fā)一個具有高度可擴展性的配置文件編輯器之后,我于200812月份結(jié)束了在微軟的實習。經(jīng)過了這次實習,我對源代碼的掌控能力也得到了提高,并且直接體現(xiàn)在我利用業(yè)余時間開發(fā)的項目的代碼質(zhì)量上。

             

            在實習結(jié)束之前,我獲得了一次面試全職員工(FTE)的機會。當時形勢十分嚴峻。2008年美國的次貸危機于10月份正式影響微軟上海,公司在那一段時間決定減少全職員工的招聘數(shù)量。而我是11月份進行轉(zhuǎn)正的面試,結(jié)果這件事情令我十分緊張。后來主管先生表示他的個人建議是希望我畢業(yè)后留下來繼續(xù)工作,讓我吃了一顆定心丸。實習生轉(zhuǎn)全職員工的面試一共有五輪。其中令我印象非常深刻的是有一輪的面試官問了我很多非常復雜的問題,最后還考了我一道關于線索二叉樹在線更新的問題,不過我已經(jīng)記不清楚具體是什么內(nèi)容了。我只記得我花了很長時間終于想到了一個正確的算法之后,時間就結(jié)束了,根本來不及在白板上寫代碼。后來我終于通過了面試,少數(shù)的幾個名額里面終于被我拿走了一個。不過聽說幾個月后限制開始放寬,沒有我面試的時候那么困難了。

             

            在實習和面試的過程中,我覺得華南理工大學軟件學院開設的很多課程其實都是十分有用的,特別是關于數(shù)據(jù)結(jié)構、設計模式和軟件測試的內(nèi)容。這些都是在工作中十分有用的知識,并且也需要在今后的工作中繼續(xù)積累這些東西的經(jīng)驗。只不過因為學院學生人數(shù)眾多,而一個新的學院總是免不了缺乏一些師資力量,所以我有很多同學都表示很難體會到課本中所提到內(nèi)容的作用。想必如今應該比我們那幾年要改善許多了。

             

            面試結(jié)束到獲得offer中間隔了幾十天,最后HR的通知在除夕的那一天終于到來了。之后的半年時間我就在學校里面繼續(xù)做自己的事情,偶爾參加幾個活動介紹經(jīng)驗等等,還有就是跟一些人出去游玩。畢業(yè)后動身前往上海微軟。中間發(fā)生了一些事情,因為名額變動的問題,我雖然拿的是WCF Toolsoffer,但是最后卻被安排到SQL Server組,在此之前我并沒有收到通知。由于我比較不喜歡數(shù)據(jù)庫,對SQL Server了解很淺,所以我做了一年半的SQL Server Management Studio(也就是傳說中的“界面”)的開發(fā)。在這期間我跟同事們傳播了一些關于單元測試、界面開發(fā)、設計模式、Linq和語法分析器的知識。

             

            這一年半的經(jīng)歷讓我成長了許多,主要是比起實習,正式工作的時候總是免不了經(jīng)常要跟別的團隊、公司、民族、國家和物種進行熱情洋溢的廣泛交流,而且還占用了不少的時間。有些時候還要坐飛機前往美帝,感受一下社會主義的優(yōu)越性。正式軟件的界面部分十分復雜,不僅要在操作系統(tǒng)的DPI變動以及本地化(大部分內(nèi)容是把界面上的文字翻譯成別的語言)的過程中界面的布局需要自動調(diào)整,以便不讓一些文字或者按鈕只顯示一半,還要照顧各式各樣的殘疾人(特別是失去視力的人群),并且對于某些自繪的復雜內(nèi)容還要提供一些運行時的接口,使得自動測試團隊可以完成他們的工作。這個經(jīng)歷讓我感受到了開發(fā)一個嚴謹?shù)慕缑媸嵌嗝吹夭蝗菀住A硪粋€感受是關于需求變更的。設計模式的存在就是為了抵御需求變更,這個真理我直到工作之后才能明白。你必須把一個軟件的架構設計得如此之好,才能在需求大規(guī)模變更之后,還能在整體上讓你的代碼是漂亮的、易于修改的、高性能的、并且是安全的。每一次改動都不能是打補丁,你總是需要重構來使得你的代碼在任何一刻都在整體上是好的。為了達到這個目標,就需要熟練掌握并使用設計模式來開發(fā)項目。

             

            微軟的跟別的公司比起來罕有一個好處就是他會給你很多時間,讓你慢慢把軟件做好。而這個好的定義,當然是以功能和可維護性為重點。倘若一段代碼以非常精妙的方法來高速完成一個任務,但是卻復雜到哪怕寫遍了注釋也不能讓后續(xù)維護的人看懂的話,那這段代碼是沒有實用價值的。一段好的代碼,不在于它的設計有多么巧妙,不在于它的算法有多么高深,而在于它可以被幾千個人同時開發(fā)10年,并且在持續(xù)添加功能的過程中,不會因為過于混亂而導致出現(xiàn)了重寫的需要。

             

            后來我因為一些原因申請了到微軟亞洲研究院(MSRA)的人事調(diào)動。20111月份我在獲得了經(jīng)理的批準之后,從上海前往北京參加研究院的面試。這一次面試仍然有五輪。這次面試很難,其中一個面試官因為在我的簡歷上發(fā)現(xiàn)了很多跟編譯器有關的東西之后,決定讓我實現(xiàn)一個strncpy函數(shù),要求是CPU對內(nèi)存的訪問次數(shù)要最少。這包含了很多諸如帶寬、對齊和二進制字節(jié)位移操作等各種問題。方法本身就已經(jīng)很繁瑣,再加上紙上寫代碼總是免不了要犯錯誤,所以我依然沒有時間把整個程序?qū)懲辍A硪粋€面試官老外在年輕的時候也做過一些編譯器的事情,讓我出乎意料的是他在面試的過程中沒有跟我出題目,反而就編譯器的各種算法和問題聊了整整一個小時,基本上我會的知識全部都因為要回答問題而說了出來。之后我跟這個人產(chǎn)生了深厚的友誼。

             

            不久之后我就獲得了調(diào)動的批準。在做了一些包括給上海的SQL Server團隊建立單元測試標準之類的收尾工作之后,我于2011年的4月份前往北京,正式成為微軟亞洲研究院的一員,做一些跟分布式系統(tǒng)相關的研究。

             

            過往的這些事情給了我很多的啟示。在程序員的生涯里面,最重要的就是保持對編程的熱情,不要被生活的瑣事所磨滅。其次是要給自己不斷地創(chuàng)造一些足夠困難但是又有辦法完成的挑戰(zhàn),這樣才可以總是讓自己保持著一個快速前進的狀態(tài)。最后,記得要感謝國家。
            posted @ 2011-12-16 07:34 陳梓瀚(vczh) 閱讀(17237) | 評論 (27)編輯 收藏

                今天給ListControl重構了一下,現(xiàn)在數(shù)據(jù)源、樣式、排版和坐標軸變成了正交的四個模塊。舉個例子,只需要寫一個針對同等行高從上到下的排版算法,那么通過坐標軸變換功能,就可以同時獲得四種方向的排版了。這種功能是相當常見的。對于ListView那種塊狀排版來說,坐標軸變換可以獲得八種方向的排版。最新的代碼發(fā)布在了Vczh Library++3.0(Candidate\GUI\GuiDemo\GuiDemo.sln)貼圖如下:









                GacUI的列表控件通過替換數(shù)據(jù)源、樣式、排版和坐標軸變換等方式,可以被配置成普通列表、ListView、TreeView、甚至是更復雜一點的帶折疊的ListView等等。而且它們都是基于Virtual List的,因此可以無壓力顯示超大數(shù)據(jù)源的內(nèi)容。當然,這需要排版功能的配合,所以我最近一直在給列表控件編寫預定義的很多數(shù)據(jù)源、樣式、排版和坐標軸變換。這樣就可以立刻擁有基本的控件了。如果要擴展的話,只需要把各種組合替換一下,或者自己編寫一個樣式,就可以得到很多好用的列表控件了(譬如說添加一個checkbox到ListViewItem上面)。

                Win7資源管理器那個ListView的ColumnHeader的樣式已經(jīng)開發(fā)完畢了,最后只要通過編寫一個樣式,就可以補上ListView剩下的最后那一個Detail模式了。

            posted @ 2011-12-15 07:08 陳梓瀚(vczh) 閱讀(2387) | 評論 (7)編輯 收藏
                (2011.12.5再次更新) 經(jīng)過了兩個星期的開發(fā),GacUI添加了TabControl和ListView的一部分視圖。這次的ListView的設計的目標是要跟win7的資源管理器相似,TabControl也是依照win7的本地樣式設計的。代碼仍然保存在Vczh Library++3.0(Candidate\GUI\GuiDemo\GuiDemo.sln)里,看圖:





                Direct2D的對于文字的高級渲染效果還沒有實現(xiàn),除此之外,List、Detail、Tile和Information也還沒有做。ListView有兩個模式,一個是跟普通的ListView一樣可以自行添加ListViewItem的,另一個是virtual list模式,需要自己實現(xiàn)一個支持IListViewItemView的GuiListControl::IItemProvider,然后使用ListView的那六個ContentProvider,就可以做出跟ListView一樣的效果,但是性能巨快無比的列表了。因為添加的ListViewItem很多的話,性能的瓶頸會在添加到列表的過程中,而ListView本身絲毫沒有區(qū)別。因此內(nèi)容太多的話建議使用virtual list模式,好處是不需要每一個項目都new一個對象,ListView會用一個item index來回調(diào)出具體的數(shù)據(jù)內(nèi)容。

                根據(jù)上一篇文章的評論,我決定以后發(fā)布GacUI的時候同時提供dll和一對h/cpp兩種選項,其中h/cpp會根據(jù)功能提供幾個裁剪的結(jié)果,而dll總是包含所有功能。使用dll的話,可以做到跟C#的WinForm和WPF一樣,把應用程序的插件寫在另一個dll里面。而h/cpp因為合并的文件太大,因此需要打開Visual C++的/bigobj選項,好處是可以深入使用到內(nèi)部的所有功能,還能根據(jù)自己的需要進行修改,而不局限于dll所提供的GUI部分。

                為了配合GacUI的使用,跟QT的QML一樣,我會升級以前開發(fā)的FreeScript2.0,做出一個3.0的版本來跟GacUI配合使用(這個功能是可選的,裁剪的h/cpp文件對將不強制包含腳本代碼,但是dll總是包含腳本功能)。關鍵的功能是直接支持json(合法的json數(shù)據(jù)即合法的FreeScript3.0代碼),容易使用的異步IO功能,還有跟linq一樣好用的list comprehension,最后當然是跟javascript的語法想當接近但是直接支持class,不會跟javascript一樣曲線救國。相信學習起來的難度非常小。這樣就可以把一部分用C++寫起來比較麻煩的代碼用FreeScript3.0實現(xiàn),并且這部分代碼將可以在GacUI Editor內(nèi)部編輯。GacUI會跟WPF一樣提供兩種調(diào)用方法,一種是C++自己new那些類,另一種就是使用GacUI Editor產(chǎn)生的xml了。我會盡量讓xml方法簡單易用,就跟XAML一樣,不過因為我的對象模型顯然沒有XAML(主要是C#)那么復雜,相比會比XAML容易閱讀和使用。

            =============================
            P.S. 經(jīng)過若干天的艱苦奮斗終于完成了三個View和DirectX的支持,就剩下Detail一種最復雜的View了。放圖:









            posted @ 2011-12-03 07:09 陳梓瀚(vczh) 閱讀(3638) | 評論 (27)編輯 收藏
                因為GacUI文件漸漸增多,為了讓大家便于使用庫,因此有下列三個選項,如果大家有空就評論,針對喜愛程度排序之:

                1、直接引用源代碼。一個文件夾下有很多.h和.cpp,給出文檔,告訴大家需要什么功能的時候需要引用什么東西,然后自行添加自己的工程文件。
                2、存在dll,并且對于一些因為模板的原因無法直接放進dll的功能將失去,需要使用則引用源代碼。
                3、存在dll,并且使用比模板丑陋的方法來將本來使用模板做接口的功能暴露出來。
                4、只有一個.h和一個.cpp文件。我將類庫通過功能切分(只有GUI,只有腳本,包含GUI和腳本和他們的互聯(lián)等等若干選項),給出若干對.h和.cpp。大家選擇需要的那一對添加進工程文件。這樣的話,直接#include那個.h文件就直接擁有了所有功能。而且Visual C++擁有預編譯頭(precompiled header),可以自行將該.h和.cpp進行預編譯,迅猛提高編譯速度(使用stl的時候大家肯定絲毫沒有感覺太多頭文件帶來的問題)。這樣還可以分別清晰地提供windows版本和linux版本等文件對。

                我自己的傾向是使用4,因為某些原因,一旦把代碼寫進dll,有一些優(yōu)美的模板實現(xiàn)的接口將被迫打散(譬如說stl,這些只是例子,我沒有使用stl),所以覺得有些不爽。而且只添加兩個文件(一個.h和一個.cpp),無論使用makefile還是工程文件,無論直接備份或者源碼版本管理(codeplex、source forge、google code、github)都十分方便。
            posted @ 2011-11-23 06:22 陳梓瀚(vczh) 閱讀(4184) | 評論 (20)編輯 收藏
                GacUI今天終于支持菜單了。Windows7的菜單漸變樣式十分復雜,讓我端詳了半個小時才搞清楚他的具體的繪圖方法。代碼上傳到了Vczh Library++ 3.0的Candidate\GUI\GuiDemo\GuiDemo.sln。先看插圖。



                制作菜單十分復雜,里面涉及到了很多黑暗的Windows API的知識,譬如說如何設置一個window的parent又不讓他真正成為子窗口啦(所以parent總是在下面,但是卻不包含它),譬如說如何設置全局鼠標鉤子以便在合適的時候關掉菜單啦,如何不讓菜單在單擊的時候接受焦點啦,很多麻煩的事情。INativeWindow框架的windows實現(xiàn)在Candidate\GUI\NativeWindow\Windows\WinNativeWindow.cpp,可以看到很多處理這種事情的代碼。

                現(xiàn)在GacUI還沒有鍵盤遍歷焦點控件和觸發(fā)快捷鍵的功能,這個等到大部分控件都做完了再添加。下面需要做的有:
                1、帶ItemTemplate的ComboBox
                2、帶ItemTemplate的ListView和TreeView
                3、Ribbon
                4、ToolBar
                5、DocumentView和Canvas
                6、其他雜碎控件

                設計中的Accessibility的功能:
                1、鍵盤操作焦點
                2、不知道要不要提供UIAutomation,聽說在美帝做軟件沒這個的話會很麻煩
                3、根據(jù)Windows的色盲選項來自動更換皮膚

                設計中的其他功能:
                1、控件專用反射功能
                2、因此可以提供UI Editor以及XML啟動的功能
            posted @ 2011-11-12 23:27 陳梓瀚(vczh) 閱讀(3210) | 評論 (9)編輯 收藏
                自從我發(fā)現(xiàn)Windows XP開始就支持Windows Image Component之后,我發(fā)現(xiàn)讀取圖片這個問題瞬間就變簡單了。因此我給GacUI添加了繪制圖片的功能,并做了一個小小的GIF動畫demo。代碼仍然更新在了Vczh Library++3.0上的Candidate\GUI\GUIDemo\GUIDemo.sln上。F5可以直接運行,不過如果要雙擊打開exe的話,則要把GUIDemo\Resources目錄復制到exe目錄下。下面的效果圖展示了一個GIF動畫上覆蓋若干個帶有alpha通道的png圖片:

            (實際效果是會動的)

                因為GacUI試圖隔離Windows API的所有信息,以便可以讓程序員自由添加對操作系統(tǒng)(Windows或其他)和渲染技術(GDI、Direct2D或其他)的支持,因此我不得不暫時封裝了一下。現(xiàn)在的這個接口只能讀,不能做一些高級操作,以后會添加上。使用GacUI編寫上述Demo的代碼如下(具體實現(xiàn)可以去下載并閱讀):
              1 #include "..\..\GUI\GacUI.h"
              2 
              3 GuiBoundsComposition* CreateImageFrame(Ptr<INativeImage> image, int frameIndex=0)
              4 {
              5     GuiImageFrameElement* element=GuiImageFrameElement::Create();
              6     element->SetImage(image, frameIndex);
              7 
              8     GuiBoundsComposition* composition=new GuiBoundsComposition;
              9     composition->SetOwnedElement(element);
             10     composition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement);
             11     return composition;
             12 }
             13 
             14 class GifAnimation : public Object, public IGuiGraphicsAnimation
             15 {
             16 protected:
             17     unsigned __int64            startTime;
             18     GuiImageFrameElement*        element;
             19 public:
             20     GifAnimation(GuiImageFrameElement* _element)
             21         :element(_element)
             22         ,startTime(DateTime::LocalTime().totalMilliseconds)
             23     {
             24     }
             25 
             26     int GetTotalLength()
             27     {
             28         return 1;
             29     }
             30 
             31     int GetCurrentPosition()
             32     {
             33         return 0;
             34     }
             35 
             36     void Play(int currentPosition, int totalLength)
             37     {
             38         unsigned __int64 ms=DateTime::LocalTime().totalMilliseconds-startTime;
             39         int frameIndex=(ms/100)%element->GetImage()->GetFrameCount();
             40         element->SetImage(element->GetImage(), frameIndex);
             41     }
             42 
             43     void Stop()
             44     {
             45     }
             46 };
             47 
             48 void SetupGifWindow(GuiControlHost* host)
             49 {
             50     host->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
             51     INativeImageProvider* imageProvider=GetCurrentController()->GetImageProvider();
             52     Ptr<INativeImage> imageNew=imageProvider->CreateImageFromFile(L"Resources\\New.png");
             53     Ptr<INativeImage> imageOpen=imageProvider->CreateImageFromFile(L"Resources\\Open.png");
             54     Ptr<INativeImage> imageSave=imageProvider->CreateImageFromFile(L"Resources\\Save.png");
             55     Ptr<INativeImage> imageGif=imageProvider->CreateImageFromFile(L"Resources\\Gif.gif");
             56 
             57     GuiBoundsComposition* image1=CreateImageFrame(imageNew);
             58     GuiBoundsComposition* image2=CreateImageFrame(imageOpen);
             59     GuiBoundsComposition* image3=CreateImageFrame(imageSave);
             60     GuiBoundsComposition* image4=CreateImageFrame(imageGif);
             61     
             62     host->GetContainerComposition()->AddChild(image4);
             63     host->GetContainerComposition()->AddChild(image1);
             64     host->GetContainerComposition()->AddChild(image2);
             65     host->GetContainerComposition()->AddChild(image3);
             66 
             67     image1->SetBounds(Rect(Point(1010), imageNew->GetFrame(0)->GetSize()));
             68     image2->SetBounds(Rect(Point(5010), imageOpen->GetFrame(0)->GetSize()));
             69     image3->SetBounds(Rect(Point(9010), imageSave->GetFrame(0)->GetSize()));
             70 
             71     Ptr<GifAnimation> animation=new GifAnimation(image4->GetOwnedElement().Cast<GuiImageFrameElement>().Obj());
             72     host->GetGraphicsHost()->GetAnimationManager()->AddAnimation(animation);
             73 }
             74 
             75 /***********************************************************************
             76 GuiMain
             77 ***********************************************************************/
             78 
             79 void GuiMain()
             80 {
             81     INativeWindow* window=GetCurrentController()->CreateNativeWindow();
             82 #ifdef GUI_GRAPHICS_RENDERER_GDI
             83     window->SetTitle(L"Vczh GUI Demo (GDI)");
             84 #endif
             85 #ifdef GUI_GRAPHICS_RENDERER_DIRECT2D
             86     window->SetTitle(L"Vczh GUI Demo (Direct2D)");
             87 #endif
             88     window->SetClientSize(Size(800600));
             89 
             90     INativeScreen* screen=GetCurrentController()->GetScreen(window);
             91     Rect windowBounds=window->GetBounds();
             92     Rect screenBounds=screen->GetClientBounds();
             93     window->SetBounds(Rect(
             94         Point(
             95             screenBounds.Left()+(screenBounds.Width()-windowBounds.Width())/2,
             96             screenBounds.Top()+(screenBounds.Height()-windowBounds.Height())/2
             97             ),
             98         windowBounds.GetSize()
             99         ));
            100 
            101     GuiControlHost host(new win7::Win7WindowStyle);
            102     SetupGifWindow(&host);
            103     host.SetNativeWindow(window);
            104 
            105     GetCurrentController()->Run(window);
            106 }


            posted @ 2011-11-06 01:00 陳梓瀚(vczh) 閱讀(2235) | 評論 (5)編輯 收藏
                GacUI完成了文本框控件和列表控件。本著可以替換Template的原則開發(fā)的列表控件,ItemTemplate也是可以替換的。下面的Demo展示了運行時替換ItemTemplate的效果。GacUI的列表控件都是強制VirtualList的,因此數(shù)據(jù)跟數(shù)據(jù)的表現(xiàn)被分開處理。如果不使用默認提供的ItemTemplate的話,可以開發(fā)自己的ItemTemplate替換進去。







                在點擊左邊的列表的時候,右邊的控件并不是重新創(chuàng)建的,僅僅替換了一個ItemTemplate。替換了之后,數(shù)據(jù)會立刻作用在新的ItemTemplate上面,并顯示新的列表的樣式。下面兩個圖是Direct2渲染的普通控件和文本框控件:





                Demo的代碼可以在Vczh Library++3.0的Candidate\GUI\GUIDemo\GUIDemo.sln下找到。
            posted @ 2011-11-02 03:08 陳梓瀚(vczh) 閱讀(2464) | 評論 (10)編輯 收藏
                大家肯定還記得上次我給NativeX開發(fā)IDE(參見這里這里)的事情。IDE使用C#進行開發(fā),然后遇到了一個瓶頸,其中的一個問題就是GDI+渲染那么多各種顏色的文字實在是太慢了。再加上我也一直很想用C++開發(fā)界面,但是又找不到一個可以跟WinForm或者WPF一樣既簡單易用又靈活的東西,所以決定自己寫。名字就叫GacUI好了,GPU Accelerated C++ User Interface。

                當然這并不是我第一次開發(fā)GUI了,開發(fā)GUI是一個慘痛的歷史。在我還在讀高中的時候,為了做一個RPG游戲就用Delphi開發(fā)了一套基于GDI的GUI。高三的時候升級了它。大一的時候使用OpenGL為了同樣的目的開發(fā)了一次,大三的時候封裝了API但是發(fā)現(xiàn)API真是超級復雜結(jié)果無法封裝所有必須的功能,去年試圖抄WPF但是由于我處理得不好性能太慢失敗了。因此現(xiàn)在總結(jié)了之前開發(fā)GUI的所有經(jīng)驗教訓,重新開發(fā)一套C++的GUI系統(tǒng)。

                這個系統(tǒng)的特征如下:
                1、排版靈活。現(xiàn)在Left, Top, Width, Height已經(jīng)不是控件的屬性了,轉(zhuǎn)而放在了另一個層次里面。簡單來說就是,GacUI支持在一個窗口上放很多的排版線,可以做各種復雜的排版,最后一個控件必須依附在排版線的矩形區(qū)域上面。可想而知,并不是所有的控件都是按照Left, Top, Width, Height來確定位置的。不過大家也不用害怕,只是這些屬性已經(jīng)被封裝到特定的一組對象。
                2、樣式靈活。簡單來說就是換皮膚,但是這并不像VCLSkin那樣只是重繪,這里的樣式允許你把整個控件的外觀都換掉(譬如說跟MacOS一樣滾動條的兩個方向按鈕都挨在一起),就跟WPF更換控件的template一樣。
                3、支持多渲染器。目前我內(nèi)置了GDI和Direct2D渲染,大家根據(jù)需要可以開發(fā)自己的渲染器——不過我覺得一般都用不上。
                4、跨平臺。這里指的是我把CreateWindow那樣子的東西給隔離了,轉(zhuǎn)而去實現(xiàn)一個INativeWindow(包括創(chuàng)建刪除打開繪圖設備等)。我默認提供了一個基于CreateWindow的實現(xiàn),然后可選創(chuàng)建GDI或者Direct2D繪圖設備。哪怕是將來大家想將GUI移植到Windows8 Metro設備(因為直接支持DirectX渲染,把控件的樣式改成MetroUI那種感覺就行了)、在游戲里面創(chuàng)造虛擬窗口、或者干脆放到Linux上,僅需提供一套INativeWindow并掛載Linux上的高性能繪圖設備(我知道linux上面的某些繪圖api性能巨差,應該避免使用,個人推薦OpenGL)。
                5、渲染方便。渲染的方法是,我提供了很多預定義圖元,可以將圖元綁定到排版線上來決定其尺寸,最后每一個圖元都會有渲染器安排一個圖元渲染算法來渲染出來。如果你需要的外觀剛好可以用預定義的圖元表達的話,那可以直接拼裝。否則,開發(fā)新的圖元即可。

                控件的邏輯、樣式、排版、渲染四套工序已經(jīng)完全隔離。舉個例子,我們都知道GroupBox和Panel除了是容器以外沒有任何區(qū)別,因此我給GuiControl類編寫了Win7GroupBoxStyle和Win7WindowStyle兩套樣式,使用不同的組合就可以創(chuàng)造出不同的外觀,不需要所有的東西都因為外觀有一點點變化就寫成兩個控件了。因此我們可以知道,如果你需要特別的外觀,那么就寫一個自己的Style。GacUI是開源的(不過暫時沒有自己的項目首頁,我把代碼放在了Vczh Library++ 3.0的Candidate\GUI\GUI\下面),因此開發(fā)樣式的時候還可以借鑒我預定義提供的Win7外觀樣式包的代碼。

                因為沒開發(fā)完,所以先貼個圖。下面的圖因為“可編輯文本元素”的Direct2D渲染代碼還沒寫,所以只給出GDI得結(jié)果。Direct2D因為自帶全屏幕去鋸齒,所以比這個要好看很多。下一個IDE我就用GacUI來開發(fā)了,C#開發(fā)IDE難度很高啊,膜拜Mono開發(fā)SharpDevelop那幫人,我還是用C++就好了。



            posted @ 2011-10-22 19:34 陳梓瀚(vczh) 閱讀(5079) | 評論 (14)編輯 收藏

                之前一邊做腳本引擎,一邊山寨一個自繪的native C++的GUI框架并且可以切換GDI或者Direct2D渲染模式。因為抄了WPF的那種高級自動布局功能,所以必然需要知道如何測量文字大小。Direct2D測量文字大小比較麻煩,不像GDI有直接函數(shù),并且用中英文搜好像都沒人直接給出結(jié)果,還有人在博客上寫“這種事情好像辦不到”這樣的文字。不過經(jīng)過我遍歷MSDN,還是找到了一個曲線救國的方法的,直接上代碼:

                首先是創(chuàng)建IDWriteTextFormat:

             1                     IDWriteFactory* dwriteFactory=GetDirectWriteFactory();
             2                     IDWriteTextFormat* format=0;
             3                     HRESULT hr=dwriteFactory->CreateTextFormat(
             4                         fontProperties.fontFamily.Buffer(),
             5                         NULL,
             6                         (fontProperties.bold?DWRITE_FONT_WEIGHT_BOLD:DWRITE_FONT_WEIGHT_NORMAL),
             7                         (fontProperties.italic?DWRITE_FONT_STYLE_ITALIC:DWRITE_FONT_STYLE_NORMAL),
             8                         DWRITE_FONT_STRETCH_NORMAL,
             9                         (FLOAT)fontProperties.size,
            10                         L"",
            11                         &format);
            12                     if(!FAILED(hr))
            13                     {
            14                         format->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
            15                         return format;
            16                     }
            17                     else
            18                     {
            19                         return 0;
            20                     }

                fontProperties是我自定義的一個結(jié)構就不用去管它了,參考MSDN就知道CreateTextFormat如何使用了。其中fontProperties.fontFamily是字體的名字。然后IDWriteTextFormat就扮演著GDI的“字體對象”的角色,可以用ID2D1RenderTarget進行繪制。ID2D1RenderTarget除了用IDWriteTextFormat當字體以外,還可以用IDWriteTextLayout當“添加多余信息的更復雜的字體”。測量文字的關鍵正是在這里。

                接下來我們借助IDWriteTextFormat來創(chuàng)建IDWriteTextLayout:

             1                     IDWriteTextLayout* textLayout=0;
             2                     HRESULT hr=GetDirectWriteFactory()->CreateTextLayout(
             3                         oldText.Buffer(),
             4                         oldText.Length(),
             5                         textFormat,
             6                         0,
             7                         0,
             8                         &textLayout);
             9                     if(!FAILED(hr))
            10                     {
            11                         DWRITE_TEXT_METRICS metrics;
            12                         hr=textLayout->GetMetrics(&metrics);
            13                         if(!FAILED(hr))
            14                         {
            15                             minSize=Size((int)ceil(metrics.widthIncludingTrailingWhitespace), (int)ceil(metrics.height));
            16                         }
            17                         textLayout->Release();
            18                         return;
            19                     }

                這里看minSize就知道如何測量文字的字體了。

                在這里放一張暫時的圖片。我抄了WPF的那種方法,從布局和繪圖元素直接開始可以構造GUI,因此演示了如何使用這些東西來創(chuàng)造一個Win7的按鈕(帶動畫的哦)打開Vczh Library++3.0,下載代碼并打開Candidate\GUI\GuiDemo\GuiDemo.sln,按F5就可以看到了效果了:



                這一個是Direct2D渲染的結(jié)果(我在工程文件指定了DXSDK的絕對路徑,如果你們安裝的地方不同改掉它既可編譯了)。按鈕基本上跟win7的效果一摸一樣,但是這里使用Direct2D進行渲染。當按鈕尺寸變化的時候,那個復雜的邊框和里面的兩個漸變和文字都可以自動對齊——但是這并不是hard code的,而是GUI的“布局功能”可以配置成這個樣子。像這兩個按鈕一直處于右下角也是“布局功能”可以提供的功能。大家可以理解為這東西類似于C#的TableLayoutPanel。

                現(xiàn)在剛剛做好了按鈕——跟WPF一樣可以更換template,不過因為反正沒人需要動態(tài)更換template所以我把template寫在了構造函數(shù)里面,因此換膚這種事情就變得相當簡單了——只要用布局功能跟圖元拼湊成一個復雜的圖形,然后實現(xiàn)各個控件所規(guī)定的“template接口”響應外觀控制的消息就行了,內(nèi)置動畫支持(這個要運行的時候才能觀察到)。

                為了方便,我在工程里面除了Debug和Release以外還加入了DebugDirect2D和ReleaseDirect2D兩個配置,可以自由切換觀看demo。


            posted @ 2011-10-11 07:42 陳梓瀚(vczh) 閱讀(5534) | 評論 (11)編輯 收藏
            僅列出標題
            共35頁: First 4 5 6 7 8 9 10 11 12 Last 
            久久久久久综合网天天| 无码任你躁久久久久久老妇App| 色播久久人人爽人人爽人人片aV | 狠狠色噜噜色狠狠狠综合久久 | 久久强奷乱码老熟女网站| 国产精品热久久无码av| 青青草原综合久久| 久久最近最新中文字幕大全 | 波多野结衣中文字幕久久| 久久香综合精品久久伊人| 久久丫精品国产亚洲av不卡 | 久久婷婷五月综合色奶水99啪| 国产精品久久久久久久久软件 | 精品久久久久久久国产潘金莲| 欧美国产精品久久高清| 亚洲精品99久久久久中文字幕 | 亚洲精品无码专区久久久| 亚洲成色WWW久久网站| 性欧美丰满熟妇XXXX性久久久| 日韩精品久久无码人妻中文字幕| 狠狠色丁香久久婷婷综合五月 | 久久综合给合久久狠狠狠97色69| 中文国产成人精品久久不卡| 国产成人久久精品一区二区三区| 久久精品国内一区二区三区| 久久996热精品xxxx| 久久久久久精品免费看SSS| 一本色道久久综合亚洲精品| 久久99国产精品久久久| 久久综合伊人77777| 久久久午夜精品| 国产成人久久精品一区二区三区| 久久久不卡国产精品一区二区| 亚洲中文字幕无码一久久区| 9191精品国产免费久久| 亚洲国产精品无码久久久秋霞2| 久久青草国产手机看片福利盒子| 欧美亚洲国产精品久久高清| 久久免费视频观看| 久久综合国产乱子伦精品免费| 日韩va亚洲va欧美va久久|