图片预览参考网址

52 篇文章 1 订阅

http://yq1518602434.blog.163.com/blog/static/20293708420123167280845/

VC实现BMP,JPG,GIF图片预览  

效果图:
VC实现BMP,JPG,GIF图片预览 - 一轮居士 - 平平淡淡的幸福
创建类CCustomDlg,派生于CFileDialog,要达到预览效果,需要在CCustomDlg类的OnInitDialog函数中调用CStatic类的成员函数
SubclassDlgItem(IDC_STATIC1,this)将picture控件与对话框连接起来(IDD_STATIC1为picture控件的ID),同时需要在CCustomDlg的构造函数中设置属性:
m_ofn.Flags |=(OFN_EXPLORER | OFN_ENABLETEMPLATE);
m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG1);(IDD_DIALOG1是新建的含picture控件的对话框)
我们知道,MFC中的CFileDialog类封装了文件对话框的功能.它的成员m_ofnOPENFILENAME类型的结构.我们要想定制文件对话框,只需从CFileDialog中派生一个新类,然后如下设置m_ofn的内部成员:

  m_ofn.Flags |=(OFN_EXPLORER | OFN_ENABLETEMPLATE);

  m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEOPENPREVIEW);

IDD_FILEOPENPREVIEW是我们创建的对话框资源的ID,包含了我们想要在定制的文件对话框中加入的控件和它们的定位信息.设置了OFN_EXPLORER属性后,系统将创建一个标准文件对话框的子对话框,其中不仅包含了原先的标准控件,还加入了我们在IDD_FILEOPENPREVIEW中包含的控件,并且它们两者的位置是由IDD_FILEOPENPREVIEW中的定位信息所决定的)

要想达到预览效果,需要重载OnFileNameChange函数来处理用户从文件列表中选择了一个新的文件或目录的情形。
此外,对于bmp图片,只要调用函数LoadImage()和Setbitmap()即可显示;
对于jpg和gif图片,因为其为压缩存储,必须采用流形式进行显示。代码如下:
void CPicture::Show(HDC dc,int x,int y,int width,int height)
{
    if (m_pPicture != NULL)
    {
        long nWidth,nHeight;
        m_pPicture->get_Width(&nWidth);
        m_pPicture->get_Height(&nHeight);       
       
        m_pPicture->Render(dc,x,y,width,height,0,nHeight,nWidth,-nHeight,NULL);
    }
}
BOOL CPicture::LoadImage(LPCTSTR szPath)
{
    CFile file;
    if( !file.Open( szPath, CFile::modeRead) )
        return FALSE;
 
    DWORD    m_nFileLen;
    m_nFileLen = file.GetLength();
 
    m_hMem = ::GlobalAlloc( GMEM_MOVEABLE, m_nFileLen );
    LPVOID lpBuf = ::GlobalLock( m_hMem );
    if( file.Read( lpBuf, m_nFileLen ) != m_nFileLen )
        return FALSE;
    file.Close();
 
    ::GlobalUnlock( m_hMem );
 
    if ( CreateStreamOnHGlobal( m_hMem, TRUE, &m_pStream ) !=S_OK )    
        return FALSE;
 
    if ( OleLoadPicture(m_pStream,m_nFileLen,TRUE,IID_IPicture,(LPVOID * )&m_pPicture ) !=S_OK )
        return FALSE;
    return TRUE;
}
 
 
 
示例程序下载到了:D:\Yifei\Download\VC++\网上实例\位图预览
程序名称:ShowImagePreview
 

 

http://bbs.csdn.net/topics/80446767

 

http://blog.csdn.net/jacky_qiu/article/details/6004558

VC实现图片移动(动画效果)

 

http://www.vckbase.com/index.php/wv/1139

在打开文件对话框上实现图象预览

前言:

本文主要是介绍在打开文件对话框,实现对图象,文本等预览(在VC++6.0下实现)。本人的水平有限,如有表达不清之处,请谅解,请各位提出意见与建议!

正文:

1、Win98下预览对话框的实现:

2、Win2000,XP下预览对话框的实现:

3、m_ofn成及OPENFILENAME的介绍:

4、定制个性的CFileDialog对话框:

5、怎么样把预览区,放在对话框的右边:

6、多选问题的解决:

7、对预览问题的收集,如对文本,声音等:

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”。

