过年回家,走之前留一个用GDI+实现的略缩图控件

来源:互联网 发布:linux中tar命令详解 编辑:程序博客网 时间:2024/05/22 06:07
这是一个加载文件夹图片略缩图的控件,支持多种图片格式~~用法也比较简单
图片
(1)、源代码

//头文件ListImageCtrl.h 
#pragma once
#include <vector>

//note:need GDI+

// ListImageCtrl.h : header file

class CListImageCtrl : public CListCtrl
{
// Construction
public:
CListImageCtrl();

// Attributes
public:
void CreateColumn();
//
BOOL  GetImageFileNames();// gather the image file names
void  DrawThumbnails();// draw the thumbnails in list control
void  Load();         //start load files
void Clear();   //clear list

// Operations
public:
CStringm_strImageDir;
CImageListm_ImageListThumb;// image list holding the thumbnails
std::vector<CString> m_VectorImageNames;// vector holding the image names
intm_nSelectedItem;
BOOL  m_bHorz;

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CListImageCtrl)
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CListImageCtrl();

// Generated message map functions
protected:
//{{AFX_MSG(CListImageCtrl)
afx_msg void OnDropFiles(HDROP hDropInfo);
//}}AFX_MSG

DECLARE_MESSAGE_MAP()
};

// ListImageCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "Medical.h"
#include "ListImageCtrl.h"

#define THUMBNAIL_WIDTH  90
#define THUMBNAIL_HEIGHT 90

void DoEvents(void);

/////////////////////////////////////////////////////////////////////////////
// CListImageCtrl

CListImageCtrl::CListImageCtrl()
{
m_strImageDir = _T("");
m_bHorz = FALSE;
}

CListImageCtrl::~CListImageCtrl()
{
}


BEGIN_MESSAGE_MAP(CListImageCtrl, CListCtrl)
//{{AFX_MSG_MAP(CListImageCtrl)
ON_WM_DROPFILES()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CListImageCtrl message handlers

// This funtion is used to load the Window dropped files into the listview

void CListImageCtrl::OnDropFiles(HDROP hDropInfo) 
{
WORD wNumFilesDropped = DragQueryFile(hDropInfo, -1, NULL, 0);

CString firstFile(_T(""));
int kk=0;
int tTot=(int)wNumFilesDropped;

// show hour glass cursor
BeginWaitCursor();

for (WORD x = 0 ; x < wNumFilesDropped; x++) 
{
kk++;
// Get the number of bytes required by the file's full pathname
WORD wPathnameSize = DragQueryFile(hDropInfo, x, NULL, 0);
TRACE1("wPathnameSize=%d,\n",wPathnameSize);

// Allocate memory to contain full pathname & zero byte
wPathnameSize +=1;
TCHAR * npszFile = (TCHAR *) LocalAlloc(LPTR, sizeof(TCHAR)*wPathnameSize);  //注意分配的内存大小

// If not enough memory, skip this one
if (npszFile == NULL) continue;
DragQueryFile(hDropInfo, x, npszFile, wPathnameSize);

if (firstFile=="") 
firstFile=npszFile;

CString strExt;
CString nFileText;
CString pItemText=npszFile;

TRACE1("%s\n",pItemText);

int i=pItemText.ReverseFind('\\');
nFileText = pItemText.Mid(i+1); 
m_strImageDir = pItemText.Left(i+1);

strExt = pItemText.Right(3);
TRACE1("strExt=%s\n",strExt);

if ( (strExt.CompareNoCase( TEXT("bmp") ) == 0) ||
(strExt.CompareNoCase( TEXT("jpg") ) == 0) ||
(strExt.CompareNoCase( TEXT("gif") ) == 0) ||
(strExt.CompareNoCase( TEXT("tif") ) == 0) ||
(strExt.CompareNoCase( TEXT("png") ) == 0) )
{
// save the image file name, not the path
m_VectorImageNames.push_back(nFileText);  
}

// clean up
LocalFree(npszFile);
}

// Free the memory block containing the dropped-file information
DragFinish(hDropInfo);

if(!m_VectorImageNames.empty())
DrawThumbnails();

SetFocus();
SetItemState(0, LVIS_SELECTED |    LVS_ICON | LVS_AUTOARRANGE, LVIS_SELECTED | LVIS_FOCUSED | LVIS_ACTIVATING); 
EndWaitCursor();

CListCtrl::OnDropFiles(hDropInfo);
}


