前言:
本文主要是介紹在打開文件對話框,實現對圖象,文本等預覽(在VC++6.0下實現)。本人的水平有限,如有表達不清之處,請諒解,請各位提出意見與建議!
1、Win98下預覽對話框的實現:對常用格式的圖片,在打開文件對話框中實現預覽功能效果如下圖:
圖一
思路:
從CFileDialog派生CFileDialogEx類,為對話框安裝鉤子,利用HOOK攔截我們感興趣的CDN_SELCHANGE消息,在其中加入我們的預覽功能,原理就是這麼簡單!
使用方法:
1):在ResourView中,加一個對話框,其 ID為IDD_DIALOG_HOOK, 注意其屬性的設置:Dialog Properties->styles下=> style為Child、Border為None, 選中Clip siblings。 More Styles下 => 選中3D-look、 Contol。
2):在對話框上加一個 Static Text控件,用來顯示圖片。ID為IDC_PIC,其屬性的設置為:Text Properties下 => 選中Notify、Sunken。
3):將Picture.h,Picture.cpp;CFileDialogEx.h,CFileDialogEx.cpp添加到工程中。其中類CFileProcess是文件處理類,用於文件進行操作。類CPicture用於處理圖片。(詳見代碼)
4)在應用處,只要包含頭文件 #include”FileDialogEx.h”。
For example:
注:由於時間緊,在Debug版本下,雙擊選中文件後,有暴停的現象(內存洩漏),而且顯示效果也沒有進行處理!
CString strPathName;
CFileDialogEx dlg(TRUE);
if(dlg.DoModal() == IDOK)
{
POSITION Pos;
Pos = dlg.GetStartPosition();
while (Pos != NULL)
{
strPathName = dlg.GetNextPathName(Pos);
if(!strPathName.IsEmpty())
{
MessageBox(strPathName, _T("GetNextPathName"), MB_ICONINFORMATION);
}
}
}
2、Win2000,XP下預覽對話框的實現:比圖一多了左面的快捷欄(方便用戶查找)。其實這個實現很簡單,只要判斷一下系統的版本就可以了,但是98下只顯示圖一所示的對話框,2000,XP則顯示圖二的對話框,這是MS在98以後的版本,對這個東東重新進行了封裝!
詳情請看鏈接: 利用MFC的CFileDialog怎麼樣生成Win2000的文件對話框,
圖二
只要在CFileDialogEX dlg(TRUE)後面,加上如下代碼,就可以顯示圖2效果。//--------只要加上下面這段代碼,就可以顯示2000下的打開文件對話框-------------
//------用來檢測目前的操作系統的版本信息
int nStructSize = 0;
DWORD dwVersion, dwWindowsMajorVersion, dwWindwosMinorVersion;
dwVersion = GetVersion();
dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
dwWindwosMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
if(dwVersion < 0x80000000)
{
nStructSize = 88; //2k,xp下顯示新的版本
}
else
{
nStructSize = 76; //98下顯示老版本,如圖1
}
dlg.m_ofn.lStructSize = nStructSize; //------用來檢測目前的操作系統的版本信息
3、m_ofn成員及OPENFILENAME的介紹:
OPENFILENAME結構體:雖然成員變量不少,但是我們常用的就幾個而已!該結構體包含一些保存或打開文件對話框的重要信息,比如過濾文件名,指定初始化路徑,對文件進行多選,顯示98風格還是2000風格的open/save對話框!
typedef struct tagOFN { // ofn
lStructSize :
DWORD lStructSize;
HWND hwndOwner;
HINSTANCE hInstance;
LPCTSTR lpstrFilter;
LPTSTR lpstrCustomFilter;
DWORD nMaxCustFilter;
DWORD nFilterIndex;
LPTSTR lpstrFile;
DWORD nMaxFile;
LPTSTR lpstrFileTitle;
DWORD nMaxFileTitle;
LPCTSTR lpstrInitialDir;
LPCTSTR lpstrTitle;
DWORD Flags;
WORD nFileOffset;
WORD nFileExtension;
LPCTSTR lpstrDefExt;
DWORD lCustData;
LPOFNHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
} OPENFILENAME;
Members
指定OPENFILENAME結構體的大小(字節)。這個決定你的對話框顯示98風格,還是2k風格。
hwndOwner :
指定擁有該對話框的窗口的標識,可以是任何有效窗口的句柄,也可以為空。
hInstance :
當在Flags中已經設置OFN_ENABLETEMPLATEHANMDLE標志,那麼hInstance是一個包含對話框模板的內存對象的句柄,假設OFN_ENABLETEMPLATE標志已經設置,那麼hInstance標識一個由lpTemplateName命名的對話框模板。
lpstrFilter:
指向一個以一對“\0”結尾的過濾字符串的緩沖區。在緩沖區中的最後一個字符串必定是以兩個NULL字符結束。(一般第一個字符串描述要過濾的格式,如“Text Files”,第二個字符串一般過濾格式進行指定,如“*.TXT”)。
如: _T(".JPG .JPEG\0*.jpg;*.jpeg\0.STL\0*.stl\0所有文件 \0 *.*\0 ");
lpstrFile :
指向一個包含文件名的緩沖區,用來初始化文件名編輯框。初始化不是必須的,也可以為空。Notice:如果OFN_ALLOWNULTISELECT標志已設定,用戶對文件進行多選,那麼該緩沖區包含所有被選擇的文件名,如果緩沖區太小,這個函數返回FALSE。
nMaxFile:
這個緩沖區的大小由lpstrFile指定。
lpstrFileTitle:
指向一個接收已選擇文件文件名和擴展名(不包括路徑信息)的緩沖區,也可以為空。
lpstrInitialDir :
指向一個指定初始化路徑的字符串,也就是最初彈出時所顯示的目錄。如果為NULL,則當前目錄為初始目錄。
lpstrTitle :
用來設置對話框的標題,如果為空,系統會用默認的標題(“打開” 或 “保存”)。
Flags :
可以設置一些標志或標志的組合來初始化對話框的顯示外觀。
Flag Meaning
OFN_ALLOWMULTISELECT:這個標志是允許選擇多個文件,如果你想選擇N個文件,那麼這個標志一定要設置。
OFN_ENABLEHOOK:允許lpfnHook為對話框指定一個HOOK函數,用來處理對話框的消息。也就可以攔截我們感興趣的消息。如:CDN_SELCHANGE
OFN_ENABLESIZING: 這個標志設定後,在對話框右下角會出現一個東東,允許用戶隨意擴大和縮小對話框
OFN_ENABLETEMPLATE:這個很重要,如果你想加入一個對話框模板做為預覽區, 這個標志一定要設置。
OFN_EXPLORER:這個標志是最重要的,如果你想定制對話框模板,利用HOOK函數,對文件進行多選,這個標志必須設定。
OFN_HIDEREADONLY:隱藏只讀屬性復選框。
OFN_READONLY:設定這標志,會在對話框的下方出現一個“Read Only”的復選框。
OFN_SHOWHELP:設置該標志,在對話框上會顯示 “幫助”按鈕。
lpstrDefExt :
指向一個包含默認擴展名的緩沖區。
lpfnHook:
指向一個HOOK的處理過程函數。在該函數裡實現攔截我們想要的消息。
lpTemplateName :
指向一個以對話框模板資源命名的字符串(以NULL結尾),該對話框模板在模塊中由hInstance成員標識。注意:如果想指定一個對話框模板資源必須在Flags中設定OFN_ENABLETEMPLATE。
如: m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG_HOOK)。
4、定制個性的CFileDialog對話框:
這個對Win98下的對話框用處比較大(個人觀點),我在這裡不詳細的說明只是給大家一個鏈接:http://www.codesky.net/article/list.asp?id=3920只要在CFileDialogEX dlg(TRUE)後面,加上如下代碼,就可以顯示圖2效果。
//--------只要加上下面這段代碼,就可以顯示2000下的打開文件對話框-------------
//------用來檢測目前的操作系統的版本信息
int nStructSize = 0;
DWORD dwVersion, dwWindowsMajorVersion, dwWindwosMinorVersion;
dwVersion = GetVersion();
dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
dwWindwosMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
if(dwVersion < 0x80000000)
{
nStructSize = 88; //2k,xp下顯示新的版本
}
else
{
nStructSize = 76; //98下顯示老版本,如圖1
}
dlg.m_ofn.lStructSize = nStructSize; //------用來檢測目前的操作系統的版本信息
3、m_ofn成員及OPENFILENAME的介紹:
OPENFILENAME結構體:雖然成員變量不少,但是我們常用的就幾個而已!該結構體包含一些保存或打開文件對話框的重要信息,比如過濾文件名,指定初始化路徑,對文件進行多選,顯示98風格還是2000風格的open/save對話框!
typedef struct tagOFN { // ofn
DWORD lStructSize;
HWND hwndOwner;
HINSTANCE hInstance;
LPCTSTR lpstrFilter;
LPTSTR lpstrCustomFilter;
DWORD nMaxCustFilter;
DWORD nFilterIndex;
LPTSTR lpstrFile;
DWORD nMaxFile;
LPTSTR lpstrFileTitle;
DWORD nMaxFileTitle;
LPCTSTR lpstrInitialDir;
LPCTSTR lpstrTitle;
DWORD Flags;
WORD nFileOffset;
WORD nFileExtension;
LPCTSTR lpstrDefExt;
DWORD lCustData;
LPOFNHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
} OPENFILENAME;
Members
lStructSize :
指定OPENFILENAME結構體的大小(字節)。這個決定你的對話框顯示98風格,還是2k風格。
hwndOwner :
指定擁有該對話框的窗口的標識,可以是任何有效窗口的句柄,也可以為空。
hInstance :
當在Flags中已經設置OFN_ENABLETEMPLATEHANMDLE標志,那麼hInstance是一個包含對話框模板的內存對象的句柄,假設OFN_ENABLETEMPLATE標志已經設置,那麼hInstance標識一個由lpTemplateName命名的對話框模板。
lpstrFilter:
指向一個以一對“\0”結尾的過濾字符串的緩沖區。在緩沖區中的最後一個字符串必定是以兩個NULL字符結束。(一般第一個字符串描述要過濾的格式,如“Text Files”,第二個字符串一般過濾格式進行指定,如“*.TXT”)。
如: _T(".JPG .JPEG\0*.jpg;*.jpeg\0.STL\0*.stl\0所有文件 \0 *.*\0 ");
lpstrFile :
指向一個包含文件名的緩沖區,用來初始化文件名編輯框。初始化不是必須的,也可以為空。Notice:如果OFN_ALLOWNULTISELECT標志已設定,用戶對文件進行多選,那麼該緩沖區包含所有被選擇的文件名,如果緩沖區太小,這個函數返回FALSE。
nMaxFile:
這個緩沖區的大小由lpstrFile指定。
lpstrFileTitle:
指向一個接收已選擇文件文件名和擴展名(不包括路徑信息)的緩沖區,也可以為空。
lpstrInitialDir :
指向一個指定初始化路徑的字符串,也就是最初彈出時所顯示的目錄。如果為NULL,則當前目錄為初始目錄。
lpstrTitle :
用來設置對話框的標題,如果為空,系統會用默認的標題(“打開” 或 “保存”)。
Flags :
可以設置一些標志或標志的組合來初始化對話框的顯示外觀。
Flag Meaning
OFN_ALLOWMULTISELECT:這個標志是允許選擇多個文件,如果你想選擇N個文件,那麼這個標志一定要設置。
OFN_ENABLEHOOK:允許lpfnHook為對話框指定一個HOOK函數,用來處理對話框的消息。也就可以攔截我們感興趣的消息。如:CDN_SELCHANGE
OFN_ENABLESIZING: 這個標志設定後,在對話框右下角會出現一個東東,允許用戶隨意擴大和縮小對話框
OFN_ENABLETEMPLATE:這個很重要,如果你想加入一個對話框模板做為預覽區, 這個標志一定要設置。
OFN_EXPLORER:這個標志是最重要的,如果你想定制對話框模板,利用HOOK函數,對文件進行多選,這個標志必須設定。
OFN_HIDEREADONLY:隱藏只讀屬性復選框。
OFN_READONLY:設定這標志,會在對話框的下方出現一個“Read Only”的復選框。
OFN_SHOWHELP:設置該標志,在對話框上會顯示 “幫助”按鈕。
lpstrDefExt :
指向一個包含默認擴展名的緩沖區。
lpfnHook:
指向一個HOOK的處理過程函數。在該函數裡實現攔截我們想要的消息。
lpTemplateName :
指向一個以對話框模板資源命名的字符串(以NULL結尾),該對話框模板在模塊中由hInstance成員標識。注意:如果想指定一個對話框模板資源必須在Flags中設定OFN_ENABLETEMPLATE。
如: m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG_HOOK)。
4、定制個性的CFileDialog對話框:
這個對Win98下的對話框用處比較大(個人觀點),我在這裡不詳細的說明
5. 怎麼樣把預覽區,放在對話框的右邊: 有時候,我們想把預覽區放在右邊,而且還想在最下面添加一些控件(如下圖三),該怎麼辦呢?當時,我找了半天資料也沒找到,後來我們老大告訴我應該這樣…..
圖三
其實很簡單,只要加一個StaticText控件就可以了,注意其ID設置,我設為stc32。但是其擺放位置很重要。如果你想要實現圖三的效果,必須如圖四這樣放置:
圖四
如果你想實現這樣的放置效果,並且復選框一定要在預覽區的下面,如圖五:
圖五
則Static text要如圖六這樣放置:
圖六
關於預覽區的放置,MSDN上有說明,但是我找不到(找了一個下午)!
6、多選問題的解決:
1).使用CFileDialog類選擇多個文件時,發現選擇的文件個數有限,這是因為m_ofn.nMaxFile的值有限:256Btye,解決的辦法是:將m_ofn.lpstrFile的緩沖區換成自己的指針。選擇多個文件,首先要給m_ofn的標志nFlags加上OFN_ALLOWMULTISELECT。當用戶選擇多個文件,CFileDialog會把選擇後的文件名拷貝到一個緩沖區,默認這個緩沖區有256個字符,這對於要求多選的用戶來說是不夠的。你可以將m_ofn.lpstrFile替換成自己的緩沖區指針:
char sBuffer[2000];
memset(sBuffer, 0, 2000);
CSTLFileDialog dlg(TRUE);
dlg.m_ofn.lpstrFile = sBuffer;
dlg.m_ofn.nMaxFile = 2000; //解決多選問題
這個方法解決多選問題,就是簡便易懂。如果你多選的真好是257或300個字符,那麼其余的1400個空間易浪費了。下面介紹一個動態解決分配的方法,請看代碼:
//------1.動態分配內存空間,解決多選的問題---------------------------------------
void CSTLFileDialog::SolveMoreSelect()
{
TCHAR chBuffer;
TCHAR *chFiles = NULL;
TCHAR *chFolder = NULL;
UINT nFileSize;
UINT nFolderSize;
nFileSize = CommDlg_OpenSave_GetSpec(GetParent()->m_hWnd, &chBuffer,
1);
nFolderSize = CommDlg_OpenSave_GetFolderPath(GetParent()->m_hWnd, &chBuffer,
1);
if((nFileSize + nFolderSize) > m_ofn.nMaxFile)
{
if(chFiles)
{
delete[] chFiles;
}
chFiles = new TCHAR[nFileSize + 1];
CommDlg_OpenSave_GetSpec(GetParent()->m_hWnd, chFiles, nFileSize);
if(chFolder)
{
delete[] chFolder;
}
chFolder = new TCHAR[nFolderSize + 1];
CommDlg_OpenSave_GetSpec(GetParent()->m_hWnd, chFolder, nFolderSize);
}
else
{
if(chFiles)
{
delete[] chFiles;
chFiles = NULL;
}
if(chFolder)
{
delete[] chFolder;
chFolder = NULL;
}
}
7、對預覽問題的收集,如對文本,聲音等
結束語:
在這裡我要感謝幫助過我的朋友們,希望您對我寫的文章提出寶貴的意見!另外如果有時間我的另一篇文章將介紹在CFileDialog的打開文件對話框中,實現對3D圖形的預覽,也就是對STL(CAD中常用的存儲格式)格式的文件進行預覽,這才是我的要做的!如果表述不清之處,請Email聯系!
本文配套源碼