(譯注:原文代碼的Demo_VC7沒有在同Demo_VC6一樣顯示滾動條視圖,修改之)
開發環境:Windows XP/Server 2003/2000/NT4.0-SP6/98/Me, MS Visual Sudio 6.0/2003, GDI+
介紹
CGdiplusFileOpenDialog和CGdiplusFileSaveAsDialog類提供了一個在GDI+的MFC應用程序輕松實現文件打開和保存對話框的方法。
主要特點是:
它們可以動態地裝入關於支持圖像的解碼器/編碼器和構建文件過濾清單。
它們可以獲得當前圖像編碼器標識碼(CLSID)以供需要將其作為一個參數的GDI+函數使用。
它們可以檢查和驗證文件名和擴展名。
你可以在類的描述和demo應用程序中找到更多的詳情。
(類的)層次表
CGdiplusFileDialog類
CGdiplusFileDialog繼承於MFC CFileDialog類,同時也是CGdiplusFileOpenDialog和CGdiplusFileSaveAsDialog的抽象基類。
封裝一個包含所支持的解碼器/編碼器的數組(m_arrCodecInfo)
實現基函數TranslateFilter:轉換一個MFC-like文件過濾器(使用一個''|''作為分隔符)到一個OPENFILENAME結構文件過濾器(使用''\0''作為分隔符)
聲明兩個純虛函數:FillCodecInfoArray 和ConstructMFCStyleFilte;在派生類中,覆寫函數實現特定操作。
覆寫CFileDialog::DoModal;在調用基類函數之前調用,它
o 檢查GDI+庫是否被初始化
o 調用FillCodecInfoArray、 ConstructMFCStyleFilter 和 TranslateFilter函數
CGdiplusFileOpenDialog類
CGdiplusFileOpenDialog實現文件打開命令對話框。
覆寫CGdiplusFileDialog::FillCodecInfoArray並調用Gdiplus::GetImageDecoders填充關於可用譯碼器的信息數組。
o 文件格式的名稱(如:"JPEG")
o 已用擴展名(如:"*.JPG、*.JPEG、*.JPE、*.JFIF")
o 在打開對話框(譯注:原文為Save As dialog,應該是Open dialog,筆誤了)中使用的缺省擴展名(如:"JPG")
o 解碼器標識碼
覆寫CGdiplusFileDialog::ConstructMFCStyleFilter構建一個"MFC 樣式"的過濾器(使用一個''|''作為分隔符);一個附加的"All GDI+ supported"(所有GDI+支持)的過濾項被添入
舉例
#include "GdiplusFileOpenDialog.h"
// ...
bool CFoo::LoadImage(Image*& pImage)
{
bool bLoaded = false;
CGdiplusFileOpenDialog dlgFile;
if(IDOK == dlgFile.DoModal())
{
CString strPathName = dlgFile.GetPathName();
pImage = Image::FromFile(strPathName.AllocSysString());
Status status = pImage->GetLastStatus();
if(Ok == status)
{
bLoaded = true;
}
}
return bLoaded;
}
CGdiplusFileSaveAsDialog類
CGdiplusFileSaveAsDialog實現文件保存的通用型對話框。
覆寫CGdiplusFileDialog::FillCodecInfoArray並調用Gdiplus::GetImageEncoders來填充關於可用編碼器的信息數組。
o 文件格式的名稱(如:" BMP ")
o 已用擴展名(如:"*. BMP、*. DIB、*. RLE ")
o 在保存對話框中使用的缺省擴展名(如:" BMP ")
覆寫CGdiplusFileDialog::ConstructMFCStyleFilter構建"MFC 樣式"的過濾器(使用一個''|''作為分隔符)
覆寫CFileDialog::OnInitDone 和 CFileDialog::OnTypeChange來設置缺省擴展名並裝入缺省編碼器標識碼(m_clsid成員變量)
實現public方法GetCodecCLSID;codec(編碼器/譯碼器)CLSID進一步被傳遞到Gdiplis::Image::Save函數
覆寫CFileDialog::OnFileNameOK以實現文件擴展名檢查:
o 如果文件名沒有擴展名,使用缺省擴展名和CLSID
o 如果文件名有一個擴展名並且可以被codec信息數組找到,擴展名和相應的CLSID將用來代替缺省值
o 如果文件名有一個擴展名同時不能被codec信息數組找到,它返回TRUE同時對話框保持顯示以便用戶輸入另一個文件名
舉例
#include "GdiplusFileSaveAsDialog.h"
// ...
bool CFoo::SaveImage(Image* pImage)
{
bool bSaved = false;
CGdiplusFileSaveAsDialog dlgFile;
if(IDOK == dlgFile.DoModal())
{
CLSID clsid = dlgFile.GetCodecCLSID();
CString strPathName = dlgFile.GetPathName();
Status status = pImage->Save(strPathName.AllocSysString(),
&clsid);
if(Ok == status)
{
bSaved = true;
}
}
return bSaved;
}
Demo應用程序
Demo應用程序是一個建立在MDI框架上的簡單的圖像浏覽器。它演示了如何使用CGdiplusFileOpenDialog 和 CGdiplusFileSaveAsDialog.
StdAfx.h 中的包含和聲明
typedef unsigned __int32 ULONG_PTR;
#include <afxtempl.h>
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;
注意
對於比VC++6.0更新的版本,或如果你已安裝了platform SDK更新,請移去ULONG_PTR的定義。
(僅在VC++ 6.0下)確保gdiplus.lib 的位置應在Tools/Option/Directories/Library文件夾下;抑或你可以在pragma comment指示中提供其完全路徑和文件名稱。
初始化和發布GDI+
你必須在做如何GDI+調用前調用GdiplusStartup,同時在你結束使用GDI+時調用GdiplusShutdown。
class CDemoApp : public CWinApp
{
// ...
// Attributes
protected:
ULONG_PTR m_gdiplusToken;
// ...
// Implementation
protected:
bool InitGdiplus();
void TermGdiplus();
// ...
};
// Called from CDemoApp::InitInstance
bool CDemoApp::InitGdiplus()
{
GdiplusStartupInput gdiplusStartupInput;
Status status = GdiplusStartup(&m_gdiplusToken,
&gdiplusStartupInput,
NULL);
return (Ok == status);
}
// Called from CDemoApp::ExitInstance
void CDemoApp::TermGdiplus()
{
GdiplusShutdown(m_gdiplusToken);
}
使用CGdiplusFileOpenDialog
去掉調用基類信息處理器的ID_FILE_OPEN命令的缺省映射並將該命令映射到在一個CWinApp派生類中處理(譯注:即Demo程序中的CDemoApp類)。
void CDemoApp::OnFileOpen()
{
CGdiplusFileOpenDialog dlgFile;
if(IDOK == dlgFile.DoModal())
{
OpenDocumentFile(dlgFile.GetPathName());
}
}
覆寫CDocument::OnOpenDocument虛函數。
class CDemoDoc : public CDocument
{
// ...
// Attributes
protected:
Image* m_pImage;
// Operations
public:
Image* GetImage() {return m_pImage;}
// ...
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDemoDoc)
public:
virtual BOOL OnOpenDocument(LPCTSTR pszPathName);
//}}AFX_VIRTUAL
// ...
};
BOOL CDemoDoc::OnOpenDocument(LPCTSTR pszPathName)
{
SafeDeleteImage();
m_pImage = Image::FromFile(CString(pszPathName).AllocSysString());
return (Ok == m_pImage->GetLastStatus());
}
使用CGdiplusFileSaveAsDialog
在CDocument派生類(譯注:即Demo程序中的CDemoDoc類)中映射ID_FILE_SAVE_AS命令。在CGdiplusFileSaveAsDialog::DoModal返回後,調用GetPathName和GetCodecCLSID以傳遞(路徑、文件名、Codec CLSID)到Image::Save方法。
void CDemoDoc::OnFileSaveAs()
{
CGdiplusFileSaveAsDialog dlgFile;
if(IDOK == dlgFile.DoModal())
{
CLSID clsid = dlgFile.GetCodecCLSID();
CString strPathName = dlgFile.GetPathName();
Status status = m_pImage->Save(strPathName.AllocSysString(),
&clsid);
if(Ok != status)
{
TRACE2(_T("\nFailed to save image in ''%s'' file\n")
_T("GDI+ Error: %u"),
strPathName,
status);
}
}
}
繪圖
在CDemoView::OnDraw中,使用一個Gdiplus::Graphics對象來繪圖。
注意這只是一個例子並且設計得盡可能的簡單。
void CDemoView::OnDraw(CDC* pDC)
{
CDemoDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
Image* pImage = pDoc->GetImage();
if(NULL != pImage)
{
Graphics graphics(*pDC);
Status status = graphics.GetLastStatus();
if(Ok == status)
{
graphics.DrawImage(pImage, 0, 0,
pImage->GetWidth(), pImage->GetHeight());
}
}
}
結束提示:
gdiplus.dll已經包含在Windows XP 和 Windows Server 2003中
對於運行在Microsoft Windows NT 4.0-SP6/2000/98/Me之上應用程序的可再分發,gdiplus.dll是必需的。
如果你再分發gdiplus.dll,推薦你將之放入應用程序的文件夾。
下載
Platform SDK Update(http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm):包含GDI+頭文件,gdiplus.lib, 和 gdiplus.dll(VC++ 6.0所需)
Platform SDK Redistributable: GDI+(http://www.microsoft.com/downloads/details.aspx?FamilyID=6a63ab9c-df12-4d41-933c-be590feaa05a&DisplayLang=en):可再分發gdiplus.dll,對於Windows NT 4.0-SP6/2000/98/Me
本文配套源碼