CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...

时间:2022-12-25 12:55:59

在GOPaint的设计研究过程中,我一直希望能够实现这样的结果(A B C 3个步骤)




CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...


在我之前的博客里面,曾经有过缩略图显示的现就,也应用到了实际的项目中。但是现在过了一段时间后回头再看,当时的实现放吧是粗糙的。基于MFC已经提供的基础库,通过c++自己的重载机制,应该能够得到精巧的实现,但是肯定需要去重写一些东西。


为了解决问题,达到效果,进行了一些研究。 


一、CMFCShellList和CMFCShellTree基本结合;


这两个控件是新出现的,使用起来比较简单。



CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...


 


CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...



CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...


DIalog的方便之处就在于“所见及所得”,这里绑定控件变量。


在initdialog中添加两句,就能得到效果


    m_ctrlShellList.ModifyStyle(LVS_TYPEMASK, LVS_ICON);
    m_ctrlShellTree.SetRelatedList( &m_ctrlShellList);



CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...


Tree的结果和List的结果是级联的。但是显示不了缩略图,只能够显示图标。


二、对CMFCShellList和CMFCShellTree的继承和研究;


如果要更好地使用这两个类,必须首先继承之后使用,在这个过程中,我才能够重写函数和事件:


在原始的mfcshelllistctrl控件中,如果双击其中的文件(图片)的话,是采用默认的打开程序打开文件(图片),那么我要把这个修改成使用我自己的程序来打开图片,所以首先就需要进行CMFCShellListCtrl的重载


#
pragma once
# include "afxshelllistctrl.h"
class CGOShellListCtrl :
public CMFCShellListCtrl
{
public
:

CGOShellListCtrl( void);
~CGOShellListCtrl( void);
DECLARE_MESSAGE_MAP()
afx_msg void OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult);
};

 


修改 OnNMDblclk事件


void CGOShellListCtrl     :     :OnNMDblclk(NMHDR      *pNMHDR, LRESULT      *pResult)     
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast
<LPNMITEMACTIVATE
>(pNMHDR);

CString Filename;
for( int i = 0; i <GetItemCount(); i ++)
{
if( GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED )
{
GetItemPath(Filename,i);
AfxMessageBox(Filename);
}
}
*pResult = 0;
}


得到能够显示双击文件绝对地址的目的:



CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...


那么下一步,需要将这个地址传入主程序,这个方法很多。


同样,也可以对CMFCShellTreeCtrl进行重载,得到当前的目录地址。


三、但是还是需要显示缩略图;


但是,核心问题还是没有解决,现在还是显示不了缩略图。


一开始我想通过重写List的CUSTOMDRAW事件来达到效果,但是研究一些资料之后,可以修改ListCtrl的样式,却无法修改主要内容。虽然CUSTOMDRAW中也提供了控价重构的机制,但是隐藏在许多宏中,不方便使用;


最后我开始反思之前我的ThumbNail是如何实现的,最后决定还是采用imagelist绑定的方法来解决问题。


这时,可以肯定基本是不用CMFCShellListCtrl了,而是要继承原始的CListCtrl,基本思路就是从CMFCTreeListCtrl中获得路径名称,而后在自定义的List控件中显示出来。并且还要截获List的点击事件,那么获得选择图片的绝对地址。


其实在这个过程中,过滤后缀名等操作也是可以完成的。


四、DLG下的实验


为了进行试验,我首先在DLG下面进行了实验。效果良好:



CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...


双击打开图片,感觉速度上面还是有些问题。


这个DLG的例子可以参考附录里面的 thumbnail 例子,基本就是根据其修改的。


五、融合到GOPaint中去:


GOPaint是我目前正在做的OpenCV图像处理框架库,力图能够提供大中型图像处理软件所需的基础环境。那么缩略图也是必须的一个环节。



CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...


采用的是浮动窗口,比较美观。毕竟要把主要区域用出来,显示图片。



CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...


在这里融合的时候,我就有意识地将代码进行合并。



CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...


对于ListCtrl和CMFCShellTreeCtrl分别进行了重载。这里还是选择了ListCtrl进行重载,因为CMFCShellListCtrl中的优秀特性这里用不起来。


SplitePane继承于CDockablePane,是一个悬浮框类。那么在这个悬浮框中我将


 CGOShellTreeCtrl m_wndTree;
 CGOListCtrl m_ListThumbnail;
 CPaneSplitter m_wndSplitter;
 CImageList m_ImageListThumb;


都放在其中,还包括一些存储用的变量。这样的结果就是如果以后在其他地方需要使用,只需要将这几个文件拷贝过去复用就可以了。


#
pragma once
# include "afxshelltreectrl.h"
# include "afxshelllistctrl.h"
# include "panesplitter.h"
# include "GOShellTreeCtrl.h"
# include "GOListCtrl.h"
# include "afxwin.h"
# include <vector >

// CSplitePane

class CSplitePane : public CDockablePane
{
DECLARE_DYNAMIC(CSplitePane)
public
:

CSplitePane();
virtual ~CSplitePane();
protected
:

DECLARE_MESSAGE_MAP()
public
:

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnDestroy();
public
:

CGOShellTreeCtrl m_wndTree;
CGOListCtrl m_ListThumbnail;
CPaneSplitter m_wndSplitter;
CPaneToolBar m_wndToolbar;
CImageList m_ImageListThumb;
int m_nSelectedItem;
void DrawThumbnails( void);
std : :vector <CString > m_VectorImageNames;
BOOL GetImageFileNames( void);
void GetThumbnailsAndShow( void);
};


 


具体的实现代码已经不重要了,因为原理已经讲明白了。这里的代码编写需要对继承、控件等都有一些了解。如果有不清楚的地方可以跟帖讨论。


五、小结:


这样一个效果,前后做了有2天,6-8个小时。我想还需要加强以下几个方面的联系:


1、对VS环境中提供的几个新控件的认识。不仅是能够了解使用,最好是能够找到实现的代码去跟一根。这样以后需要实现自己想要的效果的时候有所依据。


MFC本身是系统的、连贯的。它自己的代码很多时候就是最好的参考;


2、对继承、复用等面向对象基本原理要加强理解。


3、 解决问题的方法比结果更重要。这个缩略图的问题可以说我一直就在思考和想解决,最后还是下定决心,达到了预计目的,各中过程也比较漫长。现在反思过来看,还是要紧紧抓住需要解决问题的核心,不要过度耽搁于细节。解决问题的方法一定是有的,相关的资料及时少,也是肯定有帮助的;


4、不断积累。这里探索的过程和探索的结果,将来都会成为很好的基础。


六、参考资料


找到一了一些的例子:




CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...


能够直接显示缩略图,但是版本比较老了,很多地方需要修改。


2、 也是提供customeview修改的.


3、codeprojects Thumbnails viewer and image processing using GDI+ and MFC 这篇我跟了一下,效果很好,但是太复杂。


3、最后还是在自己的以前看过的代码里面找到了最合适的例子 thumbnail。原始链接可能是codeprojects上的,这里直接放出代码。



CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...


4、如果想学习DockPane,那么codeprojects Understanding CDockablePane  这篇是最好的



CMFCShellList和自定义ShellList结合使用,达到“直接浏览缩略图,双击打开图片”...


感谢阅读至此,希望有所帮助。