01. For example:
02.  
03.         CString strPathName;
04.  
05.         CFileDialogEx dlg(TRUE);
06.  
07.         if(dlg.DoModal() == IDOK)
08.  
09.         {
10.  
11.         POSITION Pos;
12.  
13.         Pos = dlg.GetStartPosition();
14.  
15.         while(Pos != NULL)
16.  
17.         {
18.  
19.         strPathName = dlg.GetNextPathName(Pos);
20.  
21.         if(!strPathName.IsEmpty())
22.  
23.         {
24.  
25.         MessageBox(strPathName, _T("GetNextPathName"), MB_ICONINFORMATION);
26.  
27.         }
28.  
29.         }
30.  
31.         }

注:由于时间紧,在Debug版本下,双击选中文件后,有暴停的现象(内存泄漏),而且显示效果也没有进行处理!

2、Win2000,XP下预览对话框的实现:比图一多了左面的快捷栏(方便用户查找)。其实这个实现很简单,只要判断一下系统的版本就可以了,但是98下只显示图一所示的对话框,2000,XP则显示图二的对话框,这是MS在98以后的版本,对这个东东重新进行了封装!
详情请看链接: 利用MFC的CFileDialog怎么样生成Win2000的文件对话框,http://www.chinaaspx.com/archive/VC/1068.htm

图二

只要在CFileDialogEX dlg(TRUE)后面,加上如下代码,就可以显示图2效果。

01.   //--------只要加上下面这段代码,就可以显示2000下的打开文件对话框-------------
02.  
03.   //------用来检测目前的操作系统的版本信息
04.  
05. intnStructSize = 0;
06.  
07.   DWORDdwVersion, dwWindowsMajorVersion, dwWindwosMinorVersion;
08.  
09.   dwVersion = GetVersion();
10.  
11.   dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
12.  
13.   dwWindwosMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
14.  
15.   if(dwVersion < 0x80000000)
16.  
17.   {
18.  
19.   nStructSize = 88;//2k,xp下显示新的版本
20.  
21.   }
22.  
23.   else
24.  
25.   {
26.  
27.   nStructSize = 76;//98下显示老版本,如图1
28.  
29.   }
30.  
31.   dlg.m_ofn.lStructSize = nStructSize;//------用来检测目前的操作系统的版本信息

3、m_ofn成员及OPENFILENAME的介绍:

OPENFILENAME结构体:虽然成员变量不少,但是我们常用的就几个而已!该结构体包含一些保存或打开文件对话框的重要信息,比如过滤文件名,指定初始化路径,对文件进行多选,显示98风格还是2000风格的open/save对话框!

01. typedefstructtagOFN {// ofn
02.  
03.         DWORDlStructSize;
04.  
05.         HWNDhwndOwner;
06.  
07.         HINSTANCEhInstance;
08.  
09.         LPCTSTRlpstrFilter;
10.  
11.         LPTSTRlpstrCustomFilter;
12.  
13.         DWORDnMaxCustFilter;
14.  
15.         DWORDnFilterIndex;
16.  
17.         LPTSTRlpstrFile;
18.  
19.         DWORDnMaxFile;
20.  
21.         LPTSTRlpstrFileTitle;
22.  
23.         DWORDnMaxFileTitle;
24.  
25.         LPCTSTRlpstrInitialDir;
26.  
27.         LPCTSTRlpstrTitle;
28.  
29.         DWORDFlags;
30.  
31.         WORDnFileOffset;
32.  
33.         WORDnFileExtension;
34.  
35.         LPCTSTRlpstrDefExt;
36.  
37.         DWORDlCustData;
38.  
39.         LPOFNHOOKPROC lpfnHook;
40.  
41.         LPCTSTRlpTemplateName;
42.  
43.         } OPENFILENAME;
44.  
45.         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下的对话框用处比较大(个人观点),我在这里不详细的说明只是给大家一个链接:http://www.codesky.net/article/list.asp?id=3920

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替换成自己的缓冲区指针:

1. charsBuffer[2000];
2. memset(sBuffer, 0, 2000);
3. CSTLFileDialog dlg(TRUE);
4. dlg.m_ofn.lpstrFile = sBuffer;
5. dlg.m_ofn.nMaxFile = 2000;//解决多选问题

