• <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的ListView支持Windows 7資源管理器的六種View,并且在默認的皮膚下表現的跟資源管理器十分類似。這個Demo也使用了一些Shell API來獲得資源管理器使用的文件的圖標、文件類型的字符串等等。完整的代碼可以在http://www.gaclib.net/Demos/Controls.ListView.ViewSwitching/Demo.html看到。在這里先上圖:

            Information:


            Tile:


            Detail:


            List:


            SmallIcon:


            BigIcon:


                想必這么一個簡單的兩個控件的排版大家都已經知道怎么寫了。首先創建一個2行1列的表格,其次直接放兩個控件進去。代碼如下:

            #include "..\..\Public\Source\GacUI.h"
            #include 
            <ShlObj.h>

            using namespace vl::collections;

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

            extern void FillData(GuiListView* listView);

            /***********************************************************************
            ViewSwitchingWindow
            **********************************************************************
            */

            class ViewSwitchingWindow : public GuiWindow
            {
            private:
                GuiListView
            *                    listView;
                GuiComboBoxListControl
            *            comboView;

                
            void comboView_SelectedIndexChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
                {
                    
            switch(comboView->GetSelectedIndex())
                    {
                    
            case 0:
                        listView
            ->ChangeItemStyle(new list::ListViewBigIconContentProvider);
                        
            break;
                    
            case 1:
                        listView
            ->ChangeItemStyle(new list::ListViewSmallIconContentProvider);
                        
            break;
                    
            case 2:
                        listView
            ->ChangeItemStyle(new list::ListViewListContentProvider);
                        
            break;
                    
            case 3:
                        listView
            ->ChangeItemStyle(new list::ListViewDetailContentProvider);
                        
            break;
                    
            case 4:
                        listView
            ->ChangeItemStyle(new list::ListViewTileContentProvider);
                        
            break;
                    
            case 5:
                        listView
            ->ChangeItemStyle(new list::ListViewInformationContentProvider);
                        
            break;
                    }
                }
            public:
                ViewSwitchingWindow()
                    :GuiWindow(GetCurrentTheme()
            ->CreateWindowStyle())
                {
                    
            this->SetText(L"Controls.ListView.ViewSwitching");

                    GuiTableComposition
            * table=new GuiTableComposition;
                    table
            ->SetCellPadding(4);
                    table
            ->SetAlignmentToParent(Margin(0000));
                    table
            ->SetRowsAndColumns(21);
                    table
            ->SetRowOption(0, GuiCellOption::MinSizeOption());
                    table
            ->SetRowOption(1, GuiCellOption::PercentageOption(1.0));
                    table
            ->SetColumnOption(0, GuiCellOption::PercentageOption(1.0));
                    {
                        GuiCellComposition
            * cell=new GuiCellComposition;
                        table
            ->AddChild(cell);
                        cell
            ->SetSite(0011);

                        GuiTextList
            * comboSource=g::NewTextList();
                        comboSource
            ->GetItems().Add(L"Big Icon");
                        comboSource
            ->GetItems().Add(L"Small Icon");
                        comboSource
            ->GetItems().Add(L"List");
                        comboSource
            ->GetItems().Add(L"Detail");
                        comboSource
            ->GetItems().Add(L"Tile");
                        comboSource
            ->GetItems().Add(L"Information");
                        comboSource
            ->SetHorizontalAlwaysVisible(false);

                        comboView
            =g::NewComboBox(comboSource);
                        comboView
            ->SetSelectedIndex(0);
                        comboView
            ->GetBoundsComposition()->SetAlignmentToParent(Margin(00-10));
                        comboView
            ->GetBoundsComposition()->SetPreferredMinSize(Size(1600));
                        comboView
            ->SelectedIndexChanged.AttachMethod(this&ViewSwitchingWindow::comboView_SelectedIndexChanged);
                        cell
            ->AddChild(comboView->GetBoundsComposition());
                    }
                    {
                        GuiCellComposition
            * cell=new GuiCellComposition;
                        table
            ->AddChild(cell);
                        cell
            ->SetSite(1011);

                        listView
            =g::NewListViewBigIcon();
                        listView
            ->GetBoundsComposition()->SetAlignmentToParent(Margin(0000));
                        listView
            ->SetHorizontalAlwaysVisible(false);
                        listView
            ->SetVerticalAlwaysVisible(false);
                        listView
            ->SetMultiSelect(true);
                        cell
            ->AddChild(listView->GetBoundsComposition());
                    }
                    
            this->GetBoundsComposition()->AddChild(table);
                    FillData(listView);

                    
            // 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();
                }
            };

                在非虛擬模式下的ListView控件可以使用listView->ChangeItem(list::ListView*ContentProvider)來切換外觀。整個控件的設計是開放的,如果程序員有特別的要求的話,也可以實現一個類似的ContentProvider來控制每一個item的外觀。ContentProvider可以控制的地方有列表項的排版、坐標系和每一個列表項的皮膚等等。排版和坐標系都已經有很多預定義的類(實現)可以使用。值得一提的是,在Detail模式下的ColumnHeader是列表項的排版組件放進去的。如果沒有特別復雜的要求,單純要顯示數據的話,使用起來很簡單。上面的代碼有一個關鍵的FillData函數,用于讀取Windows目錄(通常是C:\Windows)的文件內容然后顯示上去。代碼如下:

            /***********************************************************************
            FillData
            **********************************************************************
            */

            void FillList(GuiListView* listView, const WString& path, List<WString>& files)
            {
                
            // Fill all information about a directory or a file.
                FOREACH(WString, file, files.Wrap())
                {
                    Ptr
            <list::ListViewItem> item=new list::ListViewItem;
                    WString fullPath
            =path+L"\\"+file;

                    
            // Get large icon.
                    item->largeImage=GetFileIcon(fullPath, SHGFI_LARGEICON | SHGFI_ICON);
                    
            // Get small icon.
                    item->smallImage=GetFileIcon(fullPath, SHGFI_SMALLICON | SHGFI_ICON);
                    
            // Get display name
                    item->text=GetFileDisplayName(fullPath);
                    
            // Get type name
                    item->subItems.Add(GetFileTypeName(fullPath));
                    
            // Get last write time
                    item->subItems.Add(GetFileLastWriteTime(fullPath));
                    
            // Get file size
                    item->subItems.Add(GetFileSize(fullPath));

                    listView
            ->GetItems().Add(item);
                }
            }

            void FillData(GuiListView* listView)
            {
                
            // Get the Windows directory, normally L"C:\Windows".
                wchar_t folderPath[MAX_PATH]={0};
                HRESULT hr
            =SHGetFolderPath(NULL, CSIDL_WINDOWS, NULL, 0, folderPath);
                
            if(FAILED(hr)) return;

                
            // Enumerate all directories and files in the Windows directory.
                List<WString> directories;
                List
            <WString> files;
                SearchDirectoriesAndFiles(folderPath, directories, files);

                
            // Set all columns. The first column is the primary column. All others are sub columns.
                listView->GetItems().GetColumns().Add(new list::ListViewColumn(L"Name"230));
                listView
            ->GetItems().GetColumns().Add(new list::ListViewColumn(L"Type"120));
                listView
            ->GetItems().GetColumns().Add(new list::ListViewColumn(L"Date"120));
                listView
            ->GetItems().GetColumns().Add(new list::ListViewColumn(L"Size"120));

                
            // Set all data columns (important sub solumns). The first sub item is 0. The primary column is not counted in.
                listView->GetItems().GetDataColumns().Add(0);    // Type
                listView->GetItems().GetDataColumns().Add(1);    // Data

                
            // Fill all directories and files into the list view
                FillList(listView, folderPath, directories);
                FillList(listView, folderPath, files);
            }

            /***********************************************************************
            GuiMain
            **********************************************************************
            */

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

                跟很多GUI類庫類似,為了在ListView上面顯示內容,簡單的new一下ListViewItem和ListViewColumn,把數據都放進去就可以了。這里的DataColumn主要是為了在Tile和Information模式下面顯示附加數據而制作的。剩下的內容就不是重點了,不過有些人可能很關心一些具體的操作,譬如怎樣獲取文件圖標啦,怎樣獲取文件的各種屬性等等。值得一提的是Windows有很多類似GetDateFormatEx這樣的函數,用來把幾乎所有需要在GUI上顯示的數據,轉成一個跟用戶當前的區域設置(locale)相關的字符串。這種事情就應該讓操作系統來做啊。剩下的代碼包含了很多操作Windows API獲取文件屬性的代碼:

            /***********************************************************************
            File System Operations
            **********************************************************************
            */

            void SearchDirectoriesAndFiles(const WString& path, List<WString>& directories, List<WString>& files)
            {
                
            // Use FindFirstFile, FindNextFile and FindClose to enumerate all directories and files
                WIN32_FIND_DATA findData;
                HANDLE findHandle
            =INVALID_HANDLE_VALUE;

                
            while(true)
                {
                    
            if(findHandle==INVALID_HANDLE_VALUE)
                    {
                        WString searchPath
            =path+L"\\*";
                        findHandle
            =FindFirstFile(searchPath.Buffer(), &findData);
                        
            if(findHandle==INVALID_HANDLE_VALUE)
                        {
                            
            break;
                        }
                    }
                    
            else
                    {
                        BOOL result
            =FindNextFile(findHandle, &findData);
                        
            if(result==0)
                        {
                            FindClose(findHandle);
                            
            break;
                        }
                    }

                    
            if(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                    {
                        
            if(wcscmp(findData.cFileName, L".")!=0 && wcscmp(findData.cFileName, L"..")!=0)
                        {
                            directories.Add(findData.cFileName);
                        }
                    }
                    
            else
                    {
                        files.Add(findData.cFileName);
                    }
                }

                Func
            <vint(WString a, WString b)> comparer=[](WString a, WString b){return _wcsicmp(a.Buffer(), b.Buffer());};
                CopyFrom(directories.Wrap(), directories.Wrap()
            >>OrderBy(comparer));
                CopyFrom(files.Wrap(), files.Wrap()
            >>OrderBy(comparer));
            }

            Ptr
            <GuiImageData> GetFileIcon(const WString& fullPath, UINT uFlags)
            {
                
            // Use SHGetFileInfo to get the correct icons for the specified directory or file.
                SHFILEINFO info;
                DWORD result
            =SHGetFileInfo(fullPath.Buffer(), 0&info, sizeof(SHFILEINFO), uFlags);
                Ptr
            <GuiImageData> imageData;
                
            if(result)
                {
                    Ptr
            <INativeImage> image=windows::CreateImageFromHICON(info.hIcon);
                    
            if(image)
                    {
                        imageData
            =new GuiImageData(image, 0);
                    }
                    DestroyIcon(info.hIcon);
                }
                
            return imageData;
            }

            WString GetFileDisplayName(
            const WString& fullPath)
            {
                SHFILEINFO info;
                DWORD result
            =SHGetFileInfo(fullPath.Buffer(), 0&info, sizeof(SHFILEINFO), SHGFI_DISPLAYNAME);
                
            return result?info.szDisplayName:L"";
            }

            WString GetFileTypeName(
            const WString& fullPath)
            {
                SHFILEINFO info;
                DWORD result
            =SHGetFileInfo(fullPath.Buffer(), 0&info, sizeof(SHFILEINFO), SHGFI_TYPENAME);
                
            return result?info.szTypeName:L"";
            }

            WString GetFileLastWriteTime(
            const WString& fullPath)
            {
                
            // Get file attributes.
                WIN32_FILE_ATTRIBUTE_DATA info;
                BOOL result
            =GetFileAttributesEx(fullPath.Buffer(), GetFileExInfoStandard, &info);

                
            // Get the localized string for the file last write date.
                FILETIME localFileTime;
                SYSTEMTIME localSystemTime;
                FileTimeToLocalFileTime(
            &info.ftLastWriteTime, &localFileTime);
                FileTimeToSystemTime(
            &localFileTime, &localSystemTime);

                
            // Get the correct locale
                wchar_t localeName[LOCALE_NAME_MAX_LENGTH]={0};
                GetSystemDefaultLocaleName(localeName, 
            sizeof(localeName)/sizeof(*localeName));

                
            // Get the localized date string
                wchar_t dateString[100]={0};
                GetDateFormatEx(localeName, DATE_SHORTDATE, 
            &localSystemTime, NULL, dateString, sizeof(dateString)/sizeof(*dateString), NULL);

                
            // Get the localized time string
                wchar_t timeString[100]={0};
                GetTimeFormatEx(localeName, TIME_FORCE24HOURFORMAT 
            | TIME_NOSECONDS, &localSystemTime, NULL, timeString, sizeof(timeString)/sizeof(*timeString));

                
            return dateString+WString(L" ")+timeString;
            }

            WString GetFileSize(
            const WString& fullPath)
            {
                
            // Get file attributes.
                WIN32_FILE_ATTRIBUTE_DATA info;
                BOOL result
            =GetFileAttributesEx(fullPath.Buffer(), GetFileExInfoStandard, &info);

                
            // Get the string for file size
                LARGE_INTEGER li;
                li.HighPart
            =info.nFileSizeHigh;
                li.LowPart
            =info.nFileSizeLow;

                WString unit;
                
            double size=0;
                
            if(li.QuadPart>=1024*1024*1024)
                {
                    unit
            =L" GB";
                    size
            =(double)li.QuadPart/(1024*1024*1024);
                }
                
            else if(li.QuadPart>=1024*1024)
                {
                    unit
            =L" MB";
                    size
            =(double)li.QuadPart/(1024*1024);
                }
                
            else if(li.QuadPart>=1024)
                {
                    unit
            =L" KB";
                    size
            =(double)li.QuadPart/1024;
                }
                
            else
                {
                    unit
            =L" Bytes";
                    size
            =(double)li.QuadPart;
                }

                WString sizeString
            =ftow(size);
                
            const wchar_t* reading=sizeString.Buffer();
                
            const wchar_t* point=wcschr(sizeString.Buffer(), L'.');
                
            if(point)
                {
                    
            const wchar_t* max=reading+sizeString.Length();
                    point
            +=4;
                    
            if(point>max) point=max;
                    sizeString
            =sizeString.Left(point-reading);
                }

                
            return sizeString+unit;
            }

                在這里需要特別說明一下。這個Demo沒有使用GacUIIncludes.h,而是用GacUI.h,是因為GacUI.h包含了一些跟Windows操作系統直接相關的東西,譬如說把一個HICON類型轉成INativeImage類型的方法:windows::GetImageFromHICON。類似的操作在開發跟Windows系統本身交互比較密切的函數是很有用的。下一個Demo還沒有寫,但是基本上會選擇一個小場景來描述如何使用ListView的虛擬模式。GacUI里面所有的列表控件都有虛擬模式,包括GuiVirtualTextList、GuiVirtualListView和GuiTreeView(TreeView的虛擬模式和非虛擬模式是同一個類型)等。敬請期待。
            posted on 2012-06-04 09:15 陳梓瀚(vczh) 閱讀(7738) 評論(8)  編輯 收藏 引用 所屬分類: GacUI

            評論:
            # re: GacUI Demo:模擬Windows7資源管理器 2012-06-04 17:37 | SunRise_at
            大神,一點還不睡覺,很傷身體的。。。  回復  更多評論
              
            # re: GacUI Demo:模擬Windows7資源管理器 2012-06-05 22:48 | 邱震鈺(zblc)
            mark  回復  更多評論
              
            # re: GacUI Demo:模擬Windows7資源管理器 2012-06-19 08:17 | 龍哥
            無法支持vc2005  回復  更多評論
              
            # re: GacUI Demo:模擬Windows7資源管理器 2012-06-19 08:20 | 龍哥
            還有就是必須安裝dx sdk,感覺不用也要安裝還是不方便。  回復  更多評論
              
            # re: GacUI Demo:模擬Windows7資源管理器 2012-06-19 08:31 | 陳梓瀚(vczh)
            @龍哥
            Direct2D不能裝進XP,所以XP只能用GDI,不需要裝dxsdk。
            vista以后的版本自帶至少DX10,有Direct2D,所以windows sdk已經有DX10了,所以也不需要安裝dxsdk。用戶不需要sdk,dx10的runtime已經存在了,所以可以直接運行。

            結論:不需要你特別去安裝dxsdk。  回復  更多評論
              
            # re: GacUI Demo:模擬Windows7資源管理器 2012-06-19 08:31 | 陳梓瀚(vczh)
            @龍哥
            vc2005我猜是windows sdk版本的問題  回復  更多評論
              
            # re: GacUI Demo:模擬Windows7資源管理器 2012-06-19 11:11 | 龍哥
            @陳梓瀚(vczh)
            但不安裝dxsdk會提示缺少D2D1.h DWrite.h,不知道注釋掉是否可以。我用的是xp系統。
            vc2005提示缺少wincodec.h這個文件,搜索sdk目錄的確也不存在這個文件。
              回復  更多評論
              
            # re: GacUI Demo:模擬Windows7資源管理器 2012-06-20 04:15 | 陳梓瀚(vczh)
            @龍哥
            哦,我知道你的問題了。我有計劃要給一個宏,當你開發和目標系統都只能是XP的時候,通過打開這個宏來關掉所有D2D的部分。不過想來因為新的VS連XP都只支持到SP3并且隨時要干掉了,所以就降低了他的優先級。對我來說支持win8更重要一點,啊哈哈哈。  回復  更多評論
              
            久久精品国产91久久综合麻豆自制| 日本欧美国产精品第一页久久| 久久精品国产99国产精品| 久久99国内精品自在现线| 久久精品国产亚洲AV无码偷窥| 亚洲中文字幕无码久久综合网| 久久精品中文字幕一区| 欧美日韩精品久久久久| 漂亮人妻被中出中文字幕久久| 久久国内免费视频| 久久婷婷色香五月综合激情| 午夜福利91久久福利| 国产A三级久久精品| 亚洲中文久久精品无码| 人妻精品久久久久中文字幕69| 国产精品美女久久久久| 久久免费精品一区二区| 青春久久| 久久99精品国产麻豆| 国产毛片久久久久久国产毛片| 手机看片久久高清国产日韩| 一日本道伊人久久综合影| 人妻精品久久久久中文字幕69 | 久久天天躁狠狠躁夜夜不卡| 午夜精品久久久久久影视777| 久久伊人五月丁香狠狠色| 韩国免费A级毛片久久| 狠狠人妻久久久久久综合蜜桃| 色综合久久88色综合天天 | 亚洲AV日韩精品久久久久久久| 韩国无遮挡三级久久| 伊人久久大香线蕉综合热线| 999久久久免费精品国产| 久久久网中文字幕| 99精品久久精品一区二区| 久久亚洲国产成人精品无码区| 久久综合88熟人妻| 日日狠狠久久偷偷色综合免费| 国产美女久久久| 久久久久久久久久久| 久久精品国产亚洲av瑜伽|