使用GDI+的MFC应用程序的文件打开和保存对话框

 转自: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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值