这个方法解决多选问题,就是简便易懂。如果你多选的真好是257或300个字符,那么其余的1400个空间易浪费了。下面介绍一个动态解决分配的方法,请看代码:

//------1.动态分配内存空间,解决多选的问题---------------------------------------

01. voidCSTLFileDialog::SolveMoreSelect()
02.  
03.         {
04.  
05.         TCHARchBuffer;
06.  
07.         TCHAR*chFiles = NULL;
08.  
09.         TCHAR*chFolder = NULL;
10.  
11.          
12.  
13.         UINTnFileSize;
14.  
15.         UINTnFolderSize;
16.  
17.          
18.  
19.         nFileSize = CommDlg_OpenSave_GetSpec(GetParent()->m_hWnd, &chBuffer,
20.         1);
21.  
22.         nFolderSize = CommDlg_OpenSave_GetFolderPath(GetParent()->m_hWnd, &chBuffer,
23.         1);
24.  
25.          
26.  
27.         if((nFileSize + nFolderSize) > m_ofn.nMaxFile)
28.  
29.         {
30.  
31.         if(chFiles)
32.  
33.         {
34.  
35.         delete[] chFiles;
36.  
37.         }
38.  
39.         chFiles =newTCHAR[nFileSize + 1];
40.  
41.         CommDlg_OpenSave_GetSpec(GetParent()->m_hWnd, chFiles, nFileSize);
42.  
43.         if(chFolder)
44.  
45.         {
46.  
47.         delete[] chFolder;
48.  
49.         }
50.  
51.         chFolder =newTCHAR[nFolderSize + 1];
52.  
53.         CommDlg_OpenSave_GetSpec(GetParent()->m_hWnd, chFolder, nFolderSize);
54.  
55.         }
56.  
57.         else
58.  
59.         {
60.  
61.         if(chFiles)
62.  
63.         {
64.  
65.         delete[] chFiles;
66.  
67.         chFiles = NULL;
68.  
69.         }
70.  
71.         if(chFolder)
72.  
73.         {
74.  
75.         delete[] chFolder;
76.  
77.         chFolder = NULL;
78.  
79.         }
80.  
81.         }

7、对预览问题的收集,如对文本,声音等:

如果您看我的代码比较困难,请到以下链接处:

1)、对文本文件实现预览:http://www.vckbase.com/document/viewdoc/?id=417

2)、对图象文件(2D)实现预览:http://www.codeproject.com/dialog/imagepreviewdialog.asp

3)、对位图文件实现预览:http://www.vccode.com/file_show.php?id=891

4)、对声音文件实现预听:http://www.vccode.com/file_show.php?id=895

结束语:

在这里我要感谢帮助过我的朋友们,希望您对我写的文章提出宝贵的意见!另外如果有时间我的另一篇文章将介绍在CFileDialog的打开文件对话框中,实现对3D图形的预览,也就是对STL(CAD中常用的存储格式)格式的文件进行预览,这才是我的要做的!如果表述不清之处,请Email联系!

 

http://www.vckbase.com/index.php/wv/766.html

在你的MFC应用程序中显示一个JPG文件

 

在VB中,我可以通过创建一个图像控件来显示一个JPG或GIF文件,但是我如何在我的MFC应用程序中显示一个JGP文件呢? 许多读者

好问题!有时使用VB的程序员觉得这个很容易。只要往你的表中拖入一个图像控件,然后你就可以往下做了……然而C++程序员就不得不感到烦恼和头疼。那我们要做些什么呢,编写我们自己的JPG解压函数吗?

当然不是这样的!事实上,C/C++程序员能够使用与VB程序员所使用的非常类似(可以说是差不多)的图像控件。我并没有开玩笑。VB图像控件是基于一个叫"IPicture"的系统COM类(如 Figure 1 所示)。IPicture管理一个图像对象和它的特性。图像对象为位图提供一个抽象化的东西。Windows提供了一个知道如何处理BMP,JPG和GIF位图的标准操作。你所要做的只是使IPicture实例化,并调用Render。你可以调用一个叫做"OleLoadPicture"的特殊函数,来替代通常所要调用的"CoCreateInstance"。

1. IStream* pstm =// 需要一个信息流
2. IPicture* pIPicture;
3. hr = OleLoadPicture(pstm, 0, FALSE,
4. IID_IPicture, (void**)&pIPicture);

