• <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
             

                GacUI的類庫說明文檔已經可以生成了!利用了之前的這篇博客描述的pdb信息抽取并和XML注釋合并的技術,成功寫了一系列工具來從這些信息里面生成靜態html文檔。現在的XML注釋只寫了1/3,所以生成的文檔還不全。

                之所以做這個工具,而不用Doxygen,是因為Visual C++對XML注釋有著良好的支持。如果你為你的代碼寫了XML注釋,那么在智能提示里面還可以看到成員的文檔。但是這個形式的注釋并不是Doxygen所接受的,而微軟或其它開源工具對XML注釋生成文檔的工具僅限于.net程序(包括C++/CLI)。本來GacUI的release所提供的代碼是幾個壓縮過的cpp和h文件,所以可以用一個C++/CLI工程去編譯這個代碼從而使用那些軟件來產生文檔的。不過本著造福大眾兼磨練自己的精神,就寫了一個專門針對VC++的Native C++工程編譯產生的xml注釋文件和pdb文件抽取數據合成文檔的工具。

                下面是文檔的截圖:





                文檔生成工具的代碼已經提交到了Gac Library(http://gac.codeplex.com)上面。目前的話,只需要打開<root>\Libraries\GacUI\GacUISrc\GacUISrc.sln,使用debug編譯之后,運行<root>\Libraries\GacUI\Public\Release.bat,就會在Temp\StaticHtmpDoc\目錄下面產生一系列的html文件。目前這個文檔的根節點是reference_gacui.html文件。

                在Release.bat里面可以看出,我使用了<root>\Common\Tools\下面的幾個exe程序來讀pdb、讀xml注釋并生成靜態html文檔。在與exe同名的目錄下面,有這些工具的源代碼。目前這個工具還不能處理模板類的xml注釋,這個功能不久之后就會加上去。

            posted @ 2012-04-01 00:43 陳梓瀚(vczh) 閱讀(3586) | 評論 (9)編輯 收藏
                我最終還是給GacUI專門申請了一個codeplex的項目主頁:http://gac.codeplex.com。Vczh Library++ 3.0上面上傳的代碼大多是實驗產品,相比把GacUI也放在上面發布不太合適,所以開了一個新項目。新的項目使用MS-PL協議。MS-PL的協議跟BSD、MIT和Apache等協議幾乎是一樣的,除了“他人不得用MS-PL協議的代碼申請專利”。這是一個避免糾紛的好方法。

                GacUI現在還沒全部完成。目前正在制作文檔和教程。文檔應該要么是html要么是pdf,教程會跟文檔合并到一起去。GacUI大體上還是能用,不過目前處于alpha狀態。
                已經完成的功能有:
                    1、GDI和Direct2D渲染器
                    2、皮膚系統
                    3、各種基于MVVM模式設計的控件
                    4、可切換的窗口系統。我目前只提供了一個用Windows窗口做窗口骨架的provider,如果你們高興的話也可以去寫一個虛擬的,然后就可以選擇Direct2D渲染器,最后合并到游戲里面。
                還沒完成的功能有:
                    1、按鍵操作。目前只有文本框接受按鍵,列表和菜單什么的還沒有,快捷鍵功能也還沒有。
                    2、基本對話框的支持。這個我應該不會自己做,而是使用API提供的打開保存文件對話框什么的。
                    3、更加高級的控件,譬如Ribbon、VisualStudio那樣子的Docking等等。
                    4、其它。
                在這次完成基本的文檔和教程之后,將會繼續開發GacUI剩余的部分。

                之前的實驗,讓我最終采用代碼方式來發布GacUI,并且用抓取PDB地方法,結合Visual C++提供的XML注釋來生成文檔的reference部分。GacUI雖然文件上百,不過我已經寫了一個代碼生成器,將他們合并成了3個h文件和2個cpp:Vczh Library++3.0的公共部分一個cpp;GacUI的部分一個cpp。這有利于我將來繼續提供腳本引擎或者其他東西,可以共享代碼一起編譯。現在使用GacUI,只需要將這5個文件添加進工程就好了。而且cpp只有兩個,所以如果項目使用預編譯頭(precompiled header)的話,給這兩個cpp分別加上#include "stdafx.h"也將十分簡單。
            posted @ 2012-03-24 02:31 陳梓瀚(vczh) 閱讀(4354) | 評論 (7)編輯 收藏
                 摘要: 終于到了激動人心的時刻了。今天的博客內容將永遠消除Visual Studio的本地C++XML注釋編譯出來的XML文檔沒有辦法生成可讀文檔的根本原因。

            首先介紹一下C++的XML注釋。在啟用注釋之前,我們必須先去工程屬性里面,把[C/C++ -> Output Files -> Generate Xml Documentation Files]設置成Yes。這樣我們就可以在C++的類啊函數上面寫XML注釋,然后被編譯成一份帶有符號鏈接的XML注釋集合。這里先給一個GacUI的XML注釋的例子:  閱讀全文
            posted @ 2012-03-09 17:04 陳梓瀚(vczh) 閱讀(6775) | 評論 (7)編輯 收藏
                 摘要: GacUI到了撰寫文檔的時候了。雖然GacUI本身的功能還沒有全部完成,但是發布一個alpha版還是可以的。因此GacUI需要一份文檔。自從.net語言支持XML注釋生成文檔之后,Visual Studio的本地C++也支持使用XML注釋了。只要打開了[工程屬性 -> C/C++ -> Output Files -> Generate XML Documentation Files]之后,Visual Studio會在編譯本地C++工程之后,將所有的XML注釋收集起來,放在和可執行文件同一個目錄下的里面。然后我就嘗試bing了一下有沒有從C++的XML文檔生成可讀文檔的工具,結果發現只有.net才支持。

            后來我稍微研究了一下(詳細內容將會在下一篇博客透露),發現之所以沒人寫這個工具,是因為只有.net的可執行文件才包含足夠多的元數據,而且這些元數據是必須的,否則無法生成一個完整的文檔。舉個例子,雖然包含了xml注釋和該注釋所在的符號,但是卻沒有包含該符號的結構信息。結果你試圖生成一個函  閱讀全文
            posted @ 2012-03-09 14:43 陳梓瀚(vczh) 閱讀(7034) | 評論 (0)編輯 收藏
                 摘要: 在制作GacUI讀pdb生成代碼的過程中,感受到了C++語言設計和dll的需求之間的鴻溝。對于一個充分利用了C++各種功能的類庫來說,制作成dll具有非常大的困難,特別是在函數返回POD(Plain Old Data)的引用,和輸入輸出帶有泛型的類上面。所以現在還是決定以源代碼的方式來發布GacUI。但是pdb生成代碼并沒有白做,因為反射還是存在的。但是因為GacUI一共有48000行代碼,80多個源代碼文件,直接發布使用起來總是不方便。所以我寫了個小工具,根據xml的配置來將源代碼合并成少數幾個比較大的代碼文件。這樣使用的時候,只需要直接把幾個cpp拖進工程里面,就可以使用了。而且根據之前發布的一個投票,似乎大家也最喜歡這種方法。因此這次的決定,僅僅刪掉了作為backup plan的dll方法。

            這里我給出小工具的代碼和配置文件。這個配置文件是基于GacUI做出來的,不過大家可以修改它,以便用于自己的工程上面:  閱讀全文
            posted @ 2012-02-29 05:34 陳梓瀚(vczh) 閱讀(4012) | 評論 (9)編輯 收藏
                 摘要:     從pdb讀取類聲明花了很久,從類聲明產生反射和dll接口花的時間更久啊,很多細節問題需要解決。文章的代碼已經保存在了Vczh Library++3.0(\Tools\Release\SideProjects\GacUI\GacUI.sln)。    反射和dll接口的工作進行了一半。現在把類、函數、屬性和各種類型都聲稱了出來,但是...  閱讀全文
            posted @ 2012-02-21 10:33 陳梓瀚(vczh) 閱讀(3552) | 評論 (3)編輯 收藏
                GacUI終于進入制作dll的階段了。昨天上傳了一個新的工程,在Vczh Library++3.0(E:\Codeplex\vlpp\Workspace\Tools\Release\SideProjects\GacUI\GacUI.sln)。這里面一共有三個工程,有兩個是工具,一個是dll。

                為了編譯出帶反射的控件庫,因此每一個控件都可以獲得一個ITypeDescriptor對象。但是控件庫一共有幾十個類上千個函數,我不可能一個一個去實現的(請想想實現IDispatcher的時候)。根據上一篇博客討論過技術,我將使用一個程序來讀pdb生成C++代碼。詳細的計劃如下:

                1:制作一個_GacPDB工程。這是一個exe,但是是沒用的,唯一的用處就是他引用了GacUI.dll所需要的所有源代碼,然后靠編譯器產生PDB文件。
                2:制作一個_TranslatePDBtoXML工程。這是一個exe,從PDB抽取類聲明。
                3:制作一個_TranslateXMltoCode。顧名思義,不過現在還沒做,原理是一樣的。
                4:GacUI.dll。這個dll包含了所有的控件的實現,還有_TranslateXMLtoCode產生的所有代碼。

                現在我的目標是,先編譯_Translate*工程,然后編譯_GacPDB產生pdb后自動調用它們,生成代碼結束之后開始合并編譯GacUI.dll。所有的這些東西都需要在VisualStudio的“Rebuild Solution”里面完成。為了完成這個目標,我創建這些工程之后,按照下面的方法修改了工程屬性:
             1 _TranslatePDBtoXML:
             2     post build action:
             3         copy $(ProjectDir)msdia100.dll $(SolutionDir)$(Configuration)\msdia100.dll
             4 _GenPDB:
             5     references:
             6         _TranslatePDBtoXML
             7     post build action:
             8         $(SolutionDir)$(Configuration)\_TranslatePDBtoXML.exe $(SolutionDir)Debug\_GenPDB.pdb $(SolutionDir)_GenPDB.xml
             9 GacUI:
            10     references:
            11         _GenPDB

                1:工程A引用了工程B的話,那么只有當B完全編譯好之后才會編譯A。因此上面的配置將阻止三個工程平行編譯,強制他們按照_TranslatePDBtoXML、_GenPDB和GacUI的順序來。
                2:_TranslatePDBtoXML編譯好之后,會把它依賴的msdia100.dll復制到編譯出來的exe旁邊,以供接下來調用。
                3:_GenPDB編譯好之后,pdb已經產生了。這個時候它會自動調用上一步編譯出來的_TranslatePDBtoXML,讀取pdb,輸出xml
                4:(接下來要做的)調用_TranslateXMLtoCode,輸入xml,輸出C++代碼
                5:這個時候,生成的C++代碼已經就緒了,所以開始編譯GacUI。

                附加的好處還有一個。因為_GenPDB引用了GacUI的cpp,所以當GacUI的源代碼修改的時候,_GenPDB也會感應到,從而在下次編譯GacUI的時候先開始編譯_GenPDB。并且因為GacUI依賴了_GenPDB,所以_GenPDB仍然會先編譯。而且這種依賴關系是無害的,因為_GenPDB沒有輸出lib,因此GacUI.dll在運行的時候完全不需要_GenPDB.exe的存在。

                好了。那把一個個的cpp文件添加到_GenPDB也是在太麻煩了,所以我投機取巧了一下:
             1 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiApplication.cpp"
             2 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiBasicControls.cpp"
             3 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiListControls.cpp"
             4 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiTextControls.cpp"
             5 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiWindowControls.cpp"
             6 //---------------------------------------------------------------
             7 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiComboControls.cpp"
             8 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiContainerControls.cpp"
             9 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiListViewControls.cpp"
            10 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiMenuControls.cpp"
            11 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiTextListControls.cpp"
            12 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiTreeViewControls.cpp"
            13 //---------------------------------------------------------------
            14 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\Styles\GuiCommonStyles.cpp"
            15 #include "..\..\..\..\..\Candidate\GUI\GUI\Controls\Styles\GuiWin7Styles.cpp"
            16 //---------------------------------------------------------------
            17 #include "..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsComposition.cpp"
            18 #include "..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsElement.cpp"
            19 #include "..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsEventReceiver.cpp"
            20 #include "..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsHost.cpp"
            21 #include "..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsTextElement.cpp"
            22 //---------------------------------------------------------------
            23 #include "..\..\..\..\..\Candidate\GUI\GUI\NativeWindow\GuiNativeWindow.cpp"
            24 #include "..\..\..\..\..\Candidate\GUI\GUI\NativeWindow\Windows\WinNativeWindow.cpp"
            25 //---------------------------------------------------------------
            26 #include "..\..\..\..\..\Candidate\GUI\GUI\Reflection\GuiTypeDescriptor.cpp"
            27 //---------------------------------------------------------------
            28 #include "..\..\..\..\..\Library\Basic.cpp"
            29 #include "..\..\..\..\..\Library\Exception.cpp"
            30 #include "..\..\..\..\..\Library\String.cpp"
            31 #include "..\..\..\..\..\Library\Threading.cpp"
            32 #include "..\..\..\..\..\Library\Collections\Operation.cpp"
            33 //---------------------------------------------------------------
            34 #include <Windows.h>
            35 
            36 int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
            37 {
            38     return 0;
            39 }

                啊哈哈哈哈(拖走

                VisualStudio的功能是強大的。只要善于使用,或者配合MSBuild,所起到的威力將毫不亞于某些著名工具鏈。而且VisualStudio編譯器產生的文件,基本上VisualStudio都有提供API供你閱讀,所以也可以做很多事情,譬如我這篇文章說的這樣,充當了一個編譯器的擴展,而且完美集成。
            posted @ 2012-01-13 22:09 陳梓瀚(vczh) 閱讀(7400) | 評論 (7)編輯 收藏
                C++的反射一直是一個很多人都在做的事情。不過今天我終于有了一個簡單的想法,當然只對VC++編譯出來的程序有效。首先看下面的一個單元測試:

                如果我們有下面的代碼:
            1     class A{};
            2     class B:public A{};
            3     class C:public A{};
            4     class D:public B, public C{};
            5     class E:virtual public A{};
            6     class F:virtual public A{};
            7     class G:public E, public F{};
                那么下面的事情一定會發生:
            1     D d;
            2     A& da1=static_cast<B&>(d);
            3     A& da2=static_cast<C&>(d);
            4     TEST_ASSERT(&da1!=&da2);
            5     
            6     G g;
            7     A& ga1=static_cast<E&>(g);
            8     A& ga2=static_cast<F&>(g);
            9     TEST_ASSERT(&ga1==&ga2);

                對于這種virtual繼承的事情,到這里還是很容易理解的。那現在我們來更進一步:
             1     class Base
             2     {
             3     public:
             4         size_t size;
             5 
             6         Base()
             7             :size(0)
             8         {
             9         }
            10     };
            11 
            12     template<typename T>
            13     class Derived : public virtual Base
            14     {
            15     public:
            16         Derived()
            17         {
            18             if(size<sizeof(T)) size=sizeof(T);
            19         }
            20     };
            21 
            22     class H : public Derived<H>{};
            23     class I : public H, public Derived<I>{};
            24     class J : public I, public Derived<J>{};

                首先,H、I和J都各自擁有自己的唯一的一個Base。J雖然繼承了Derived<H>、Derived<I>和Derived<J>,但是始終只擁有一個Base。因為Base是virtual繼承的。

                其次,sizeof(Derived<T>)>sizeof(Base)始終是成立的,因為Base的virtual繼承導致了Derived<T>里面至少要保存一個指向Base(或者可以用來找到Base)的指針。這個條件很重要,因為這導致了sizeof(J)>sizeof(I)這個條件是恒成立的。

                好了,那么來看J。由于C++并沒有規定多重繼承的時候,幾個父類的構造函數的順序是什么,所以我們需要sizeof(J)>sizeof(I)這個條件。為什么呢?看Derived類的構造函數——它之讓sizeof(T)更大的數據覆蓋Base里面的數據。

                所以我們就可以確定下面的事情:
            1     const H& h=H();
            2     const H& i=I();
            3     const H& j=J();
            4     TEST_ASSERT(h.size<i.size);
            5     TEST_ASSERT(i.size<j.size);
            6     TEST_ASSERT(h.size==sizeof(H));
            7     TEST_ASSERT(i.size==sizeof(I));
            8     TEST_ASSERT(j.size==sizeof(J));

                無論J的三個Derived<T>的構造函數誰先執行,最后能夠留下來的Base里面的數據肯定是Derived<J>里面的數據。講到這里應該很清楚了。如果讀者還沒想到這跟反射有什么關系的話,那么請想一下,如果Base除了size以外,還有一個ITypeDescriptor** typeDescriptor;成員。然后Derived改成這樣:
             1 template<typename T>
             2 class Derived : 
             3 {
             4 public:
             5     static ITypeDescriptor* type;
             6 
             7     Derived()
             8     {
             9         if(){size=sizeof(T); typeDescriptor=&type;}
            10     }
            11 };

                那么不管你的J拿到手里的類型是什么,哪怕是const H& j,那么j.typeDescriptor肯定就是&Derived<J>::type;

                到這里還沒有跟VC++有關系的東西。假設ITypeDescriptor是一個足夠代表反射功能的高級接口的話,那么我們要怎么實現它呢?我們自己來按照字符串去調用各種函數什么的去實現它肯定麻煩到死了。但是如果大家還記的我前面的這篇博客文章的話,那么大家肯定想到了,我們可以寫一個程序來替我們讀pdb生成ITypeDescriptor的代碼,還有把具體的對象賦值進Derived<T>::type里面去的一個初始化函數!啊哈哈哈!當然pdb只能是從Visual C++編譯出來的,就算不是,也至少只能是Windows上面的。不過對GacUI來說并無所謂。因為我只要把GacUI在VisualStudio里面編譯生成反射的代碼,這個生成之后的代碼我還是能放到其他地方編譯的。到時候我只要連同這段代碼一并發布就好了。

                當然,這個程序不僅僅可以幫我實現ITypeDescriptor,還可以幫我實現C語言和C++語言的dll接口的實現,因為dll里面肯定不能暴露模板的。下面就僅需要我去把它做出來就可以了。至此,我們讓一個類支持反射的代價很低——只要讓他繼承自Derived<自己>就好了。
            posted @ 2012-01-11 03:39 陳梓瀚(vczh) 閱讀(8779) | 評論 (7)編輯 收藏
                GacUI今天完成了可自定義格式的ComboBox。ComboBox分為兩種,一種是空空如也全部要自己做的只提供下拉功能的GuiComboBoxBase,另一種是在構造函數接受一個GuiSelectableListControl從而自動將列表與ComboBox關聯起來的GuiComboBoxListControl。因為列表控件是MVC和virtual mode的混合體,所以如果要自動把列表的文本顯示到ComboBox上面去的話,那么加進去的基類為GuiSelectableListControl(預定義的所有列表控件的基類都是這個,包括TreeView)所提供的ItemProvider必須實現一個GuiListControl::IItemPrimaryTextView的View。當然,沒有這個View也可以,因為ComboBox同時也可以讓你自定義“選中列表”的顯示方法——不一定非的是一個字符串,也可以是圖片啊色塊什么的。

                最新的代碼可以在Vczh Library++3.0(Candidate\GUI\GuiDemo\GuiDemo.sln)中找到,運行結果如圖所示:



                這個ComboBox之所以直接跟GuiListControl結合起來,還是歸功于GuiListControl的MVC和virtual mode混合功能的設計。GuiListControl可以自定義數據源、數據顯示樣式、數據排列算法以及坐標軸的。其中數據源運行時可修改但是不可直接替換對象。每一種數據顯示樣式都可以要求數據源提供某種固定格式的View。譬如list::TextItemStyleProvider就要求數據源提供list::TextItemStyleProvider::ITextItemView,ListView的六種樣式共享list::ListViewItemStyleProvider::IListViewItemView。如果你需要設計新的view,或者為已知的數據源提供view,可以簡單的繼承那個數據源類并override它的RequestView和ReleaseView方法。這樣View就成為了數據源和數據顯示樣式中間的一個媒介。不同的數據顯示樣式可以共享View,不同的數據源也可以提供相通的View,這樣他們之間的耦合就解除了。用戶可以根據各自的性能要求來實現View。

                舉個例子,你直接從文件讀出來的一個巨大的struct數組,要求你轉換成一個一個的object顯然是太浪費性能了。在這種情況下,你只需要實現一個GuiListControl::IItemProvider并提供具體的View的實現,就可以讓列表控件僅僅在需要顯示數據的時候,才使用index來向View獲取具體的數據內容。這可以大大提高性能,而且甚至可以在可能的情況下實現“一邊拖滾動條,一邊異步加載數據”這樣的高級操作。

                更多的ComboBox樣式會在接下來提供到Demo里面去,可能會有ColorPicker或者FontPicker等等,如果時間充足的話。
            posted @ 2012-01-04 06:24 陳梓瀚(vczh) 閱讀(2593) | 評論 (8)編輯 收藏
                GacUI為了實現把界面序列化和反序列化到XML,必然要有類似反射一樣的功能。但是C++卻沒有反射,現在想到的方法就是,把編譯后的pdb文件拿出來。因為控件不是模板類,所以數據都可以直接獲取。pdb文件包含了所有函數的信息,還有被實例化后的模板類和模板函數的信息。因此只需要使用IDiaDataSource(Visual Studio提供的COM組件)讀取pdb的類聲明之后,把信息整理并輸出到一個xml里面,然后就可以用C#編寫linq to xml的程序去分析并生成支持C++反射的一系列周邊代碼了。這樣就自動讓C++其中一部分必要的類獲得反射的功能,代價就是每一次修改完代碼之后,要記得非人肉地更新自動生成的代碼。

                不過為了更加形象的展示pdb的內容,我使用GacUI的帶Virtual Mode的TreeView打開pdb填充。這里面有兩個view,第一個是pdb,第二個是整理后的class view。顯示pdb的GuiTreeView控件展示了如何通過提供一個數據源,從而實現“展開的時候再從pdb文件里面讀取信息”的技術。而class view則是通過提供一個數據源來將一個文件中的xml讀取到內存并顯示出來,但是避免new那些暫時還不需要顯示出來的TreeViewNode對象。代碼放在Vczh Library++ 3.0(Candidate\GUI\GUIDemo\GUIDemo.sln)。現在先上圖:





                解析PDB的關鍵代碼在DumpPDB.cpp文件中,大家只需要下載代碼并閱讀即可。所有的內容都可以從MSDN搜索IDiaDataSource獲得,但是運行的話則需要有這個COM組件,一般要求安裝Visual Studio。下面解釋一下一段C++代碼。這是上面那個按鈕的回調函數。這個回調函數做了下面幾件事情
                1、將Button和TagPage都Disable
                2、利用線程池異步將PDB的內容保存到XML文件中(一秒鐘)
                3、第2步完成之后,發一個消息回到GUI線程,自動顯示第二個TagPage
                4、異步將XML讀取到內存。在這里我沒有使用延遲讀取技術,所以我直接創建了大約幾百萬個字符串,需要五秒鐘
                5、第4步完成之后,發一個消息回到GUI線程嗎,將創建好的內存中的XML格式顯示在TreeView里

                這些異步操作來往十分復雜,但是借助C++0x就可以描述得十分清晰。GacUI的實現并沒有使用C++0x,但是仍然可以為使用C++0x的那部分用戶提供一些更加優化的接口。因此這些復雜的步驟最后就寫成了:

            buttonDump->Clicked.AttachLambda([=](GuiGraphicsComposition* sender, GuiEventArgs& arguments)
            {
                INativeController* controller=GetCurrentController();
                tabControl->GetPages()[0]->GetContainer()->SetEnabled(false);
                buttonDump->SetEnabled(false);
                buttonDump->SetText(L"Dumping...");
                buttonDump->GetRelatedControlHost()->GetBoundsComposition()->SetAssociatedCursor(controller->GetSystemCursor(INativeCursor::LargeWaiting));

                ThreadPoolLite::QueueLambda([=]()
                {
                    dumppdb::DumpPdbToXml(diaSymbol, L"..\\Debug\\GuiDemo.xml");
                    GetApplication()->InvokeLambdaInMainThread([=]()
                    {
                        tabControl->GetPages()[0]->GetContainer()->SetEnabled(true);
                        tabControl->SetSelectedPage(tabControl->GetPages()[1]);
                        buttonDump->SetText(L"Loading GuiDemo.xml in the class view...");

                        ThreadPoolLite::QueueLambda([=]()
                        {
                            FileStream fileStream(L"..\\Debug\\GuiDemo.xml", FileStream::ReadOnly);
                            CacheStream cacheStream(fileStream, 1048576);
                            BomDecoder decoder;
                            DecoderStream decoderStream(cacheStream, decoder);
                            StreamReader reader(decoderStream);
                            Ptr<TreeElement> xml=LoadXmlRawDocument(reader).Cast<TreeElement>();

                            GetApplication()->InvokeLambdaInMainThreadAndWait([=]()
                            {
                                buttonDump->SetText(L"GuiDemo.xml dumpped.");
                                buttonDump->GetRelatedControlHost()->GetBoundsComposition()->SetAssociatedCursor(controller->GetDefaultSystemCursor());

                                GuiTreeView* treeControl=new GuiTreeView(new win7::Win7TreeViewProvider, CreateProviderFromXml(xml));
                                treeControl->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0));
                                treeControl->SetVerticalAlwaysVisible(false);
                                treeControl->SetHorizontalAlwaysVisible(false);
                                tabControl->GetPages()[1]->GetContainer()->GetContainerComposition()->AddChild(treeControl->GetBoundsComposition());
                            });
                        });
                    });
                });
            });


                buttonDump->Clicked.AttachLambda的意思是將一個滿足C++0x標準的lambda表達式當成一個事件處理程序綁定到一個時間上。ThreadPoolLite::QueueLambda則是將一個lambda表達式放進Windows內核實現的內存池進行異步調用。GetApplication()->InvokeLambdaInMainThread(AndWait)則是在別的線程里將一個lambda表達式放到GUI線程(一般是主線程)中運行。如果調用了Wait的版本,則這個函數會一直等到該lambda表達式在主線程執行完了才會返回。如果大家關心實現的話,可以去Candidate\GUI\GUI\NativeWindow\Windows\WinNativeWindow.cpp文件里查看。

                大家可以想象,在古老的不支持lambda表達式的C++版本里面,要實現這個過程,這個函數將被拆散成多少函數。為了傳遞很多復雜的對象,要寫多少個臨時的struct,new多少內存碎片才能將異步回調函數的參數做成Windows所希望的DWORD(__stdcall*)(void*)格式。為了把一部分事情放回到GUI線程做(我們都知道GUI庫不值得為了線程安全而做很多浪費性能的事情),得實現多少私有的Win32消息,subclass多少東西才能最終做到。這一切在GacUI中都簡化了。

                接下來將會研究如何利用pdb里面的信息讓跟GacUI有關的對象支持反射的具體細節。元旦就先休息了,啊哈哈哈。
            posted @ 2011-12-30 04:12 陳梓瀚(vczh) 閱讀(7625) | 評論 (21)編輯 收藏
            僅列出標題
            共35頁: First 3 4 5 6 7 8 9 10 11 Last 
            国产A三级久久精品| 伊人精品久久久久7777| 伊人久久大香线蕉综合Av| 久久天天躁夜夜躁狠狠| 亚洲精品美女久久777777| 国产亚洲欧美成人久久片| 久久97久久97精品免视看| 久久99久久99精品免视看动漫| 国产精品女同久久久久电影院| 人妻精品久久久久中文字幕| 久久婷婷激情综合色综合俺也去| 国产成人精品久久| 婷婷久久久亚洲欧洲日产国码AV | 久久e热在这里只有国产中文精品99 | 亚洲中文精品久久久久久不卡| 久久精品嫩草影院| 中文字幕无码免费久久| 久久国产精品波多野结衣AV| 久久久久久毛片免费播放| 亚洲国产成人久久精品99 | 亚洲中文久久精品无码ww16| 99久久伊人精品综合观看| 男女久久久国产一区二区三区| 色综合合久久天天给综看| 国产免费久久精品99久久| 精品久久人妻av中文字幕| 97久久国产露脸精品国产| 一级女性全黄久久生活片免费| 久久精品亚洲男人的天堂| 91精品国产91久久久久久| 99久久精品日本一区二区免费 | 久久精品国产99国产精偷| 亚洲精品无码久久久久| 亚洲伊人久久成综合人影院| 久久久久久国产精品美女| 狠狠久久综合伊人不卡| 国产精品丝袜久久久久久不卡| 久久久女人与动物群交毛片 | 久久夜色精品国产亚洲| 色婷婷久久久SWAG精品| 伊人久久精品影院|