void CListImageCtrl::CreateColumn()
{
InsertColumn(0,_T("Filename"),LVCFMT_LEFT,125,-1);
InsertColumn(1,_T("Path"),LVCFMT_LEFT,125,-1);
InsertColumn(2,_T("Size"),LVCFMT_LEFT,75,-1);

HIMAGELIST hScreens = ImageList_Create(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, ILC_COLOR32 /*| ILC_MASK*/ , 0, 1);
m_ImageListThumb.Attach(hScreens);
m_nSelectedItem = 0;

// load the starting bitmap ("Loading..." and "Corrupt file")
//  CBitmap dummy;
//  dummy.LoadBitmap(IDB_BITMAP1);
//  m_ImageListThumb.Add(&dummy, RGB(0, 0, 0));

SetImageList(&m_ImageListThumb, LVSIL_NORMAL);
SetImageList(&m_ImageListThumb, LVSIL_SMALL);

}

// this function is used to enable the system messages
// this is mainly used to display the multiple images dropped on the list control

void DoEvents(void)
{
    MSG Symsg;
    
    while(PeekMessage(&Symsg,NULL,0,0,PM_REMOVE))
    {
    TranslateMessage(&Symsg);
    DispatchMessage(&Symsg);
    }
}

BOOL  CListImageCtrl::GetImageFileNames()
{
CStringstrExt;
CStringstrName;
CStringstrPattern;
BOOLbRC = TRUE;

HANDLEhFind = NULL;
WIN32_FIND_DATAFindFileData;
std::vector<CString>VectorImageNames;

if ( m_strImageDir[m_strImageDir.GetLength() - 1] == TCHAR('\\') )
strPattern.Format( TEXT("%s*.*"), m_strImageDir );
else
strPattern.Format( TEXT("%s\\*.*"), m_strImageDir );

hFind = ::FindFirstFile(strPattern, &FindFileData);// strat search
if (hFind == INVALID_HANDLE_VALUE)
{
LPVOID  msg;
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 
NULL, 
GetLastError(), 
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&msg, 
0, 
NULL);
MessageBox((LPTSTR)msg, CString((LPCSTR)IDS_TITLE), MB_OK|MB_ICONSTOP);
::LocalFree(msg);
return FALSE;
}

// filter off the system files and directories
if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)  &&
!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)     &&
!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)     &&
!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY))
{    
// test file extension
strName = FindFileData.cFileName;
strExt = strName.Right(3);

if ( (strExt.CompareNoCase( TEXT("bmp") ) == 0) ||
(strExt.CompareNoCase( TEXT("jpg") ) == 0) ||
(strExt.CompareNoCase( TEXT("gif") ) == 0) ||
(strExt.CompareNoCase( TEXT("tif") ) == 0) ||
(strExt.CompareNoCase( TEXT("png") ) == 0) )
{
// save the image file name
VectorImageNames.push_back(strName);
}
}  

// loop through to add all of them to our vector
while (bRC)
{
bRC = ::FindNextFile(hFind, &FindFileData);
if (bRC)
{
// filter off the system files and directories
if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)  &&
!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)     &&
!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)     &&
!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY))
{
// test file extension
strName = FindFileData.cFileName;
strExt = strName.Right(3);

if ( (strExt.CompareNoCase( TEXT("bmp") ) == 0) ||
(strExt.CompareNoCase( TEXT("jpg") ) == 0) ||
(strExt.CompareNoCase( TEXT("gif") ) == 0) ||
(strExt.CompareNoCase( TEXT("tif") ) == 0) ||
(strExt.CompareNoCase( TEXT("png") ) == 0) )
{
// save the image file name
VectorImageNames.push_back(strName);
}
}
}  
else
{
DWORD err = ::GetLastError();
if (err !=  ERROR_NO_MORE_FILES)
{
LPVOID msg;
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 
NULL, err, 
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&msg, 0, NULL);
MessageBox((LPTSTR)msg, CString((LPCSTR)IDS_TITLE), MB_OK|MB_ICONSTOP);
::LocalFree(msg);
::FindClose(hFind);
return FALSE;
}
}
} // end of while loop

// close the search handle
::FindClose(hFind);

// update the names, if any
if ( !VectorImageNames.empty() )
{
// reset the image name vector
m_VectorImageNames.clear();
m_VectorImageNames = VectorImageNames;
return TRUE;
}

return FALSE;
}