OleLoadPicture从信息流里加载图像,并创建一个你能够用来显示图像的新的IPicture对象。

1. rc =// 要在其中显示的矩形
2. // 转换rc为HIMETRIC
3. spIPicture->Render(pDC, rc);

IPicture包揽了所有的令人厌烦的用来推算图像是否是Windows位图,JPEG,或GIF文件的事, 它甚至还可以推算图像是否是图标和图元文件!自然,其中的细节是需要些技巧,所以我就写了一个将它们都包含其中的叫"ImgView"( 如 Figure 2 所示)的演示程序。

 

Figure 2 ImgView

ImgView是一个典型的MFC文档/视图结构的应用程序,它使用了一个我以前写的叫"CPicture"的类(如 Figure 3 所示)来封装IPicture。CPicture将一些麻烦的COM类型的参数映射为那些更容易被MFC程序员接受的类型。例如,CPicture可以让你直接从一个文件名加载图像,如CFile或CArchive,而不是处理信息流;而且CPicture::Render完成了所有的令人厌烦的而又是IPicture所需要的HIMETRIC坐标转换,这样,你就没必要去做这些了。CPicture甚至还有一个可以从你的资源数据中加载图像的加载函数,所以要显示一个资源图像,你所要做的就是像下面那样写:

1. CPicture pic(ID_MYPIC);// 加载pic
2. CRect rc(0,0,0,0);     // 使用默认 rc
3. pic.Render(pDC, rc);   // 显示它

什么能够使工作变得更加容易呢?CPicture::Render能获得一个你想在其中显示图像的矩形。IPicture可以适当地拉伸图像。如果你传递了一个空的矩形,CPicture就使用图像本来的尺寸,并不对其进行拉伸。对于图像本身,CPicture要寻找一个名为"IMAGE"的资源类型,所以你必须对你的RC文件进行如下的编写:

1. IDR_MYPIC IMAGE MOVEABLE PURE"res\\MyPic.jpg"

总的来说,CPicture相当没头脑。它有一个ATL CComQIPtr巧妙的指向IPicture界面的指针,其中不同的加载函数通过调用OleLoadPicture来初始化该界面。CPicture提供一般的封装函数来调用里面的IPicture。CPicture仅封装了我编写ImgView所需要的IPicture成员函数;这么做是因为我是这样的一个懒惰的程序员。如果你还需要调用IPicture::get_Handle或一些其它的较少用的IPicture成员函数,很抱歉,你就只好自己为其添加封装了。至少,这代码是件琐碎的事情。

顺便说一下,在我写完CPicture后,我就觉得有件事要提一下,那就是我发现一个鲜为人知的叫做"CPictureHolder"的MFC类也做了绝大部分的类似的事情。你可以在afxctl.h中找到它。

正如我先前提到的,ImgView是一个典型的MFC文档/视图结构的应用程序,其中CPictureDoc和CPictureView类分别对应于文档和视图结构。如 Figure 4 所示 中显示了该视图。CPictureDoc有些琐碎;它使用CPicture来保存图像--

1. classCPictureDoc :publicCDocument {
2. protected:
3.   CPicture m_pict;// 图像
4. };

,并且CPictureDoc::Serialize调用CPicture::Load从MFC所建立的存档中读取图像。

1. voidCPictureDoc::Serialize(CArchive& ar)
2. {
3.  
4.   if(ar.IsLoading()) {
5.     m_pict.Load(ar);
6.   }
7. }

仅仅是为了有趣,CPictureDoc::OnNewDocument从程序的资源数据中加载了一张漂亮的NASA图像。为了显示这图像,CPictureView::OnDraw调用了CPicture::Render。

1. voidCPictureView::OnDraw(CDC* pDC)
2. {
3.   CPictureDoc* pDoc = GetDocument();
4.   CPicture* ppic = pDoc->GetPicture();
5.   CRect rc;
6.   GetImageRect(rc);
7.   ppic->Render(pDC,rc);
8. }

GetImageRect是CPictureView的一个函数,它依靠当前ImgView缩放比例而返回一个适当的图像矩形。(ImgView可以通过25%,33%,50%,75%,100%或"自适应比例"这六种比例形式来显示图像)。GetImageRect调用CPicture::GetImageSize获得真实的图像尺寸,随后依据比例适当地缩放。

