转自:http://www.vckbase.com/index.php/wv/1409
(译注:原文代码的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+支持)的过滤项被添入
举例
01.
#include "GdiplusFileOpenDialog.h"
02.
03.
// ...
04.
05.
bool
CFoo::LoadImage(Image*& pImage)
06.
07.
{
08.
09.
bool
bLoaded =
false
;
10.
11.
CGdiplusFileOpenDialog dlgFile;
12.
13.
if
(IDOK == dlgFile.DoModal())
14.
15.
{
16.
17.
CString strPathName = dlgFile.GetPathName();
18.
19.
pImage = Image::FromFile(strPathName.AllocSysString());
20.
21.
Status status = pImage->GetLastStatus();
22.
23.
if
(Ok == status)
24.
25.
{
26.
27.
bLoaded =
true
;
28.
29.
}
30.
31.
}
32.
33.
return
bLoaded;
34.
35.
}
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同时对话框保持显示以便用户输入另一个文件名
举例
01.
#include "GdiplusFileSaveAsDialog.h"
02.
03.
// ...
04.
05.
bool
CFoo::SaveImage(Image* pImage)
06.
07.
{
08.
09.
bool
bSaved =
false
;
10.
11.
CGdiplusFileSaveAsDialog dlgFile;
12.
13.
if
(IDOK == dlgFile.DoModal())
14.
15.
{
16.
17.
CLSID clsid = dlgFile.GetCodecCLSID();
18.
19.
CString strPathName = dlgFile.GetPathName();
20.
21.
Status status = pImage->Save(strPathName.AllocSysString(),
22.
23.
&clsid);
24.
25.
if
(Ok == status)
26.
27.
{
28.
29.
bSaved =
true
;
30.
31.
}
32.
33.
}
34.
35.
return
bSaved;
36.
37.
}
Demo应用程序
Demo应用程序是一个建立在MDI框架上的简单的图像浏览器。它演示了如何使用CGdiplusFileOpenDialog 和CGdiplusFileSaveAsDialog.
StdAfx.h 中的包含和声明
1.
typedef
unsigned
__int32
ULONG_PTR
;
2.
#include < afxtempl.h >
3.
#include < gdiplus.h >
4.
#pragma comment(lib, "gdiplus.lib")
5.
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。
01.
class
CDemoApp :
public
CWinApp
02.
03.
{
04.
05.
// ...
06.
07.
// Attributes
08.
09.
protected
:
10.
11.
ULONG_PTR
m_gdiplusToken;
12.
13.
// ...
14.
15.
// Implementation
16.
17.
protected
:
18.
19.
bool
InitGdiplus();
20.
21.
void
TermGdiplus();
22.
23.
// ...
24.
25.
};
26.
27.
// Called from CDemoApp::InitInstance
28.
29.
bool
CDemoApp::InitGdiplus()
30.
31.
{
32.
33.
GdiplusStartupInput gdiplusStartupInput;
34.
35.
Status status = GdiplusStartup(&m_gdiplusToken,
36.
37.
&gdiplusStartupInput,
38.
39.
NULL);
40.
41.
return
(Ok == status);
42.
43.
}
44.
45.
// Called from CDemoApp::ExitInstance
46.
47.
void
CDemoApp::TermGdiplus()
48.
49.
{
50.
51.
GdiplusShutdown(m_gdiplusToken);
52.
53.
}
使用CGdiplusFileOpenDialog
去掉调用基类信息处理器的ID_FILE_OPEN命令的缺省映射并将该命令映射到在一个CWinApp派生类中处理(译注:即Demo程序中的CDemoApp类)。
01.
void
CDemoApp::OnFileOpen()
02.
03.
{
04.
05.
CGdiplusFileOpenDialog dlgFile;
06.
07.
if
(IDOK == dlgFile.DoModal())
08.
09.
{
10.
11.
OpenDocumentFile(dlgFile.GetPathName());
12.
13.
}
14.
15.
}
覆写CDocument::OnOpenDocument虚函数。
01.
class
CDemoDoc :
public
CDocument
02.
03.
{
04.
05.
// ...
06.
07.
// Attributes
08.
09.
protected
:
10.
11.
Image* m_pImage;
12.
13.
// Operations
14.
15.
public
:
16.
17.
Image* GetImage() {
return
m_pImage;}
18.
19.
// ...
20.
21.
// Overrides
22.
23.
// ClassWizard generated virtual function overrides
24.
25.
//{{AFX_VIRTUAL(CDemoDoc)
26.
27.
public
:
28.
29.
virtual
BOOL
OnOpenDocument(
LPCTSTR
pszPathName);
30.
31.
//}}AFX_VIRTUAL
32.
33.
// ...
34.
35.
};
36.
37.
BOOL
CDemoDoc::OnOpenDocument(
LPCTSTR
pszPathName)
38.
39.
{
40.
41.
SafeDeleteImage();
42.
43.
m_pImage = Image::FromFile(CString(pszPathName).AllocSysString());
44.
45.
return
(Ok == m_pImage->GetLastStatus());
46.
47.
}
使用CGdiplusFileSaveAsDialog
在CDocument派生类(译注:即Demo程序中的CDemoDoc类)中映射ID_FILE_SAVE_AS命令。在CGdiplusFileSaveAsDialog::DoModal返回后,调用GetPathName和GetCodecCLSID以传递(路径、文件名、Codec CLSID)到Image::Save方法。
01.
void
CDemoDoc::OnFileSaveAs()
02.
03.
{
04.
05.
CGdiplusFileSaveAsDialog dlgFile;
06.
07.
if
(IDOK == dlgFile.DoModal())
08.
09.
{
10.
11.
CLSID clsid = dlgFile.GetCodecCLSID();
12.
13.
CString strPathName = dlgFile.GetPathName();
14.
15.
Status status = m_pImage->Save(strPathName.AllocSysString(),
16.
17.
&clsid);
18.
19.
if
(Ok != status)
20.
21.
{
22.
23.
TRACE2(_T(
"\nFailed to save image in ''%s'' file\n"
)
24.
25.
_T(
"GDI+ Error: %u"
),
26.
27.
strPathName,
28.
29.
status);
30.
31.
}
32.
33.
}
34.
35.
}
绘图
在CDemoView::OnDraw中,使用一个Gdiplus::Graphics对象来绘图。
注意这只是一个例子并且设计得尽可能的简单。
01.
void
CDemoView::OnDraw(CDC* pDC)
02.
03.
{
04.
05.
CDemoDoc* pDoc = GetDocument();
06.
07.
ASSERT_VALID(pDoc);
08.
09.
Image* pImage = pDoc->GetImage();
10.
11.
if
(NULL != pImage)
12.
13.
{
14.
15.
Graphics graphics(*pDC);
16.
17.
Status status = graphics.GetLastStatus();
18.
19.
if
(Ok == status)
20.
21.
{
22.
23.
graphics.DrawImage(pImage, 0, 0,
24.
25.
pImage->GetWidth(), pImage->GetHeight());
26.
27.
}
28.
29.
}
30.
31.
}
结束提示:
gdiplus.dll已经包含在Windows XP 和 Windows Server 2003中
对于运行在Microsoft Windows NT 4.0-SP6/2000/98/Me之上应用程序的可再分发,gdiplus.dll是必需的。
如果你再分发gdiplus.dll,推荐你将之放入应用程序的文件夹。
下载
Platform SDK Update:包含GDI+头文件,gdiplus.lib, 和 gdiplus.dll(VC++ 6.0所需)
Platform SDK Redistributable: GDI+:可再分发gdiplus.dll,对于Windows NT 4.0-SP6/2000/98/Me