void  CListImageCtrl::DrawThumbnails()
{
CStringstrPath;
inti;

// no images
if (m_VectorImageNames.empty())
return;

// set the length of the space between thumbnails
// you can also calculate and set it based on the length of your list control
int nGap = 40;

// hold the window update to avoid flicking
SetRedraw(FALSE);

// reset our image list
for (i = 0; i < m_ImageListThumb.GetImageCount(); i++)
m_ImageListThumb.Remove(i);

// remove all items from list view
if (this->GetItemCount() != 0)
this->DeleteAllItems();

// set the size of the image list
m_ImageListThumb.SetImageCount(m_VectorImageNames.size());
i = 0;

// draw the thumbnails
std::vector<CString>::iterator  iter;
for (iter = m_VectorImageNames.begin(); iter != m_VectorImageNames.end(); iter++)
{
HBITMAP hbmReturn = NULL; 
Bitmap  *bmPhoto  = NULL;
CBitmap Bmp1;

// load the bitmap
strPath.Format( TEXT("%s\\%s"), m_strImageDir, *iter );

Bitmap img( strPath.AllocSysString() );

int sourceWidth  = img.GetWidth();
int sourceHeight = img.GetHeight();

int destX, destY, destWidth, destHeight;
const float fRatio=(float)THUMBNAIL_HEIGHT/THUMBNAIL_WIDTH;
const float fImgRatio=(float)sourceHeight/sourceWidth;

if(fImgRatio > fRatio)
{
destWidth=(THUMBNAIL_HEIGHT/fImgRatio);
destX=(THUMBNAIL_WIDTH-destWidth)/2;
destY=0;
destHeight=THUMBNAIL_HEIGHT;
}
else
{
destX=0;
destWidth=THUMBNAIL_WIDTH;
destHeight=(THUMBNAIL_WIDTH*fImgRatio);
destY=(THUMBNAIL_HEIGHT-destHeight)/2;
}

//check out very small image
if ((sourceHeight < THUMBNAIL_HEIGHT) && (sourceWidth < THUMBNAIL_WIDTH))
{
destWidth=sourceWidth;
destHeight=sourceHeight;
destX=(THUMBNAIL_WIDTH-destWidth)/2;
destY=(THUMBNAIL_HEIGHT-destHeight)/2;
}

bmPhoto = new Bitmap( THUMBNAIL_WIDTH, THUMBNAIL_WIDTH , PixelFormat32bppRGB );
bmPhoto->SetResolution( img.GetHorizontalResolution(), img.GetVerticalResolution() );

Graphics *grPhoto = Graphics::FromImage( bmPhoto );
Color colorW(255, 255, 255, 255);
Gdiplus::Pen pen(Color(200,192,192,192));
grPhoto->Clear( colorW );
grPhoto->SetInterpolationMode( InterpolationModeHighQualityBilinear );
grPhoto->DrawImage( &img, Rect(destX, destY, destWidth, destHeight) );
grPhoto->DrawRectangle(&pen,Gdiplus::Rect(0,0,THUMBNAIL_WIDTH-1,THUMBNAIL_HEIGHT-1));  //draw border

bmPhoto->GetHBITMAP( colorW, &hbmReturn );

Bmp1.Attach( hbmReturn );
m_ImageListThumb.Replace( i, &Bmp1, NULL );
//int imgP=m_ImageListThumb.Add(&Bmp1,RGB(0,0,0));

InsertItem(i, m_VectorImageNames[i],i);  //Link to the added listview item 

delete grPhoto;
delete bmPhoto;
Bmp1.Detach();
DeleteObject( hbmReturn );
i++;

}

// let's show the new thumbnails
SetRedraw(); 
}

void CListImageCtrl::Load() 
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);

// validate image directory
if (m_strImageDir.IsEmpty())
{
MessageBox(CString((LPCSTR)IDS_DIR_ERROR), CString((LPCSTR)IDS_TITLE), MB_OK|MB_ICONSTOP);
return;
}

// show hour glass cursor
BeginWaitCursor();

// get the names of bitmap files
 if ( !GetImageFileNames() )
 {
 EndWaitCursor();
 return;
 }

// draw thumbnail images in list control
DrawThumbnails();

// draw the selected image in its full size
//DrawSelectedImage();

// if this was a shortcut, we need to expand it to the target path
SetItemState(0, LVIS_SELECTED |    LVS_ICON | LVS_AUTOARRANGE, LVIS_SELECTED | LVIS_FOCUSED | LVIS_ACTIVATING); 
SetFocus();

RedrawWindow(NULL,NULL);

EndWaitCursor();

}

void CListImageCtrl::Clear()
{
// hold the window update to avoid flicking
SetRedraw(FALSE);

// reset our image list
for (int i = 0; i < m_ImageListThumb.GetImageCount(); i++)
m_ImageListThumb.Remove(i);

// remove all items from list view
if (this->GetItemCount() != 0)
this->DeleteAllItems();

m_strImageDir = _T("");

m_VectorImageNames.clear();

SetRedraw(); 

}

(2)、用法

1、在界面上放一个ListCtrl控件,设置View属性为ICON,Accept files属性TRUE,然后关联一个变量,如CListImageCtrl  m_lstImg;
2、在 BOOL CXXXDlg::OnInitDialog()初始化控件,一个语句就可以了m_lstImg.CreateColumn();
3、加载略缩图方法可以拖拽图片到控件,也可以这样加载
                        //strPath 是一个CString变量,文件夹路径

m_lstImg.m_strImageDir = strPath;
m_lstImg.Load();

 


 


原创粉丝点击