现在,在CPictureView中剩下的就是典型的CScrollView部分,其中有用于视的初始化和滚动条尺寸与句柄命令的设置之类的代码。对于IPicture唯一有意思的是,正如之前我所提到的,IPicture::Render希望它的坐标是HIMETRIC单位的,然而一般的MFC应用程序使用的是默认的MM_TEXT映射模式。不要担心,CPicture::Render和CPicture::GetImageSize对其做了魔术般的转换,所以你就没必要为这样世俗的和令人厌烦的琐事而操过多的心了。

CPictureView有一个消息处理函数值得注意,它就是OnEraseBkgnd。它被要求在图像比视的客户区小的情况时对空白的区域进行填充(如图5所示)。OnEraseBkgnd创建一个与图像大小一样的剪切的矩形,然后将客户矩形填充为黑色。当你变化窗口尺寸的时候,这样的剪切就避免了闪烁,其中的FillRect并没有往被剪切的矩形中填充。这是标准的Windows图形101。

 

图 5 OnEraseBkgnd填充被剪切的图像

IPicture/CPicture真正使得显示图像变得容易了。它甚至可以完成调色板的实现和所有令人厌烦的事情。你可以丢掉原先所有的用来加载调色板,BitBlts和StretchBlts等的DIB的绘图代码了,IPicture是个很好的办法。如果你还没有使用IPicture来显示图像,那么现在就开始用它吧!

所有的事情都是这么的简单,这让我想写另一个类来试试。当你想写一个图像浏览器时,CPictureView是很好用的,但要是你想将一个图像加到对话框或其它的一些窗口上,那该怎么办呢?为了实现这,我写了另一个类,CPictureCtrl(如 Figure 6 所示)。CPictureCtrl可以让你将一个图像作为一个子控件放在任何的对话框或窗口上。例如:

01. classCAboutDialog :publicCDialog {
02. protected:
03.   CPictureCtrl m_wndPict;
04.   virtualBOOLOnInitDialog();
05. };
06. BOOLCAboutDialog::OnInitDialog()
07. {
08.   m_wndPict.SubclassDlgItem(IDC_MYIMAGE,this);
09.   returnCDialog::OnInitDialog();
10. }

这里假设在你的对话框中有一个静态控件,它的ID是IDC_IMAGE,同时还有一个具有相同ID的IMAGE资源。我从我那很常用的CStaticLink中派生了CPictureCtrl,这样,如果你想的话就可以声明一个URL超链接了(或仅仅创建一个与控件和图像具有相同ID的字符串资源)。如果你声明了一个URL,在这图像上点击鼠标将启动你的浏览器并实现这个链接。令人惊奇的是,CPicture保存了一个CPicture对象,并通过重载WM_PAINT来调用CPicture::Render,而不是通过一般的静态控件。要想了解更多的细节,可从本文开始处的链接下载源文件,使用它吧,我祝福你!

使用 cppqa@microsoft.com 发送你的问题和评论给 Paul  

作者简介

Paul DiLascia 是一个自由作家,顾问和 Web/UI 方面资深的设计师。他是 Windows++: Writing Reusable Windows Code in C++ (Addison-Wesley, 1992)一书的作者。你可以在 http://www.dilascia.com 网站和 Paul 联系上。

本文出自 MSDN Magazine 的 October 2001 期刊,可通过当地 报摊获得,或者最好是 订阅

 

http://www.cxybl.com/html/bcyy/c/201110185995_2.html

VC PICTURE控件的使用,如何加载背景图片

 

http://www.cnblogs.com/awen2011/archive/2011/10/17/2215488.html

VC对话框中显示图片及滚动条的使用

<对话框控件显示图片>

在VC对话框程序中,图片的显示载体一般需要使用对话框控件。在此总结下在控件上绘图的几点东西:

1、在对话框资源中放置图片控件,并对其类型属性选为Frame。可在对话框的绘图消息响应函数OnPaint或其他函数中,用CWnd类的函数GetDlgItem:CWnd* GetDlgItem( int nID ) const;来获得图片控件的窗口对象,再用函数GetDC:CDC* GetDC( );由窗口对象得到DC,然后就可以用该DC在控件中画图。

