青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-341  評論-2670  文章-0  trackbacks-0

    趁此機會做個廣告,http://www.gaclib.net終于上線啦!

    GacUI的列表控件的第二個Demo是關于列表項的多選的。跟Windows一樣,我們可以通過鼠標和方向鍵,配合CTRL和SHIFT選擇列表的多個內容。因此這次我實現了一個簡單的“名字選擇窗口”,就跟QQ邀請好友入群的界面一樣,兩個列表,兩個按鈕。先看圖:



    列表內容始終是排序的。當我們選中一邊的內容之后,可以按按鈕把內容復制到另一邊。現在我們先來看一看創建和排版這些控件的代碼。這里我用了一個五行三列的表格。左右方列表,中間的第二個第四行放按鈕,第三行64個像素高,按鈕32*32,第一行和第五行平均地充滿剩下的空間:

#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 NameSelectorWindow : public GuiWindow
{
private:
    GuiTextList
*                    listSource;
    GuiTextList
*                    listDestination;
    GuiButton
*                        buttonAdd;
    GuiButton
*                        buttonRemove;

    (略)
public:
    NameSelectorWindow()
        :GuiWindow(GetCurrentTheme()
->CreateWindowStyle())
    {
        
this->SetText(L"Controls.ListBox.NameSelector");

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

        table
->SetRowOption(0, GuiCellOption::PercentageOption(0.5));
        table
->SetRowOption(1, GuiCellOption::MinSizeOption());
        table
->SetRowOption(2, GuiCellOption::AbsoluteOption(64));
        table
->SetRowOption(3, GuiCellOption::MinSizeOption());
        table
->SetRowOption(4, GuiCellOption::PercentageOption(0.5));

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

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

        {
            GuiCellComposition
* cell=new GuiCellComposition;
            table
->AddChild(cell);
            cell
->SetSite(0051);

            listSource
=g::NewTextList();
            listSource
->GetBoundsComposition()->SetAlignmentToParent(Margin(0000));
            
// make listSource's horizontal scroll bar disappeared when it is not needed.
            listSource->SetHorizontalAlwaysVisible(false);
            listSource
->SetMultiSelect(true);
            listSource
->SelectionChanged.AttachMethod(this&NameSelectorWindow::listSource_SelectionChanged);
            cell
->AddChild(listSource->GetBoundsComposition());
        }
        {
            GuiCellComposition
* cell=new GuiCellComposition;
            table
->AddChild(cell);
            cell
->SetSite(0251);

            listDestination
=g::NewTextList();
            listDestination
->GetBoundsComposition()->SetAlignmentToParent(Margin(0000));
            
// make listSource's horizontal scroll bar disappeared when it is not needed.
            listDestination->SetHorizontalAlwaysVisible(false);
            listDestination
->SetMultiSelect(true);
            listDestination
->SelectionChanged.AttachMethod(this&NameSelectorWindow::listDestination_SelectionChanged);
            cell
->AddChild(listDestination->GetBoundsComposition());
        }
        {
            GuiCellComposition
* cell=new GuiCellComposition;
            table
->AddChild(cell);
            cell
->SetSite(1111);

            buttonAdd
=g::NewButton();
            buttonAdd
->SetText(L">>");
            buttonAdd
->GetBoundsComposition()->SetAlignmentToParent(Margin(0000));
            buttonAdd
->GetBoundsComposition()->SetPreferredMinSize(Size(3232));
            buttonAdd
->Clicked.AttachMethod(this&NameSelectorWindow::buttonAdd_Clicked);
            buttonAdd
->SetEnabled(false);
            cell
->AddChild(buttonAdd->GetBoundsComposition());
        }
        {
            GuiCellComposition
* cell=new GuiCellComposition;
            table
->AddChild(cell);
            cell
->SetSite(3111);

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

        
// Add names into listSource
        LoadNames(listSource);

        
// set the preferred minimum client size
        this->GetBoundsComposition()->SetPreferredMinSize(Size(640480));
        
// 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 NameSelectorWindow;
    GetApplication()
->Run(window);
    delete window;
}


    剩下的內容分為三部分。首先是如何在列表沒有選中內容的時候把按鈕變灰。在上面的代碼中我們知道listSource和listDestination都監聽了SelectionChanged事件。事件處理函數的內容如下:

    void listSource_SelectionChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
    {
        buttonAdd
->SetEnabled(listSource->GetSelectedItems().Count()>0);
    }

    
void listDestination_SelectionChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
    {
        buttonRemove
->SetEnabled(listDestination->GetSelectedItems().Count()>0);
    }


    代碼內容十分簡潔明了。第二部分是NameSelectorWindow構造函數中調用的LoadNames函數。我們首先把所有的名字都放在一個const wchar_t* DataSource[]數組里面,內容是沒有排過序的:

const wchar_t* DataSource[]=
{
    L
"Weierstrass",
    L
"Cantor",
    L
"Bernoulli",
    L
"Fatou",
    L
"Green",
    L
"S.Lie",
    L
"Euler",
    L
"Gauss",
    L
"Sturm",
    L
"Riemann",
    L
"Neumann",
    L
"Caratheodory",
    L
"Newton",
    L
"Jordan",
    L
"Laplace",
    L
"Wiener",
    L
"Thales",
    L
"Maxwell",
    L
"Riesz",
    L
"Fourier",
    L
"Noether",
    L
"Kepler",
    L
"Kolmogorov",
    L
"Borel",
    L
"Sobolev",
    L
"Dirchlet",
    L
"Lebesgue",
    L
"Leibniz",
    L
"Abel",
    L
"Lagrange",
    L
"Ramanujan",
    L
"Ljapunov",
    L
"Holder",
    L
"Poisson",
    L
"Nikodym",
    L
"H.Hopf",
    L
"Pythagoras",
    L
"Baire",
    L
"Haar",
    L
"Fermat",
    L
"Kronecker",
    L
"E.Laudau",
    L
"Markov",
    L
"Wronski",
    L
"Zermelo",
    L
"Rouche",
    L
"Taylor",
    L
"Urysohn",
    L
"Frechet",
    L
"Picard",
    L
"Schauder",
    L
"Lipschiz",
    L
"Liouville",
    L
"Lindelof",
    L
"de Moivre",
    L
"Klein",
    L
"Bessel",
    L
"Euclid",
    L
"Kummer",
    L
"Ascoli",
    L
"Chebyschev",
    L
"Banach",
    L
"Hilbert",
    L
"Minkowski",
    L
"Hamilton",
    L
"Poincare",
    L
"Peano",
    L
"Zorn",
};


    然后LoadNames函數如下所示:

    void LoadNames(GuiTextList* list)
    {
        
// Use linq for C++ to create sorted TextItem(s) from DataSource
        CopyFrom(
            list
->GetItems(),
            FromArray(DataSource)
                
>>OrderBy(_wcsicmp)
                
>>Select<const wchar_t*, list::TextItem>(
                    [](
const wchar_t* name){return list::TextItem(name);}
                )
            );
    }


    首先我們用FromArray函數從const wchar_t* DataSource[]數組創建出一個IEnumerable<const wchar_t*>,然后用_wcsicmp進行排序,最后把每一個const wchar_t* name都用list::TextItem(name)轉變成一個列表項。

    最后一步比較復雜,就是如何在移動列表的內容的時候還保持兩個列表的內容是排序的。首先,從一個排序列表中刪除東西,結果肯定是排序的。其次,把一堆新的名字插入一個列表,最簡單的方法就是把所有的東西連起來重新排序一遍,然后放回去:

    static list::TextItem GetTextItem(GuiTextList* list, int index)
    {
        
return list->GetItems()[index];
    }

    
static int CompareTextItem(list::TextItem a, list::TextItem b)
    {
        
return _wcsicmp(a.GetText().Buffer(), b.GetText().Buffer());
    }

    
static int ReverseCompareInt(int a, int b)
    {
        
return b-a;
    }

    
void MoveNames(GuiTextList* from, GuiTextList* to)
    {
        CopyFrom(
            to
->GetItems(),
            to
->GetItems()
                
>>Concat(
                    from
->GetSelectedItems()>>Select(Curry(GetTextItem)(from))
                    )
                
>>OrderBy(CompareTextItem)
            );

        List
<int> selectedItems;
        CopyFrom(
            selectedItems.Wrap(),
            from
->GetSelectedItems()
                
>>OrderBy(ReverseCompareInt)
            );
        FOREACH(
int, index, selectedItems.Wrap())
        {
            from
->GetItems().RemoveAt(index);
        }
    }

    
void buttonAdd_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
    {
        MoveNames(listSource, listDestination);
    }

    
void buttonRemove_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
    {
        MoveNames(listDestination, listSource);
    }


    我們可以看到MoveNames函數里面做了三件事情。

    第一件事情就是把to列表中的內容,和from列表中選中的內容Concat起來,也就是一個連著一個組成一個沒有排序過的IEnumerable<list::TextItem>,然后用CompareTextItem進行排序。其中Curry(GetTextItem)(item)的意思是,將item作為GetTextItem的第一個參數,把“填補剩下的參數”的這個過程產生一個新的函數,就跟bind1st函數的意思是一樣的。所以經過這個Select,就可以吧GetSelectedItems()返回的所有選中的item的下標,給轉換成原原本本的列表項。這樣將to里面的列表項和from里面選中的列表項所有的內容合起來排序,最后放回to列表里面,這樣東西就挪過去了。

    第二件事情就是要把from->GetSelectedItems()的內容都復制下來,然后逆序。

    第三件事情,就是遍歷逆序后的GetSelectedItems的結果,一個一個刪除掉選中的項目了。列表控件只要內容一變化,選中就會全部清空,因此如果不先保留GetSelectedItems的結果的話,刪除了一個列表項之后,GetSelectedItems就會變空,這樣就會出bug。

    這個Demo就介紹到這里了。GacUI下一個列表控件的Demo將是關于虛擬模式的。也就是說,這次我們不一個一個Add進去了,而是直接告訴列表控件一共有多少個項目,然后列表要顯示的時候回調一下獲得真正的內容。這個功能是很有用的,特別是當內容特別多,我們沒辦法一下子準備好的時候,可以讓界面很快的出來,讓用戶感覺起來,程序運行的很流暢。

posted on 2012-05-25 21:54 陳梓瀚(vczh) 閱讀(3654) 評論(12)  編輯 收藏 引用 所屬分類: GacUI

評論:
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-26 01:42 | phoenixbing
我是來支持老大的  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-26 06:35 | 溪流
linq 能合起來寫不?哈~  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-26 07:29 | 朱峰everettjf
學習。
請問,能否說,gaclib是一個.NET WinForm風格的c++界面庫?
GPU accelerated 是針對顯示做了優化(相對于使用sdk或mfc、wtl)?  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-26 09:19 | 陳梓瀚(vczh)
@朱峰everettjf
我覺得,應該是WPF風格的吧。GPU是針對WinForm、MFC、WTL這種傳統的界面而言的。  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-26 09:20 | 陳梓瀚(vczh)
@溪流
能啊,里面不是合了嗎,還嵌套了  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-26 18:23 | 朱峰everettjf
@陳梓瀚(vczh)
嗯。向博主學習。  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-27 16:42 | tb
向博主學習  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-27 20:49 | 溪流
@陳梓瀚(vczh)
我是說類sql的寫法:)  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-27 23:09 | TianJun
單擊列表控件里面的名字有時候會選擇到其它名字, 不是我單擊的名字。  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-28 01:23 | 陳梓瀚(vczh)
@TianJun
有沒有重現方法?然后我去查一查  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-28 01:23 | 陳梓瀚(vczh)
@溪流
沒有那種寫法,C++搞不定這種……  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-28 03:44 | Scan
在C++中倒是可以弄出a.OrderBy().Select([](){}).ToList()這種語法的linq,借助一個代理類,用.來連接操作,至少在代碼補全方面更好用。
我以前倒是也試過在C++11中借助閉包實現linq to object,閉包用于延遲迭代。  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++ 2012-05-29 19:13 | TianJun
@陳梓瀚(vczh)
剛打開程序時不會, 把一些名字移動到右邊后, 就會出現單擊左邊列表控件會選擇不對的名字。  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++[未登錄] 2012-05-29 19:35 | 陳梓瀚(vczh)
@TianJun
我去看一看  回復  更多評論
  
# re: GacUI Demo:列表控件內容的排序和移動,以及Linq for C++[未登錄] 2012-05-29 20:13 | 陳梓瀚(vczh)
@TianJun
refactor的時候犯了點小錯誤,這個問題已經解決了。感謝提供信息。  回復  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            韩国美女久久| 亚洲欧美国产高清| 久久福利毛片| 亚洲国产精品成人综合色在线婷婷| 韩国在线一区| 欧美高清不卡在线| 欧美日韩国产首页在线观看| 亚洲一区二区三区免费观看 | 国产欧美一区视频| 午夜精品国产| 欧美在线免费| 亚洲精品国产精品国自产观看| 亚洲精品极品| 国产欧美日韩精品丝袜高跟鞋| 玖玖玖国产精品| 欧美午夜片在线免费观看| 久久精品视频导航| 欧美精品一区二区三区视频| 午夜精品在线视频| 毛片基地黄久久久久久天堂 | 国产噜噜噜噜噜久久久久久久久 | 亚洲国产精品一区二区三区| 国产精品视频导航| 亚洲二区视频在线| 国产一区二区三区最好精华液| 狂野欧美一区| 久久天天躁夜夜躁狠狠躁2022| 一本久久综合亚洲鲁鲁五月天| 欧美伊人久久大香线蕉综合69| 亚洲欧洲一二三| 香蕉乱码成人久久天堂爱免费 | 亚洲一区二区影院| 裸体丰满少妇做受久久99精品| 亚洲欧美日韩网| 欧美成人午夜视频| 久久综合电影| 国产欧美日韩一区二区三区在线观看 | 久久久久久亚洲精品杨幂换脸| 亚洲综合欧美日韩| 欧美极品在线观看| 欧美国产日韩一区二区| 国产有码在线一区二区视频| 一区二区三区在线观看国产| 亚洲一区中文| 在线视频亚洲一区| 欧美精品在线一区| 亚洲第一区色| 91久久久亚洲精品| 美女视频网站黄色亚洲| 久久资源av| 国内精品久久久久久久果冻传媒| 亚洲桃花岛网站| 亚洲一区二区三区四区五区黄| 欧美好骚综合网| 亚洲激情国产精品| 亚洲欧洲视频| 欧美精品二区三区四区免费看视频| 欧美国产三级| 91久久嫩草影院一区二区| 蜜臀久久久99精品久久久久久| 母乳一区在线观看| 亚洲国产精品一区在线观看不卡| 久久久激情视频| 免费成人高清视频| 亚洲激情不卡| 欧美日本国产在线| 一本色道久久88综合亚洲精品ⅰ| 亚洲一区二区在线观看视频| 国产精品美女久久久久久久| 亚洲一区二区精品| 欧美亚洲一区在线| 国产一区日韩欧美| 老司机精品视频网站| 欧美激情在线狂野欧美精品| 亚洲精品影视| 国产精品免费网站| 久久福利视频导航| 亚洲风情亚aⅴ在线发布| 一本色道久久综合亚洲精品按摩| 欧美色综合网| 久久精品二区亚洲w码| 欧美电影在线| 亚洲一区免费网站| 狠狠色综合网| 欧美精品一区二区三区蜜臀| 亚洲在线国产日韩欧美| 久久天天躁狠狠躁夜夜av| 亚洲精品中文字幕女同| 国产精品美女xx| 麻豆成人av| 亚洲午夜免费福利视频| 玖玖综合伊人| 亚洲在线不卡| 亚洲国产mv| 国产精品一区一区| 能在线观看的日韩av| 这里只有精品丝袜| 欧美1区视频| 亚洲欧美怡红院| 亚洲国产三级网| 国产精品丝袜白浆摸在线| 美女脱光内衣内裤视频久久影院| 亚洲尤物在线| 亚洲美女视频网| 久久综合精品国产一区二区三区| 亚洲小说欧美另类社区| 亚洲二区在线视频| 国产三级精品在线不卡| 欧美日韩三级在线| 男人的天堂亚洲在线| 亚洲第一福利在线观看| 国产精品白丝av嫩草影院 | 欧美成人精品不卡视频在线观看| 99这里只有精品| 在线观看日韩专区| 国产婷婷精品| 欧美性jizz18性欧美| 欧美激情影院| 免费在线日韩av| 久久久免费av| 欧美在线二区| 亚洲制服av| 亚洲视频图片小说| 亚洲精品国产系列| 亚洲国产精品久久久| 麻豆久久精品| 免费视频亚洲| 欧美成人国产| 奶水喷射视频一区| 欧美大片第1页| 麻豆国产精品777777在线| 久久精品五月婷婷| 久久久久久电影| 国产欧美一区二区三区在线看蜜臀 | 久久免费视频在线观看| 久久精品99久久香蕉国产色戒| 午夜精品久久久久久久| 亚洲综合色视频| 亚洲欧美另类久久久精品2019| 亚洲午夜视频在线观看| 亚洲欧美一区二区在线观看| 午夜亚洲福利| 久久久www成人免费毛片麻豆| 欧美在线播放一区| 久久频这里精品99香蕉| 另类图片综合电影| 亚洲国产成人精品女人久久久 | 亚洲精品1234| 亚洲美女诱惑| 亚洲永久免费av| 欧美伊人影院| 欧美www视频在线观看| 欧美韩日一区二区| 欧美性色aⅴ视频一区日韩精品| 国产精品yjizz| 激情视频一区二区三区| 亚洲激情在线| 亚洲欧美国产毛片在线| 久久精品免费电影| 欧美大片在线影院| 夜夜嗨av色一区二区不卡| 亚洲欧美日韩国产成人| 久久理论片午夜琪琪电影网| 欧美激情精品久久久六区热门| 欧美调教视频| 精品96久久久久久中文字幕无| 亚洲国产欧美在线人成| 亚洲一区二区三区四区五区黄 | 亚洲欧美久久久久一区二区三区| 欧美综合二区| 亚洲第一区在线观看| 亚洲视频一二三| 久久天天狠狠| 国产精品久久久一区二区三区| 在线播放精品| 亚洲中无吗在线| 欧美国产激情| 午夜精品久久久久久久| 欧美激情视频一区二区三区免费| 国产精品一区二区三区免费观看| 亚洲国产精品99久久久久久久久| 亚洲在线观看视频网站| 亚洲福利电影| 久久精品国产999大香线蕉| 欧美午夜在线| 亚洲精品免费一二三区| 久久久不卡网国产精品一区| 亚洲乱码国产乱码精品精98午夜| 久久久www成人免费毛片麻豆| 国产精品久久国产三级国电话系列| 亚洲国产精品成人综合| 久久成人免费日本黄色| 一本久久a久久免费精品不卡| 久久综合九色九九| 国产亚洲欧美另类中文 | 亚洲伦理久久| 欧美电影在线观看| 久久人人爽人人| 国产自产v一区二区三区c| 亚洲欧美日韩在线|