• <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
             
                GacUI在結(jié)束了文本框的介紹之后,開(kāi)始進(jìn)入列表的介紹。列表內(nèi)容豐富,包含各種預(yù)定義的列表控件、用來(lái)顯示和操作大量對(duì)象的虛擬模式、MVC分離、修改列表樣式等內(nèi)容。今天先從文本列表的簡(jiǎn)單操作開(kāi)始。這個(gè)Demo展示了如何對(duì)列表進(jìn)行添加和刪除。窗口里面有一個(gè)列表,然后有添加和刪除兩個(gè)按鈕,分別用于把文本框的內(nèi)容添加到列表內(nèi),和刪除掉選中的列表項(xiàng)的。在這個(gè)Demo里面只允許列表項(xiàng)單選,并且水平滾動(dòng)條默認(rèn)不出現(xiàn)。先看圖:



                空間如何布局,我就不再贅述了,明顯是一個(gè)四行三列的表格。代碼如下:

            #include "..\..\Public\Source\GacUIIncludes.h"
            #include 
            <Windows.h>

            // for SortedList, CopyFrom and Select
            using namespace vl::collections;

            int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
            {
                
            return SetupWindowsDirect2DRenderer();
            }

            class NameEditorWindow : public GuiWindow
            {
            private:
                GuiTextList
            *                        listBox;
                GuiSinglelineTextBox
            *                textBox;
                GuiButton
            *                            buttonAdd;
                GuiButton
            *                            buttonRemove;
                
                
            void buttonAdd_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    
            // add the specified name at the end of the list box
                    listBox->GetItems().Add(textBox->GetText());
                    textBox
            ->SelectAll();
                    textBox
            ->SetFocus();
                }

                
            void buttonRemove_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    
            // remove the selected items using item index
                    listBox->GetItems().RemoveAt(listBox->GetSelectedItems()[0]);
                }

                
            void listBox_SelectionChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    
            // disable the button if no item is selected
                    buttonRemove->SetEnabled(listBox->GetSelectedItems().Count()>0);
                }
            public:
                NameEditorWindow()
                    :GuiWindow(GetCurrentTheme()
            ->CreateWindowStyle())
                {
                    
            this->SetText(L"Controls.ListBox.NameEditor");

                    GuiTableComposition
            * table=new GuiTableComposition;
                    table
            ->SetRowsAndColumns(43);
                    table
            ->SetCellPadding(3);
                    table
            ->SetAlignmentToParent(Margin(0000));

                    table
            ->SetRowOption(0, GuiCellOption::MinSizeOption());
                    table
            ->SetRowOption(1, GuiCellOption::MinSizeOption());
                    table
            ->SetRowOption(2, GuiCellOption::MinSizeOption());
                    table
            ->SetRowOption(3, GuiCellOption::PercentageOption(1.0));

                    table
            ->SetColumnOption(0, GuiCellOption::PercentageOption(1.0));
                    table
            ->SetColumnOption(1, GuiCellOption::MinSizeOption());
                    table
            ->SetColumnOption(2, GuiCellOption::MinSizeOption());

                    
            this->GetContainerComposition()->AddChild(table);
                    
                    {
                        GuiCellComposition
            * cell=new GuiCellComposition;
                        table
            ->AddChild(cell);
                        cell
            ->SetSite(0041);

                        listBox
            =g::NewTextList();
                        listBox
            ->GetBoundsComposition()->SetAlignmentToParent(Margin(0000));
                        listBox
            ->SetHorizontalAlwaysVisible(false);
                        listBox
            ->SelectionChanged.AttachMethod(this&NameEditorWindow::listBox_SelectionChanged);
                        cell
            ->AddChild(listBox->GetBoundsComposition());
                    }
                    {
                        GuiCellComposition
            * cell=new GuiCellComposition;
                        table
            ->AddChild(cell);
                        cell
            ->SetSite(0111);

                        GuiLabel
            * label=g::NewLabel();
                        label
            ->SetText(L"Name to add: ");
                        label
            ->GetBoundsComposition()->SetAlignmentToParent(Margin(0-100));
                        cell
            ->AddChild(label->GetBoundsComposition());
                    }
                    {
                        GuiCellComposition
            * cell=new GuiCellComposition;
                        table
            ->AddChild(cell);
                        cell
            ->SetSite(0211);

                        textBox
            =g::NewTextBox();
                        textBox
            ->GetBoundsComposition()->SetPreferredMinSize(Size(12023));
                        textBox
            ->GetBoundsComposition()->SetAlignmentToParent(Margin(0000));
                        cell
            ->AddChild(textBox->GetBoundsComposition());
                    }
                    {
                        GuiCellComposition
            * cell=new GuiCellComposition;
                        table
            ->AddChild(cell);
                        cell
            ->SetSite(1112);

                        buttonAdd
            =g::NewButton();
                        buttonAdd
            ->SetText(L"Add");
                        buttonAdd
            ->GetBoundsComposition()->SetAlignmentToParent(Margin(0000));
                        buttonAdd
            ->Clicked.AttachMethod(this&NameEditorWindow::buttonAdd_Clicked);
                        cell
            ->AddChild(buttonAdd->GetBoundsComposition());
                    }
                    {
                        GuiCellComposition
            * cell=new GuiCellComposition;
                        table
            ->AddChild(cell);
                        cell
            ->SetSite(2112);

                        buttonRemove
            =g::NewButton();
                        buttonRemove
            ->SetText(L"Delete");
                        buttonRemove
            ->SetEnabled(false);
                        buttonRemove
            ->GetBoundsComposition()->SetAlignmentToParent(Margin(0000));
                        buttonRemove
            ->Clicked.AttachMethod(this&NameEditorWindow::buttonRemove_Clicked);
                        cell
            ->AddChild(buttonRemove->GetBoundsComposition());
                    }

                    
            // set the preferred minimum client size
                    this->GetBoundsComposition()->SetPreferredMinSize(Size(480480));
                    
            // call this to calculate the size immediately if any indirect content in the table changes
                    
            // so that the window can calcaulte its correct size before calling the MoveToScreenCenter()
                    this->ForceCalculateSizeImmediately();
                    
            // move to the screen center
                    this->MoveToScreenCenter();
                }
            };

            void GuiMain()
            {
                GuiWindow
            * window=new NameEditorWindow;
                GetApplication()
            ->Run(window);
                delete window;
            }

                這里需要注意的幾點(diǎn)就是,為了實(shí)現(xiàn)在列表沒(méi)有選中內(nèi)容的時(shí)候禁用刪除按鈕,我們需要監(jiān)聽(tīng)GuiTextList::SelectionChanged事件。核心的代碼就是下面這幾行:

                void buttonAdd_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    
            // add the specified name at the end of the list box
                    listBox->GetItems().Add(textBox->GetText());
                    textBox
            ->SelectAll();
                    textBox
            ->SetFocus();
                }

                
            void buttonRemove_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    
            // remove the selected items using item index
                    listBox->GetItems().RemoveAt(listBox->GetSelectedItems()[0]);
                }

                
            void listBox_SelectionChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    
            // disable the button if no item is selected
                    buttonRemove->SetEnabled(listBox->GetSelectedItems().Count()>0);
                }

                GuiTextList控件的GetItems函數(shù)返回所有的列表項(xiàng)。這個(gè)對(duì)象有Add、Insert、Clear、IndexOf、Remove、RemoveAt、Contains、Count等函數(shù),可以用來(lái)操作列表項(xiàng)。GuiTextList還有GetSelectedItems函數(shù)(其實(shí)是定義在GuiSelectableListControl里面的),可以用來(lái)獲得所有選中的列表項(xiàng)的下標(biāo)(從0開(kāi)始)。每當(dāng)列表內(nèi)容被修改的時(shí)候,GetSelectedItems的結(jié)果就會(huì)被自動(dòng)清空。

                下一個(gè)Demo將是關(guān)于如何處理允許多選的列表的操作方法。
            posted @ 2012-05-23 04:42 陳梓瀚(vczh) 閱讀(2360) | 評(píng)論 (4)編輯 收藏
                這是GacUI關(guān)于文本框高亮的最后一個(gè)Demo了。這個(gè)Demo是關(guān)于XML著色的。XML著色比起C++著色更難,主要是因?yàn)樵陬愃?lt;book name="C++ Primer">這樣的代碼里面,book和name的顏色不一樣,<和book的顏色也不一樣(參考Visual Studio)。這種時(shí)候單純依靠正則表達(dá)式來(lái)區(qū)分顏色是不夠的,我們還需要引入一個(gè)新的狀態(tài)機(jī)。這個(gè)狀態(tài)機(jī)只有三個(gè)狀態(tài),用來(lái)區(qū)分tag name,attribute name和text三種顏色。狀態(tài)機(jī)是手寫(xiě)的,并且GacUI提供了一個(gè)回調(diào)來(lái)寫(xiě)這個(gè)只有寥寥幾行狀態(tài)機(jī)。先看圖:



                跟C++一樣,XML著色首先是由正則表達(dá)式組成的。XML的正則表達(dá)式比較簡(jiǎn)單,只有符號(hào)、name、字符串、CData、注釋和其它一些簡(jiǎn)單的東西:

             1 class XmlColorizer : public GuiTextBoxRegexColorizer
             2 {
             3 public:
             4     XmlColorizer()
             5     {
             6         text::ColorEntry entry=win7::Win7GetTextBoxTextColor();
             7         SetDefaultColor(entry);
             8 
             9         entry.normal.text=Color(01280);
            10         AddToken(L"/<!--([^/-]|-[^/-]|--[^>])*--/>", entry);
            11 
            12         entry.normal.text=Color(1280255);
            13         AddToken(L"/<!/[CDATA/[([^/]]|/][^/]]|/]/][^>])*/]/]/>", entry);
            14 
            15         entry.normal.text=Color(000);
            16         AddToken(L"\"[^\"]*\"", entry);
            17 
            18         entry.normal.text=Color(00255);
            19         AddToken(L"[<>=]", entry);
            20 
            21         entry.normal.text=Color(25500);
            22         AddToken(L"[a-zA-Z0-9_/-:]+", entry);
            23 
            24         entry.normal.text=Color(1632121);
            25         AddExtraToken(entry);
            26 
            27         Setup();
            28     }
            29 
            30     void ColorizeTokenContextSensitive(const wchar_t* text, vint start, vint length, vint& token, int& contextState)override
            31     {
            32         
            33     }
            34 
            35     int GetContextStartState()override
            36     {
            37         
            38     }
            39 };

                其次要對(duì)三種地方的[a-zA-Z0-9_/-:]進(jìn)行著色。Tag的名字用褐色,attribute的名字用紅色,而普通文本用黑色。因此我們可以做一個(gè)狀態(tài)機(jī),初始狀態(tài)為0。如果讀進(jìn)了<,狀態(tài)變成1。1遇到了一個(gè)Tag名字之后變?yōu)?。從2開(kāi)始所有的名字就只能是attribute的名字了。我們只考慮正確的情況,錯(cuò)誤的代碼著色出了問(wèn)題不僅沒(méi)有壞處,還可以提醒程序員有什么地方寫(xiě)錯(cuò)了。之后遇到了>變回0,在0的狀態(tài)下所有的東西都是普通文本,所以名字就都是黑色的。因此上面ColorizeTokenContextSensitive函數(shù)中就需要填入這個(gè)邏輯。GetContextStartState返回0,作為第一行的起始狀態(tài)。代碼如下:

                void ColorizeTokenContextSensitive(const wchar_t* text, vint start, vint length, vint& token, int& contextState)override
                {
                    
            // 0 < 1 name 2 att > 0
                    switch(token)
                    {
                    
            case 3:
                        
            if(length==1)
                        {
                            
            switch(text[start])
                            {
                            
            case '<':
                                contextState
            =1;
                                
            break;
                            
            case '>':
                                contextState
            =0;
                                
            break;
                            }
                        }
                        
            break;
                    
            case 4:
                        
            switch(contextState)
                        {
                        
            case 0:
                            token
            =-1;
                            
            break;
                        
            case 1:
                            token
            =5;
                            contextState
            =2;
                            
            break;
                        }
                        
            break;
                    }
                }

                
            int GetContextStartState()override
                {
                    
            return 0;
                }

                這個(gè)函數(shù)里面有幾個(gè)魔法數(shù)字,其實(shí)都是關(guān)于Token的編號(hào)的。構(gòu)造函數(shù)里面我們使用AddToken將一個(gè)顏色關(guān)聯(lián)到正則表達(dá)式上,使用AddExtraToken創(chuàng)建一個(gè)沒(méi)有正則表達(dá)式關(guān)聯(lián)的顏色。所以在這個(gè)狀態(tài)機(jī)里面,所有的顏色都用Token的序號(hào)來(lái)表示。無(wú)論是使用AddToken還是AddExtraToken,第一個(gè)顏色編號(hào)為0,第二個(gè)顏色編號(hào)為1。因此case 3指的是[<>=],而case 4指的是[a-zA-Z0-9_/-:]+。而case 4里面的token=5則表示在狀態(tài)為1的時(shí)候,名字都用AddExtraToken指定的那個(gè)褐色進(jìn)行染色。缺省的名字(也就是id為4的token)是紅色,所以不需要對(duì)contextState為2的時(shí)候進(jìn)行處理。

                這樣我們就完成了XML的著色。GacUI接下來(lái)的幾個(gè)Demo將會(huì)是關(guān)于ListBox、ListView和TreeView的,敬請(qǐng)期待。
            posted @ 2012-05-20 00:41 陳梓瀚(vczh) 閱讀(2246) | 評(píng)論 (2)編輯 收藏
                GacUI終于把上一篇文章中提到的自動(dòng)采用正則表達(dá)式進(jìn)行高亮的Demo做出來(lái)了。這次實(shí)現(xiàn)的是C++ colorizer。而XML colorizer不僅需要正則表達(dá)式,還需要一個(gè)人工維護(hù)的狀態(tài),這個(gè)等到下一個(gè)Demo再提及。先看圖



                在不需要人工維護(hù)狀態(tài),僅通過(guò)正則表達(dá)式就可以著色的時(shí)候,編寫(xiě)一個(gè)colorizer變得十分的簡(jiǎn)單。這個(gè)Colorizer雖然不是一定非得通過(guò)繼承來(lái)實(shí)現(xiàn),但是這個(gè)Demo還是使用了繼承。首先編寫(xiě)一個(gè)類,繼承自GuiTextBoxRegexColorizer,然后在構(gòu)造函數(shù)里面填寫(xiě)下面的代碼:

            class CppColorizer : public GuiTextBoxRegexColorizer
            {
            public:
                CppColorizer()
                {
                    text::ColorEntry entry
            =win7::Win7GetTextBoxTextColor();
                    SetDefaultColor(entry);

                    entry.normal.text
            =Color(1280255);
                    AddToken(L
            "/d+(./d*)?([eE][+/-]?/d+)?", entry);

                    entry.normal.text
            =Color(1632121);
                    AddToken(L
            "\"([^\"]|\\\\/.)*\"", entry);

                    entry.normal.text
            =Color(01280);
                    AddToken(L
            "////[^\r\n]*", entry);
                    AddToken(L
            "///*(//|[*]*[^*//])*/*+//", entry);

                    entry.normal.text
            =Color(00255);
                    AddToken(L
            "#[a-zA-Z0-9_]*", entry);
                    AddToken(CppKeywords, entry);
                    
                    AddToken(L
            "[a-zA-Z0-9_]+", GetDefaultColor());

                    Setup();
                }
            };

                然后只需要把它綁定到文本框里面就可以了。在這個(gè)Demo里面,我們?cè)谙吕虻氖录锩嫣砑酉旅娴拇a:

                void comboSelector_SelectedIndexChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    
            switch(comboSelector->GetSelectedIndex())
                    {
                    
            case 0:(略)
                    
            case 1:(略)
                    
            case 2:
                        textBox
            ->SetColorizer(new CppColorizer);
                        textBox
            ->SetText(
                            L
            "#include <iostream>\r\n"
                            L
            "using namespace std;\r\n"
                            L
            "\r\n"
                            L
            "int main()\r\n"
                            L
            "{\r\n"
                            L
            "\t//This is a comment\r\n"
                            L
            "\t/**This*is/another\r\n"
                            L
            "\tcomment**/\r\n"
                            L
            "\tcout<<\"Hello, world!\"<<endl;\r\n"
                            L
            "\treturn 0;\r\n"
                            L
            "}\r\n"
                            );
                        
            break;
                    
            default:
                        textBox
            ->SetColorizer(0);
                    }
                }

                當(dāng)然這樣是不完整的,因?yàn)镃ppColorizer里面還有一個(gè)CppKeywords的常量。這實(shí)際上是一個(gè)正則表達(dá)式,里面用“|”字符把所有C++的關(guān)鍵字連了起來(lái)。內(nèi)容抄自MSDN的C++ Language Reference:

              1 const wchar_t* CppKeywords=
              2 L"__abstract|"
              3 L"__alignof|"
              4 L"__asm|"
              5 L"__assume|"
              6 L"__based|"
              7 L"__box|"
              8 L"__cdecl|"
              9 L"__declspec|"
             10 L"__delegate|"
             11 L"__event|"
             12 L"__except|"
             13 L"__fastcall|"
             14 L"__finally|"
             15 L"__forceinline|"
             16 L"__gc|"
             17 L"__hook|"
             18 L"__identifier|"
             19 L"__if_exists|"
             20 L"__if_not_exists|"
             21 L"__inline|"
             22 L"__int16|"
             23 L"__int32|"
             24 L"__int64|"
             25 L"__int8|"
             26 L"__interface|"
             27 L"__leave|"
             28 L"__m128d|"
             29 L"__m128|"
             30 L"__m128i|"
             31 L"__m64|"
             32 L"__multiple_inheritance|"
             33 L"__nogc|"
             34 L"__noop|"
             35 L"__pin|"
             36 L"__property|"
             37 L"__raise|"
             38 L"__sealed|"
             39 L"__single_inheritance|"
             40 L"__stdcall|"
             41 L"__super|"
             42 L"__try|"
             43 L"__except|"
             44 L"__finally|"
             45 L"__try_cast|"
             46 L"__unaligned|"
             47 L"__unhook|"
             48 L"__uuidof|"
             49 L"__value|"
             50 L"__virtual_inheritance|"
             51 L"__w64|"
             52 L"__wchar_t|"
             53 L"wchar_t|"
             54 L"abstract|"
             55 L"array|"
             56 L"bool|"
             57 L"break|"
             58 L"case|"
             59 L"catch|"
             60 L"char|"
             61 L"class|"
             62 L"const_cast|"
             63 L"const|"
             64 L"continue|"
             65 L"decltype|"
             66 L"default|"
             67 L"delegate|"
             68 L"delete|"
             69 L"do|"
             70 L"double|"
             71 L"dynamic_cast|"
             72 L"else|"
             73 L"enum|"
             74 L"event|"
             75 L"explicit|"
             76 L"extern|"
             77 L"false|"
             78 L"finally|"
             79 L"float|"
             80 L"for|"
             81 L"friend|"
             82 L"gcnew|"
             83 L"generic|"
             84 L"goto|"
             85 L"if|"
             86 L"initonly|"
             87 L"inline|"
             88 L"int|"
             89 L"interface|"
             90 L"interior_ptr|"
             91 L"literal|"
             92 L"long|"
             93 L"mutable|"
             94 L"namespace|"
             95 L"new|"
             96 L"new|"
             97 L"nullptr|"
             98 L"operator|"
             99 L"private|"
            100 L"property|"
            101 L"property|"
            102 L"protected|"
            103 L"public|"
            104 L"register|"
            105 L"reinterpret_cast|"
            106 L"return|"
            107 L"sealed|"
            108 L"short|"
            109 L"signed|"
            110 L"sizeof|"
            111 L"static_assert|"
            112 L"static_cast|"
            113 L"static|"
            114 L"struct|"
            115 L"switch|"
            116 L"template|"
            117 L"this|"
            118 L"__thiscall|"
            119 L"throw|"
            120 L"true|"
            121 L"try|"
            122 L"typedef|"
            123 L"typeid|"
            124 L"typeid|"
            125 L"typename|"
            126 L"union|"
            127 L"unsigned|"
            128 L"using|"
            129 L"virtual|"
            130 L"void|"
            131 L"volatile|"
            132 L"while";

                使用GacUI為文本框著色已經(jīng)變得如此簡(jiǎn)單。
            posted @ 2012-05-17 09:03 陳梓瀚(vczh) 閱讀(2199) | 評(píng)論 (2)編輯 收藏
                 摘要:     GacUI的高亮Demo做了一半。現(xiàn)在的進(jìn)度是,可以手寫(xiě)著色器的狀態(tài)轉(zhuǎn)換函數(shù),但是自動(dòng)從正則表達(dá)式產(chǎn)生著色器的狀態(tài)轉(zhuǎn)換函數(shù)部分還沒(méi)有集成進(jìn)GacUI。這篇博客還是照舊,看圖、看Demo代碼,說(shuō)著色原理。    這次的Demo要做一個(gè)可以動(dòng)態(tài)切換著色器的小程序,里面包含INI、XML和C++三種著色器。現(xiàn)在只實(shí)現(xiàn)了INI一中,手寫(xiě)的...  閱讀全文
            posted @ 2012-05-11 08:58 陳梓瀚(vczh) 閱讀(3255) | 評(píng)論 (1)編輯 收藏
                 摘要:     GacUI添加了一個(gè)新的Demo。這個(gè)Demo用了幾個(gè)按鈕(之所以不用菜單是因?yàn)椴幌胱孌emo一下子包含太多新東西)來(lái)實(shí)現(xiàn)剪貼板操作、只讀控制和行跳轉(zhuǎn)等功能。在剪貼板里面的內(nèi)容是文字的時(shí)候,Paste按鈕會(huì)被Enable。這個(gè)過(guò)程是自動(dòng)的,也就是說(shuō),你在畫(huà)圖里面復(fù)制了一個(gè)圖片,這個(gè)按鈕也會(huì)變灰。Cut和Copy按鈕僅在文本框有文字被選中的時(shí)候可用,因此相應(yīng)了文...  閱讀全文
            posted @ 2012-05-05 02:37 陳梓瀚(vczh) 閱讀(5321) | 評(píng)論 (5)編輯 收藏
                GacUI新增了一個(gè)Demo。這里模擬了一個(gè)簡(jiǎn)單到過(guò)頭了的編輯程序。界面是一個(gè)標(biāo)簽頁(yè),第一頁(yè)里面只有一個(gè)按鈕:Add Page。點(diǎn)中了他之后,其它頁(yè)包含一個(gè)用來(lái)關(guān)掉自己的按鈕,和一個(gè)多行的文本框。

                這個(gè)Demo要展示的其中一個(gè)問(wèn)題是,在按下關(guān)閉按鈕的時(shí)候,由于那個(gè)Page會(huì)被移除并刪除,會(huì)導(dǎo)致按鈕自己也被刪除。但是事件發(fā)生過(guò)后,實(shí)際上還有很多事情要做的。所以這里展示了如何使用GacUI進(jìn)行“延遲執(zhí)行”,在事件結(jié)束之后再刪除自己。為了方便,這個(gè)Demo使用了C++11(但是庫(kù)的實(shí)現(xiàn)并不依賴與C++11)。先上圖:





                然后我們來(lái)看代碼:

            #include "..\..\Public\Source\GacUIIncludes.h"
            #include 
            <Windows.h>

            int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
            {
                
            return SetupWindowsDirect2DRenderer();
            }

            class TextBoxPage : public GuiTabPage
            {
            private:
                
            static int pageCounter;

                GuiButton
            *                closeButton;
                GuiMultilineTextBox
            *    textBox;

                
            void closeButton_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    
            // deleteing the tab page will also delete the button, because the button is in the page
                    
            // when an event is processing, the button is not going to be deleted
                    
            // because there are many works to do after this event
                    
            // and maybe someone has already added another event handler to this button
                    
            // so it use GetApplication()->InvokeInMainThread to send a function to the queue
                    
            // so that this function will be executed after this input message (an input message raises multiple events)
                    
            // to the user, this page is closed after cliking this button
                    GetApplication()->InvokeInMainThread([this]()
                    {
                        
            // remove the page and delete it
                        this->GetOwnerTab()->RemovePage(this);
                        delete 
            this;
                    });
                }

                
            void OnPageContainerReady(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    
            // create a table to place a button and a text box
                    GuiTableComposition* table=new GuiTableComposition;
                    table
            ->SetRowsAndColumns(21);
                    table
            ->SetRowOption(0, GuiCellOption::MinSizeOption());
                    table
            ->SetRowOption(1, GuiCellOption::PercentageOption(1.0));
                    table
            ->SetColumnOption(0, GuiCellOption::PercentageOption(1.0));
                    table
            ->SetAlignmentToParent(Margin(0000));
                    table
            ->SetCellPadding(2);

                    {
                        GuiCellComposition
            * cell=new GuiCellComposition;
                        table
            ->AddChild(cell);
                        cell
            ->SetSite(0011);
                        
                        closeButton
            =g::NewButton();
                        closeButton
            ->SetText(L"Close Me!");
                        closeButton
            ->Clicked.AttachMethod(this&TextBoxPage::closeButton_Clicked);
                        cell
            ->AddChild(closeButton->GetBoundsComposition());
                    }
                    
                    {
                        GuiCellComposition
            * cell=new GuiCellComposition;
                        table
            ->AddChild(cell);
                        cell
            ->SetSite(1011);
                        
                        textBox
            =g::NewMultilineTextBox();
                        textBox
            ->GetBoundsComposition()->SetAlignmentToParent(Margin(0000));
                        textBox
            ->SetText(L"You can input several lines of text here.\r\nThis is a multiple line text box.");
                        cell
            ->AddChild(textBox->GetBoundsComposition());
                    }

                    
            this->GetContainer()->GetContainerComposition()->AddChild(table);
                }

            public:
                TextBoxPage()
                    :closeButton(
            0)
                    ,textBox(
            0)
                {
                    PageContainerReady.AttachMethod(
            this&TextBoxPage::OnPageContainerReady);
                    
            this->SetText(L"Page "+itow(++pageCounter));
                }

                
            ~TextBoxPage()
                {
                }
            };

            int TextBoxPage::pageCounter=0;

            class TextBoxPageWindow : public GuiWindow
            {
            private:
                GuiTab
            *                        tabControl;
                GuiTabPage
            *                    controlPanelPage;
                GuiButton
            *                    buttonAddPage;

                
            void buttonAddPage_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    
            // when the button is clicked, it creates a new TextBoxPage and adds it to the tab control
                    TextBoxPage* page=new TextBoxPage;
                    tabControl
            ->CreatePage(page);
                    tabControl
            ->SetSelectedPage(page);
                }
            public:
                TextBoxPageWindow()
                    :GuiWindow(GetCurrentTheme()
            ->CreateWindowStyle())
                {
                    
            this->SetText(L"Controls.Tab.TextBoxPage");
                    
            this->GetBoundsComposition()->SetPreferredMinSize(Size(640480));

                    
            // create a tab control
                    tabControl=g::NewTab();
                    tabControl
            ->GetBoundsComposition()->SetAlignmentToParent(Margin(2222));
                    
            this->AddChild(tabControl);

                    
            // the first page is a control panel
                    controlPanelPage=tabControl->CreatePage();
                    controlPanelPage
            ->SetText(L"Control Panel");

                    
            // add a button to the control panel
                    buttonAddPage=g::NewButton();
                    buttonAddPage
            ->SetText(L"Add a tab page");
                    buttonAddPage
            ->Clicked.AttachMethod(this&TextBoxPageWindow::buttonAddPage_Clicked);
                    controlPanelPage
            ->GetContainer()->GetContainerComposition()->SetInternalMargin(Margin(2222));
                    controlPanelPage
            ->GetContainer()->AddChild(buttonAddPage);

                    
            this->ForceCalculateSizeImmediately();
                    
            this->MoveToScreenCenter();
                }

                
            ~TextBoxPageWindow()
                {
                }
            };

            void GuiMain()
            {
                GuiWindow
            * window=new TextBoxPageWindow();
                GetApplication()
            ->Run(window);
                delete window;
            }

                那一大段的注釋,就是在講延遲執(zhí)行的事情。看過(guò)C++11的人都知道,lambda expression實(shí)際上就是一個(gè)functor。在舊C++里面,調(diào)用InvokeInMainThread的時(shí)候,要么可以傳一個(gè)void(*)(void*)和void*,要么可以傳一個(gè)帶operator()()的struct。在新C++里面,直接把lambda expression寫(xiě)在里面就好了。

                如果不使用延遲執(zhí)行,在事件發(fā)生的時(shí)候把自己刪掉,會(huì)導(dǎo)致Access Violation的發(fā)生,因?yàn)榻酉聛?lái)要訪問(wèn)的對(duì)象被你刪掉了。如果使用延遲執(zhí)行,就可以在input message處理完之后,執(zhí)行刪除的代碼。這樣一切都是好的。

                下一個(gè)Demo就是關(guān)于文本框的操作,再下一個(gè)Demo是關(guān)于如何做用來(lái)顯示代碼的高亮文本框的事情。敬請(qǐng)期待,啊哈哈哈。
            posted @ 2012-04-30 23:28 陳梓瀚(vczh) 閱讀(2029) | 評(píng)論 (2)編輯 收藏
                GacUI發(fā)布了一個(gè)新的Demo。這個(gè)Demo是關(guān)于多選框和單選框的。跟Windows一樣,直接創(chuàng)建出來(lái)的單選框其實(shí)是不會(huì)互斥的,除非你把他們放進(jìn)同一個(gè)group里面。界面是左右各一個(gè)group box,使用table來(lái)保證兩邊的尺寸都一樣大。每一個(gè)group box里面放三個(gè)按鈕,而且每一個(gè)group box的最小尺寸都取決于兩邊所有6按鈕中最長(zhǎng)的那個(gè)按鈕。每一邊的三個(gè)按鈕使用stack來(lái)排列成像一個(gè)列表一樣。左邊是多選框,右邊是單選框。現(xiàn)在先上圖:

                第一張是剛打開(kāi)的時(shí)候,窗口的尺寸自動(dòng)變化到能顯示所有內(nèi)容的最小的尺寸。盡管因?yàn)槲淖值年P(guān)系,左邊的按鈕比右邊的短,但是table可以控制兩個(gè)group box一樣大,并且共享最小尺寸。



                然后改變窗口的尺寸,按鈕始終靠左上角,兩個(gè)group box則保持一樣大。



                大家已經(jīng)看了前面的三個(gè)demo,所以有些東西其實(shí)已經(jīng)不需要重復(fù)解釋了。先上代碼:

            #include "..\..\Public\Source\GacUIIncludes.h"
            #include 
            <Windows.h>

            int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
            {
                
            return SetupWindowsDirect2DRenderer();
            }

            class CheckAndRadioWindow : public GuiWindow
            {
            private:

                GuiCellComposition
            * CreateButtons(const WString& groupName, const WString& buttonName, bool checkBox, GuiSelectableButton::GroupController* groupController)
                {
                    GuiCellComposition
            * cell=new GuiCellComposition;

                    GuiControl
            * groupBox=g::NewGroupBox();
                    groupBox
            ->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
                    groupBox
            ->GetContainerComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
                    
            // all child controls should at least 10 pixels away from the group box
                    groupBox->GetContainerComposition()->SetInternalMargin(Margin(10101010));
                    
            // dock the group box to fill the cell
                    groupBox->GetBoundsComposition()->SetAlignmentToParent(Margin(0000));
                    groupBox
            ->SetText(groupName);
                    
            // add the button to the cell
                    cell->AddChild(groupBox->GetBoundsComposition());

                    
            // create a stack to layout the 3 buttons from top to bottom shown like a list
                    GuiStackComposition* stack=new GuiStackComposition;
                    stack
            ->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
                    stack
            ->SetDirection(GuiStackComposition::Vertical);
                    stack
            ->SetAlignmentToParent(Margin(0000));
                    stack
            ->SetPadding(6);
                    groupBox
            ->GetContainerComposition()->AddChild(stack);

                    
            // create buttons
                    for(int i=0;i<3;i++)
                    {
                        GuiSelectableButton
            * button=checkBox?g::NewCheckBox():g::NewRadioButton();
                        button
            ->SetText(buttonName+itow(i+1));
                        button
            ->GetBoundsComposition()->SetAlignmentToParent(Margin(0000));
                        
            if(groupController)
                        {
                            button
            ->SetGroupController(groupController);
                        }

                        GuiStackItemComposition
            * stackItem=new GuiStackItemComposition;
                        stack
            ->AddChild(stackItem);
                        stackItem
            ->AddChild(button->GetBoundsComposition());
                    }

                    
            return cell;
                }
            public:
                CheckAndRadioWindow()
                    :GuiWindow(GetCurrentTheme()
            ->CreateWindowStyle())
                {
                    
            this->SetText(L"Controls.Button.CheckAndRadio");
                    
            // limit the size that the window should always show the whole content without cliping it
                    this->GetContainerComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);

                    
            // create a table to layout the 2 group boxes
                    GuiTableComposition* table=new GuiTableComposition;
                    
            // make the table to have 2 rows
                    table->SetRowsAndColumns(12);
                    table
            ->SetRowOption(0, GuiCellOption::MinSizeOption());
                    table
            ->SetColumnOption(0, GuiCellOption::PercentageOption(0.5));
                    table
            ->SetColumnOption(1, GuiCellOption::PercentageOption(0.5));
                    
            // dock the table to fill the window
                    table->SetAlignmentToParent(Margin(4444));
                    table
            ->SetCellPadding(6);
                    
            // add the table to the window;
                    this->GetContainerComposition()->AddChild(table);

                    
            // add group box for check boxes
                    {
                        GuiCellComposition
            * cell=CreateButtons(L"Check Boxes", L"This is a check box "true0);
                        table
            ->AddChild(cell);
                        
            // this cell is the left cell
                        cell->SetSite(0011);
                    }

                    
            // add group box for radio buttons
                    {
                        
            // create a group controller to group those radio buttons together
                        
            // so that select a radio button will unselect the previous one automatically
                        GuiSelectableButton::GroupController* groupController=new GuiSelectableButton::MutexGroupController;
                        
            this->AddComponent(groupController);

                        GuiCellComposition
            * cell=CreateButtons(L"Radio buttons", L"This is a radio button "false, groupController);
                        table
            ->AddChild(cell);
                        
            // this cell is the right cell
                        cell->SetSite(0111);
                    }

                    
            // call this to calculate the size immediately if any indirect content in the table changes
                    
            // so that the window can calcaulte its correct size before calling the MoveToScreenCenter()
                    this->ForceCalculateSizeImmediately();
                    
            // move to the screen center
                    this->MoveToScreenCenter();
                }

                
            ~CheckAndRadioWindow()
                {
                }
            };

            void GuiMain()
            {
                GuiWindow
            * window=new CheckAndRadioWindow();
                GetApplication()
            ->Run(window);
                delete window;
            }

                需要關(guān)心的就是第二次調(diào)用CreateButtons函數(shù),用來(lái)構(gòu)造單選按鈕的時(shí)候,穿進(jìn)去的最后一個(gè)參數(shù)。GuiSelectableButton::GroupController類是一個(gè)虛類,用來(lái)控制選中狀況。而預(yù)定義的MutexGroupController則可以控制連接到的所有GuiSelectionButton并保證他們互斥。如果需要更加復(fù)雜的情況,譬如說(shuō)“最多只能選中N個(gè)按鈕”這樣的,則自己集成一個(gè)group controller就可以了。在創(chuàng)建了一個(gè)group controller,要調(diào)用GuiWindow::AddComponent保持他的生命周期,然后使用GuiSelectableButton::SetGroupController來(lái)幫頂一個(gè)按鈕和一個(gè)group controller。

                這個(gè)demo就介紹到這里了,下一個(gè)將是關(guān)于tab控件和文本框的demo。
            posted @ 2012-04-27 06:02 陳梓瀚(vczh) 閱讀(2272) | 評(píng)論 (25)編輯 收藏
                今天為GacUI寫(xiě)了一個(gè)新的Demo,展示了一些可以自動(dòng)排版的按鈕。主要的設(shè)想就是在窗口上放一個(gè)表格,分成兩行兩列。上面的按鈕占滿一整行,下面兩個(gè)單元格放兩個(gè)按鈕。然后就可以設(shè)置每個(gè)行和列占整個(gè)表格的比例,在這個(gè)Demo里面都設(shè)置成50%。這樣每當(dāng)窗口縮放的時(shí)候,按鈕的位置也會(huì)隨之重新排版。然后設(shè)置表格充滿整個(gè)窗口,這樣窗口的最小值就會(huì)被表格的內(nèi)容所限定,這樣試圖把窗口縮小的時(shí)候,就會(huì)有一個(gè)最小的尺寸限制著,至始至終保證所有的東西都可以顯示出來(lái),不會(huì)因?yàn)榇翱谔《伙@示一半。按鈕也是同樣,可以設(shè)置它必須顯示所有的文字。所有的過(guò)程一旦配置好之后,計(jì)算尺寸的時(shí)候所有的操作都會(huì)自動(dòng)做,程序員不需要為窗口的Resize事件寫(xiě)任何代碼。

                下面先放圖。

                第一個(gè)圖是窗口剛剛打開(kāi)的時(shí)候的樣子。因?yàn)镈emo里面沒(méi)有設(shè)置窗口的尺寸,所以一上來(lái)就自動(dòng)變成了最小的尺寸——并且剛好可以顯示所有的內(nèi)容。



                第二個(gè)圖是窗口放大之后的樣子。Disable按鈕被按下了,所以上面的按鈕就變灰。



                這個(gè)Demo使用了Direct2D渲染器,所有的繪制過(guò)程都十分高速。而且表格的尺寸計(jì)算也是經(jīng)過(guò)優(yōu)化的,在拖放窗口的時(shí)候十分流暢。事實(shí)上按鈕的漸變啊、邊框啊、文字等等也是借助表格排版的。由于尺寸計(jì)算過(guò)于復(fù)雜,除了表格之外整個(gè)框架都不保存控件的尺寸,所有的東西都在需要的時(shí)候——譬如說(shuō)渲染的時(shí)候,譬如說(shuō)計(jì)算鼠標(biāo)點(diǎn)中的位置——的那一刻才開(kāi)始算。因此無(wú)論是鼠標(biāo)滑過(guò),或者是窗口拖放,都拼命地執(zhí)行很多虛函數(shù)。可見(jiàn)C++的虛函數(shù)的性能之高,幾乎永遠(yuǎn)都不會(huì)成為程序的瓶頸。下面來(lái)看代碼:

            #include "..\..\Public\Source\GacUIIncludes.h"
            #include 
            <Windows.h>

            int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
            {
                
            return SetupWindowsDirect2DRenderer();
            }

            class EnableDisableWindow : public GuiWindow
            {
            private:
                GuiButton
            *            buttonTarget;
                GuiButton
            *            buttonEnable;
                GuiButton
            *            buttonDisable;

                
            void buttonEnable_OnClick(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    buttonTarget
            ->SetEnabled(true);
                }

                
            void buttonDisable_OnClick(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    buttonTarget
            ->SetEnabled(false);
                }
            public:
                EnableDisableWindow()
                    :GuiWindow(GetCurrentTheme()
            ->CreateWindowStyle())
                {
                    
            this->SetText(L"Controls.Button.EnableDisable");
                    
            // limit the size that the window should always show the whole content without cliping it
                    this->GetContainerComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);

                    
            // create a table to layout the 3 buttons
                    GuiTableComposition* table=new GuiTableComposition;
                    
            // make the table to have 2 rows
                    table->SetRowsAndColumns(22);
                    table
            ->SetRowOption(0, GuiCellOption::PercentageOption(0.5));
                    table
            ->SetRowOption(1, GuiCellOption::PercentageOption(0.5));
                    table
            ->SetColumnOption(0, GuiCellOption::PercentageOption(0.5));
                    table
            ->SetColumnOption(1, GuiCellOption::PercentageOption(0.5));
                    
            // dock the table to fill the window
                    table->SetAlignmentToParent(Margin(10101010));
                    
            // add the table to the window;
                    this->GetContainerComposition()->AddChild(table);

                    
            // add the target button
                    {
                        GuiCellComposition
            * cell=new GuiCellComposition;
                        table
            ->AddChild(cell);
                        
            // this cell is the top cell
                        cell->SetSite(0012);

                        buttonTarget
            =g::NewButton();
                        buttonTarget
            ->SetText(L"Enable or disable me using the buttons below!");
                        
            // ensure that the buttonTarget display the whole text
                        buttonTarget->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
                        
            // dock the button to fill the cell
                        buttonTarget->GetBoundsComposition()->SetAlignmentToParent(Margin(0003));
                        
            // add the button to the cell
                        cell->AddChild(buttonTarget->GetBoundsComposition());
                    }

                    
            // add the enable button
                    {
                        GuiCellComposition
            * cell=new GuiCellComposition;
                        table
            ->AddChild(cell);
                        
            // this cell is the bottom left cell
                        cell->SetSite(1011);

                        buttonEnable
            =g::NewButton();
                        buttonEnable
            ->SetText(L"Enable");
                        buttonEnable
            ->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
                        buttonEnable
            ->GetBoundsComposition()->SetAlignmentToParent(Margin(0330));
                        buttonEnable
            ->Clicked.AttachMethod(this&EnableDisableWindow::buttonEnable_OnClick);
                        cell
            ->AddChild(buttonEnable->GetBoundsComposition());
                    }

                    
            // add the disable button
                    {
                        GuiCellComposition
            * cell=new GuiCellComposition;
                        table
            ->AddChild(cell);
                        
            // this cell is the bottom right cell
                        cell->SetSite(1111);

                        buttonDisable
            =g::NewButton();
                        buttonDisable
            ->SetText(L"Disable");
                        buttonDisable
            ->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
                        buttonDisable
            ->GetBoundsComposition()->SetAlignmentToParent(Margin(3300));
                        buttonDisable
            ->Clicked.AttachMethod(this&EnableDisableWindow::buttonDisable_OnClick);
                        cell
            ->AddChild(buttonDisable->GetBoundsComposition());
                    }

                    
            // change the button font
                    {
                        FontProperties font;

                        font
            =buttonTarget->GetFont();
                        font.size
            =20;
                        buttonTarget
            ->SetFont(font);
                        buttonEnable
            ->SetFont(font);
                        buttonDisable
            ->SetFont(font);
                    }

                    
            // call this to calculate the size immediately if any indirect content in the table changes
                    
            // so that the window can calcaulte its correct size before calling the MoveToScreenCenter()
                    table->UpdateCellBounds();
                    
            // update the size
                    this->SetBounds(Rect());
                    
            // move to the screen center
                    this->MoveToScreenCenter();
                }

                
            ~EnableDisableWindow()
                {
                }
            };

            void GuiMain()
            {
                GuiWindow
            * window=new EnableDisableWindow();
                GetApplication()
            ->Run(window);
                delete window;
            }

                代碼里面充滿了注釋,而且主要的內(nèi)容也在上面介紹了,在這里我就不羅嗦了。所有的代碼都可以在http://gac.codeplex.com中,下載最新的代碼,然后在Libraries\GacUI\GacUIDemo\GacUIDemo.sln下面找到。
            posted @ 2012-04-25 02:46 陳梓瀚(vczh) 閱讀(2356) | 評(píng)論 (5)編輯 收藏
                今天我給GacUI添加了一個(gè)新Demo。我發(fā)現(xiàn)寫(xiě)Demo也是一個(gè)測(cè)試的過(guò)程,可以用來(lái)檢驗(yàn)類庫(kù)提供的API是否夠完整。前面這兩個(gè)Demo都促使我往類庫(kù)里面加入了新的函數(shù)。這次的Demo是用Label控件來(lái)模仿超鏈接。下載最新代碼之后,可以在“Libraries\GacUI\GacUIDemo\GacUIDemo.sln”下面找到最新的Demo代碼。

                為了模仿超鏈接,我們要做兩件事情。第一件事情就是鼠標(biāo)懸浮在Label上的時(shí)候需要顯示出手的光標(biāo)圖,第二件事情就是在鼠標(biāo)進(jìn)入Label的時(shí)候顯示下劃線,離開(kāi)的時(shí)候去掉下劃線。因此我們需要監(jiān)聽(tīng)三個(gè)事件,分別是MouseEnter,MouseLeave和LeftButtonDown。下面是Demo的圖:

                上圖:鼠標(biāo)在Label外。下圖:鼠標(biāo)在Label內(nèi)。單擊Label的時(shí)候會(huì)打開(kāi)瀏覽器。



                代碼如下:

            #include "..\..\Public\Source\GacUIIncludes.h"
            #include 
            <Windows.h>

            int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
            {
                
            return SetupWindowsDirect2DRenderer();
            }

            class HyperlinkWindow : public GuiWindow
            {
            private:
                GuiLabel
            *                labelHyperlink;

                
            void labelHyperlink_OnMouseEnter(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    FontProperties font
            =labelHyperlink->GetFont();
                    font.underline
            =true;
                    labelHyperlink
            ->SetFont(font);
                }

                
            void labelHyperlink_OnMouseLeave(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    FontProperties font
            =labelHyperlink->GetFont();
                    font.underline
            =false;
                    labelHyperlink
            ->SetFont(font);
                }

                
            void labelHyperlink_OnLeftButtonDown(GuiGraphicsComposition* sender, GuiMouseEventArgs& arguments)
                {
                    ShellExecute(NULL, L
            "OPEN", L"http://www.shnenglu.com/vczh", NULL, NULL, SW_SHOWNORMAL);
                }
            public:
                HyperlinkWindow()
                    :GuiWindow(GetCurrentTheme()
            ->CreateWindowStyle())
                {
                    SetText(L
            "Controls.Label.Hyperlink");
                    SetClientSize(Size(
            300200));
                    MoveToScreenCenter();

                    labelHyperlink
            =g::NewLabel();
                    labelHyperlink
            ->SetText(L"http://www.shnenglu.com/vczh");
                    labelHyperlink
            ->SetTextColor(Color(00255));
                    {
                        FontProperties font;
                        font.fontFamily
            =L"Segoe UI";
                        font.size
            =18;
                        font.antialias
            =true;
                        labelHyperlink
            ->SetFont(font);
                    }
                    {
                        INativeCursor
            * hand=GetCurrentController()->ResourceService()->GetSystemCursor(INativeCursor::Hand);
                        labelHyperlink
            ->GetBoundsComposition()->SetAssociatedCursor(hand);
                    }
                    labelHyperlink
            ->GetEventReceiver()->mouseEnter.AttachMethod(this&HyperlinkWindow::labelHyperlink_OnMouseEnter);
                    labelHyperlink
            ->GetEventReceiver()->mouseLeave.AttachMethod(this&HyperlinkWindow::labelHyperlink_OnMouseLeave);
                    labelHyperlink
            ->GetEventReceiver()->leftButtonDown.AttachMethod(this&HyperlinkWindow::labelHyperlink_OnLeftButtonDown);
                    AddChild(labelHyperlink);
                }

                
            ~HyperlinkWindow()
                {
                }
            };

            void GuiMain()
            {
                GuiWindow
            * window=new HyperlinkWindow();
                GetApplication()
            ->Run(window);
                delete window;
            }

                這里展示的主要是監(jiān)聽(tīng)事件的方法。在使用control->GetEventReceiver()->event的時(shí)候,可以使用Attach、AttachMethod、AttachFunction和AttachLambda。AttachLambda傳入一個(gè)functor,在C++11里面可以直接使用lambda表達(dá)式。在這里使用AttachMethod給一個(gè)事件綁定類成員函數(shù)。C++運(yùn)行類成員函數(shù)的時(shí)候,不僅需要參數(shù),還需要一個(gè)this對(duì)象,所以AttachMethod有兩個(gè)參數(shù),使用方法在Demo里面已經(jīng)展現(xiàn)出來(lái)了。

                在這里還引入了GetCurrentController函數(shù)。GetCurrentController返回的INativeController對(duì)象抽象了所有需要的操作系統(tǒng)的功能,其中獲得一個(gè)光標(biāo)的對(duì)象就封裝在了ResourceService里面。INativeController還包含了很多其他的Service,這個(gè)留在以后的Demo展示。
            posted @ 2012-04-24 02:37 陳梓瀚(vczh) 閱讀(2126) | 評(píng)論 (8)編輯 收藏
                今晚終于把GacUI所有該加上的XML注釋都加上了,開(kāi)始做起了Demo。需要做的Demo大概有幾十個(gè),除了每個(gè)控件要那么幾個(gè)以外,還有一些其他功能,譬如換皮膚換風(fēng)格啊,使用不同的渲染器啊,移植到Direct3D上什么的,好多啊,即將寫(xiě)到手軟。今天寫(xiě)了第一個(gè)Demo,是一個(gè)helloworld程序。創(chuàng)建一個(gè)GacUI程序是一件很容易的事情,首先下載GacUI的最新代碼(在有了Release之后會(huì)有更好的文件組織和html文檔),然后將“Libraries\GacUI\Public\Source”下面的5個(gè)文件添加進(jìn)建好的Visual C++的Windows工程里面,然后開(kāi)始寫(xiě)main函數(shù):

            #include "..\..\Public\Source\GacUIIncludes.h"
            #include 
            <Windows.h>

            int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
            {
                
            return SetupWindowsDirect2DRenderer();
            }

            void GuiMain()
            {
                GuiWindow
            * window=g::NewWindow();
                window
            ->SetText(L"Hello, world!");
                window
            ->SetClientSize(Size(640480));
                window
            ->MoveToScreenCenter();
                
                GuiControl
            * label=g::NewLabel();
                label
            ->SetText(L"Welcome to GacUI Library!");
                {
                    FontProperties font;
                    font.fontFamily
            =L"Segoe UI";
                    font.size
            =40;
                    font.antialias
            =true;
                    label
            ->SetFont(font);
                }
                window
            ->AddChild(label);

                GetApplication()
            ->Run(window);
                delete window;
            }

                Main函數(shù)里面需要選擇渲染器,這里選的是Direct2D。如果要選擇GDI,則調(diào)用SetupWindowsGDIRenderer。至于void GuiMain(void)函數(shù)則是類庫(kù)自己的要求,一定要有那么一個(gè),因?yàn)镾etupWindowsDirect2DRenderer(或GDI)最終會(huì)進(jìn)行一大段初始化工作之后調(diào)用一個(gè)聲明了卻沒(méi)有實(shí)現(xiàn)的void GuiMain(void)函數(shù),所以一個(gè)合法的GacUI工程需要包含void GuiMain(void)的實(shí)現(xiàn),也就是上面這樣。

                然后接下來(lái)的就是普通的工作了,創(chuàng)建一個(gè)GuiWindow,加點(diǎn)東西,Run一下當(dāng)主窗口。當(dāng)主窗口被關(guān)掉的時(shí)候Run函數(shù)就會(huì)結(jié)束,這個(gè)時(shí)候進(jìn)行一下必要的清理,程序就可以結(jié)束了。運(yùn)行之后就是下面這個(gè)樣子:



                至此HelloWorld的Demo就結(jié)束了。

            posted @ 2012-04-23 07:37 陳梓瀚(vczh) 閱讀(2487) | 評(píng)論 (12)編輯 收藏
            僅列出標(biāo)題
            共35頁(yè): First 2 3 4 5 6 7 8 9 10 Last 
            精品国产乱码久久久久久郑州公司| 久久久久久亚洲Av无码精品专口| 国产亚洲婷婷香蕉久久精品| 99久久精品国产一区二区| 大美女久久久久久j久久| 国产精品久久久久免费a∨| 精品久久久久久久无码| 久久综合狠狠色综合伊人| 午夜精品久久久久久中宇| 久久精品国产只有精品66| 久久亚洲精品中文字幕| 久久99热这里只频精品6| 国产韩国精品一区二区三区久久| 97久久国产综合精品女不卡| 精品久久久久久无码中文字幕| 色综合久久久久综合体桃花网| 久久久九九有精品国产| 久久午夜福利无码1000合集| 国产ww久久久久久久久久| 香蕉久久夜色精品升级完成| 亚洲欧美久久久久9999| 日日狠狠久久偷偷色综合0| 99精品久久久久中文字幕| 日韩久久无码免费毛片软件 | 国内精品久久久久影院网站| 亚洲国产精品无码久久一线| 天天综合久久一二三区| 99久久婷婷国产一区二区| 国内精品久久人妻互换| 亚洲AV无码久久精品蜜桃| 久久天天躁狠狠躁夜夜avapp| 一本久久免费视频| 国产精品成人久久久久三级午夜电影| 久久久久久免费视频| 久久久无码精品亚洲日韩京东传媒 | 久久激情五月丁香伊人| 久久免费99精品国产自在现线| 国产成人精品久久综合| 久久亚洲国产午夜精品理论片| 久久精品国产精品青草app| 好久久免费视频高清|