2、在对话框资源中放置非Frame类静态控件,先按顺序依次调用CWnd类的Invalidate和UpdateWindow函数后,再开始用DC画图。

注:

I、为了使在运行时能够不断及时更新控件的显示(主要是自己加的显式代码),可以将自己绘制控件的所有代码都全部加入对话框类的消息响应函数OnPaint中。在需要时(例如在绘图参数修改后),自己调用CWnd的Invalidate和UpdateWindow函数,请求系统刷新对话框和控件的显示。因为控件也是窗口,控件类都是CWnd的派生类。所以在对话框和控件中,可以像在视图类中一样,调用各种CWnd的成员函数;

II、为了在鼠标指向控件时,避免控件自己绘制的图形消去,需要设置控件的“Owner Draw”属性为“True”;

III、如果希望非按钮控件(如图片控件和静态文本等),也可以响应鼠标消息(如单击、双击等),需要设置控件的“Notify”属性为“True”;

 

<使用对话框滚动条浏览控件上的图片>

当图片显示范围超过控件大小时,我们需要使用滚动图片以便浏览超出图片的其他部分。对话框滚动条控件包括水平滚动条和垂直滚动条,使用步骤:

1、像对话框添加两种控件资源,分别添加实例变量;

2、添加控件的响应消息函数CWnd::OnVScroll 和CWnd::OnHScroll,完成控件的滚动消息响应;

3、根据滚动位置更新图片的显示区域;

注:

---------------------------------------------------------------------------------------

CWnd::OnHScroll 

afx_msg void OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar );

Parameters

nSBCode

Specifies a scroll-bar code that indicates the user’s scrolling request. This parameter can be one of the following:

  • SB_LEFT   Scroll to far left.
  • SB_ENDSCROLL   End scroll.
  • SB_LINELEFT   Scroll left.
  • SB_LINERIGHT   Scroll right.
  • SB_PAGELEFT   Scroll one page left.
  • SB_PAGERIGHT   Scroll one page right.
  • SB_RIGHT   Scroll to far right.
  • SB_THUMBPOSITION   Scroll to absolute position. The current position is specified by the nPos parameter.
  • SB_THUMBTRACK   Drag scroll box to specified position. The current position is specified by the nPos parameter.

nPos

Specifies the scroll-box position if the scroll-bar code is SB_THUMBPOSITION or SB_THUMBTRACK; otherwise, not used. Depending on the initial scroll range, nPos may be negative and should be cast to an int if necessary.

pScrollBar

If the scroll message came from a scroll-bar control, contains a pointer to the control. If the user clicked a window’s scroll bar, this parameter is NULL. The pointer may be temporary and should not be stored for later use.

Remarks

The framework calls this member function when the user clicks a window’s horizontal scroll bar.

The SB_THUMBTRACK scroll-bar code typically is used by applications that give some feedback while the scroll box is being dragged.

If an application scrolls the contents controlled by the scroll bar, it must also reset the position of the scroll box with the SetScrollPos member function.

Note   This member function is called by the framework to allow your application to handle a Windows message. The parameters passed to your function reflect the parameters received by the framework when the message was received. If you call the base-class implementation of this function, that implementation will use the parameters originally passed with the message and not the parameters you supply to the function.

Example

void CMyView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
   // Get the minimum and maximum scroll-bar positions.
   int minpos;
   int maxpos;
   pScrollBar->GetScrollRange(&minpos, &maxpos);
   maxpos = pScrollBar->GetScrollLimit();

   // Get the current position of scroll box.
   int curpos = pScrollBar->GetScrollPos();

   // Determine the new position of scroll box.
   switch (nSBCode)
   {
   case SB_LEFT:      // Scroll to far left.
      curpos = minpos;
      break;

   case SB_RIGHT:      // Scroll to far right.
      curpos = maxpos;
      break;

   case SB_ENDSCROLL:   // End scroll.
      break;

   case SB_LINELEFT:      // Scroll left.
      if (curpos > minpos)
         curpos--;
      break;

   case SB_LINERIGHT:   // Scroll right.
      if (curpos < maxpos)
         curpos++;
      break;

   case SB_PAGELEFT:    // Scroll one page left.
   {
      // Get the page size.
      SCROLLINFO   info;
      pScrollBar->GetScrollInfo(&info, SIF_ALL);

      if (curpos > minpos)
      curpos = max(minpos, curpos - (int) info.nPage);
   }
      break;

   case SB_PAGERIGHT:      // Scroll one page right.
   {
      // Get the page size.
      SCROLLINFO   info;
      pScrollBar->GetScrollInfo(&info, SIF_ALL);

      if (curpos < maxpos)
         curpos = min(maxpos, curpos + (int) info.nPage);
   }
      break;

   case SB_THUMBPOSITION: // Scroll to absolute position. nPos is the position
      curpos = nPos;      // of the scroll box at the end of the drag operation.
      break;

   case SB_THUMBTRACK:   // Drag scroll box to specified position. nPos is the
      curpos = nPos;     // position that the scroll box has been dragged to.
      break;
   }

   // Set the new position of the thumb (scroll box).
   pScrollBar->SetScrollPos(curpos);

   CView::OnHScroll(nSBCode, nPos, pScrollBar);
}
-----------------------------------------------------------------------------

