先看兩張圖,第一張是AE自帶的Add data對話框, 相信所有做AE開發的人都見過;另一張是本人仿製和擴展的添加數據對話框,大家肯定沒見過。
各位筒子,有沒有覺得十分震撼?這是我整整一天的勞動結晶,下面就讓我來隆重介紹一下。
我的風格是有所保留的奉獻源碼,無所顧忌的貢獻思路。
爲什麼做這個東西
一個原因是本人可能是極端分子,在做軟件時,要麼全部用中文,要麼全部用英文,最不喜歡半洋半中,因此一直有個宏偉的計劃,就是將AE裏面自帶的對話框和浮動窗體都重做一下,這個工作仍然在進行中;另一個原因是AE自帶的這個對話框只能加載其指定的數據類型,連Desktop中支持的CAD圖都不能加載,就別說自定義的數據類型了,以前的做法重新寫一個命令來加載這些數據,這讓我很反感,所以一直想自己設計一個添加數據的對話框。
這個東西是怎麼做的
網上有通過Windows API函數直接擴展Windows對話框如打開文件對話框的例子,但十分複雜,而且也不一定能做出我想要的效果。其實自己動手做一個普通對話框不難,但做一個打開文件的對話框難在何處呢?我們先看看AE自帶的Add data對話框的結構:頂部是一個下拉列表框,可以以樹狀的形式顯示驅動器和文件夾;左邊是幾個按鈕,起過濾文件類型的作用;正中是一個列表框,可以顯示驅動器、文件夾、文件的信息;底部有一個文本框用於顯示文件名,一個下拉列表框,用於選擇文件類型,還有兩個按鈕,一個是打開按鈕,一個是取消按鈕。好了,通過分析這個對話框的結構,我們就可以發現實現的難點在何處了。
難點一:如何實現一個樹狀的下拉列表框;
難點二:如何獲取計算機中的驅動器、文件夾和文件信息;
難點三:如何分門別類的加載各種數據。
實際上,後面兩個都是比較容易解決的,關鍵就是第一個了,於是我又想到第三方控件以及我的最愛開源網站www.codeproject.com了,往上一搜,果然有人寫過,讓我喜出望外的是,作者的目的也是爲了仿製一個Window打開文件對話框,這就好辦了。
這款第三方控件名爲ExplorerControls,提供了好幾個做界面的控件,大家可以去看看,網址是:http://www.codeproject.com/KB/cpp/ExpCombo.aspx
接下來開始動手,首先是設計界面,費了不少功夫,做一個漂亮的界面真不是件容易的事,甚至比寫程序還累。這個界面的主角當然是ExplorerControls中的Brower控件了,這個控件由一個下拉列表和一個列表框組成,基本實現了打開文件框中相應的部分,即在下拉列表中選擇驅動器和文件夾,在列表框中顯示文件夾和文件。browser需要設置許多屬性,大家可參照源碼來做。
下面就要寫代碼了。
一、點擊左邊按鈕過濾文件類型的功能的實現
很簡單,brower有一個Filter屬性,可以設置你想要的所有文件類型,注意這是一個string數組。下面是一個過濾raster的按鈕的單擊事件。
private void btnFilterRaster_Click(object sender, EventArgs e)
{
this.browser.Filter = new string[] { "img","tif","tiff","jpg","jpeg","bmp","gif","png"};
this.browser.RefreshBrowser();
this.cmbDataType.Items.Clear();
this.cmbDataType.Items.AddRange( new string[] {
"所有支持的文件 (*.img,*.tif,*.tiff,*.jpg,*.jpeg,*.bmp,*.gif,*.png)",
"Imagine image文件 (*.img)",
"TIFF文件 (*.tif)",
"TIFF文件 (*.tiff)",
"JPEG文件 (*.jpg)",
"JPEG文件 (*.jpeg)",
"位圖文件 (*.bmp)",
"PNG文件 (*.png)",
"GIF文件 (*.gif)"
});
this.cmbDataType.SelectedIndex = 0;
g_pDataType = 3;
}
其中,cmbDataType是文件類型的下拉列表框,g_pDataType是標誌,用於判斷打開的是什麼類型的數據。二、在列表框中單擊文件返回文件路徑,單擊文件夾打開文件夾
brower公開了一個SelectedListIndexChanged事件,可以在個事件中添加相應代碼,如下所示:
private void browser_SelectedListIndexChanged(object sender,EventArgs e)
{
string SelectFileName="";
m_ShitemList = new List<CShItem>();
ExplorerControls.ExpList.SelectedExpListItemCollection ExpListCol = this.browser.SelectedListItems;
if (ExpListCol.Count == 0) return;
else if (ExpListCol.Count == 1)
{
ExpListItem pExpListItem = ExpListCol[0];
CShItem shItem;
shItem = pExpListItem.CShItem;
if (shItem.IsFolder)
{
m_shItem_1 = shItem;
this.txtFileName.Text = "";
return;
}
else
{
m_ShitemList.Add(shItem);
m_shItem_1 = null;
}
SelectFileName = pExpListItem.Text;
this.txtFileName.Text = SelectFileName;
}
else
{
foreach (ExpListItem pExpListItem in ExpListCol)
{
CShItem shItem;
shItem = pExpListItem.CShItem;
if (shItem.IsFolder)
{
m_shItem_1 = shItem;
this.txtFileName.Text = "";
return;
}
else
{
m_ShitemList.Add(shItem);
m_shItem_1 = null;
}
SelectFileName += pExpListItem.Text;
SelectFileName += "; ";
}
SelectFileName = SelectFileName.Remove(SelectFileName.Length - 1);
this.txtFileName.Text = SelectFileName;
}
}
其中CShitem是一個十分重要的類,在這個類中提供了諸如文件路徑path的屬性,也提供了諸如判斷所選項是文件夾還是文件的方法isforder,這些東西十分有用。由於brower支持多選,所以定義了一個list數組m_ShitemList來存儲列表框中被選定的所有項。txtFileName是一個用於顯示文件名的文本框。
三、將文件的雙擊事件綁定到打開按鈕
看如下代碼:
private void browser_FileActivate(object sender, ExpList.ExpListItemEventArgs e)
{
this.btnOpen.PerformClick();
}
四、在打開按鈕中實現打開各種數據的代碼
加載各種數據的代碼在論壇中很多,這裏不再重複。
這樣,工作就完成了,當然中間有很多細節我無法一一表述,大家不妨也動動手,DIY一個自己的添加數據對話框。