CWnd::OnVScroll 

afx_msg void OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar );

Parameters

nSBCode

Specifies a scroll-bar code that indicates the user’s scrolling request. This parameter can be one of the following:

  • SB_BOTTOM   Scroll to bottom.
  • SB_ENDSCROLL   End scroll.
  • SB_LINEDOWN   Scroll one line down.
  • SB_LINEUP   Scroll one line up.
  • SB_PAGEDOWN   Scroll one page down.
  • SB_PAGEUP   Scroll one page up.
  • SB_THUMBPOSITION   Scroll to the absolute position. The current position is provided in nPos.
  • SB_THUMBTRACK   Drag scroll box to specified position. The current position is provided in nPos.
  • SB_TOP   Scroll to top.

nPos

Contains the current scroll-box position if the scroll-bar code is SB_THUMBPOSITION or SB_THUMBTRACK; otherwise not used. Depending on the initial scroll range, nPos may be negative and should be cast to an int if necessary.

pScrollBar

If the scroll message came from a scroll-bar control, contains a pointer to the control. If the user clicked a window’s scroll bar, this parameter is NULL. The pointer may be temporary and should not be stored for later use.

Remarks

The framework calls this member function when the user clicks the window’s vertical scroll bar.

OnVScroll typically is used by applications that give some feedback while the scroll box is being dragged.

If OnVScroll scrolls the contents of the CWnd object, it must also reset the position of the scroll box with the SetScrollPos member function.

Note   This member function is called by the framework to allow your application to handle a Windows message. The parameters passed to your function reflect the parameters received by the framework when the message was received. If you call the base-class implementation of this function, that implementation will use the parameters originally passed with the message and not the parameters you supply to the function.

<程序示例>

滚动消息响应:根据图片的显示大小设置滚动条的滚动步长信息

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
void CImageboxUI::OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar )
{
     SCROLLINFO vSI;
     m_vScrollBar.GetScrollInfo(&vSI);
     switch (nSBCode)
     {
     case SB_TOP:
         vSI.nPos = 0;
         break ;
     case SB_BOTTOM:
         vSI.nPos = INT_MAX;
         break ;
     case SB_LINEUP:
         {
<font color= "#ff0000" >          vSI.nPos -= ( int )((m_imageShow.Height()*m_dRatioY)/70);
             vSI.nPos  = vSI.nPos<vSI.nMin? vSI.nMin:vSI.nPos;</font>
         }
         break ;
     case SB_LINEDOWN:
         {
<font color= "#ff0000" >          vSI.nPos += ( int )((m_imageShow.Height()*m_dRatioY)/70);
             vSI.nPos  = vSI.nPos>vSI.nMax? vSI.nMax:vSI.nPos;</font>
         }
         break ;
     case SB_PAGEUP:
 
         break ;
     case SB_PAGEDOWN:
 
         break ;
     case SB_THUMBPOSITION:
         break ;
     case SB_THUMBTRACK:
         vSI.nPos = nPos;
         break ;
     case SB_ENDSCROLL:
         break ;
     }
     m_vScrollBar.SetScrollInfo(&vSI);
     SendMessage(WM_PAINT);
 
     CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}
 
void CImageboxUI::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar )
{
     SCROLLINFO hSI;
     m_hScrollBar.GetScrollInfo(&hSI);
     switch (nSBCode)
     {
     case SB_LEFT:
         hSI.nPos = 0;
         break ;
     case SB_RIGHT:
         hSI.nPos = INT_MAX;
         break ;
     case SB_LINERIGHT:
         {
<font color= "#ff0000" >          hSI.nPos += ( int )((m_imageShow.Width()*m_dRatioX)/70);
             hSI.nPos  = hSI.nPos<hSI.nMin? hSI.nMin:hSI.nPos;</font>
         }
         break ;
     case SB_LINELEFT:
         {
<font color= "#ff0000" >          hSI.nPos -= ( int )((m_imageShow.Width()*m_dRatioX)/70);
             hSI.nPos  = hSI.nPos<hSI.nMin? hSI.nMin:hSI.nPos;</font>
         }
         break ;
     case SB_PAGEUP:
         break ;
     case SB_PAGEDOWN:
         break ;
     case SB_THUMBPOSITION:
         break ;
     case SB_THUMBTRACK:
         hSI.nPos = nPos;
         break ;
     case SB_ENDSCROLL:
         break ;
     }
     m_hScrollBar.SetScrollInfo(&hSI);
     SendMessage(WM_PAINT);
 
     CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
?
1
根据滚动信息进行图片绘制(双缓冲机制):
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
void CImageboxUI::OnPaint()
{
     CPaintDC dc( this ); // device context for painting
     // TODO: 在此处添加消息处理程序代码
     // 不为绘图消息调用 CDialog::OnPaint()
     //
     // 对话框Static控件双缓冲绘图
     CWnd* pImageWnd=GetDlgItem(IDC_STATIC_PIC);
     if (NULL==pImageWnd) return ;
     pImageWnd->ModifyStyle(0, BS_OWNERDRAW);  // 修改CStatic样式,改成自绘制(图形不被消去)
 
     // 绘图控件的DC
     CDC*  pDC=pImageWnd->GetDC();
     if (NULL==pDC) return ;
 
     // 绘图背景区域大小
     pImageWnd->GetWindowRect(&m_backShow);
     ScreenToClient(&m_backShow);
 
     // 图像绘制的实际大小
     CRect imageShow;
     imageShow.SetRect(0,0, ( int )(m_imageShow.Width()*m_dRatioX), ( int )(m_imageShow.Height()*m_dRatioY));
 
     // 滚动条信息
     SCROLLINFO vSI, hSI;
     m_vScrollBar.GetScrollInfo(&vSI);
     m_hScrollBar.GetScrollInfo(&hSI);
 
     /// 绘图
     CDC     memeroyDC;
     CBitmap memeroyBP;
     memeroyDC.CreateCompatibleDC(NULL);
     memeroyBP.CreateCompatibleBitmap(pDC,m_backShow.Width(),m_backShow.Height());
     CBitmap *pOldBit=memeroyDC.SelectObject(&memeroyBP);
 
     // 在内存上绘制绘图背景
     CBrush backBrush;
     backBrush.CreateSolidBrush(RGB(128,128,128));
     CBrush* pOldBrush=memeroyDC.SelectObject(&backBrush);
     memeroyDC.Rectangle(&m_backShow);
     memeroyDC.SelectObject(pOldBrush);
     backBrush.DeleteObject();
 
     // 在内存上绘制实际大小图像
     if (m_backShow.Width()<imageShow.Width())
     {
         ;
     }
     else
     {
         int y=0;
         int x=( int )((m_backShow.Width()-imageShow.Width())/2.0);
         if (m_backShow.Height()>imageShow.Height())
         {
             y=( int )((m_backShow.Height()-imageShow.Height())/2.0);
         }
         imageShow.OffsetRect(x,y);
     }  
 
     imageShow.OffsetRect(-hSI.nPos,-vSI.nPos);
     m_imageFile.StretchBlt(memeroyDC.m_hDC, imageShow, SRCCOPY);
 
     // 将内存图像绘制到控件
     pDC->BitBlt(0,0,m_backShow.Width(),m_backShow.Height(),&memeroyDC,0,0,SRCCOPY);
 
     // 释放对象和DC
     memeroyBP.DeleteObject();
     memeroyDC.SelectObject(pOldBit);
     memeroyDC.DeleteDC();
     ReleaseDC(pDC);
}
<程序效果>

12

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值