There are several
image libraries
with
source codes and
sources
currently available. So I made my mind
up to make a free
Image Viewer using a
free image
library, and I got many free
demo programs. I think a good
image viewer
must be able to show
thumbnail
images in a selected
directory. I found some sources showing
thumbnails,
but they didn't support several formats,
only BMP files. This
thumbnail
viewer is based on
CxImage
,
so if there is an image format supported
by
CxImage
,
this viewer also supports that format.
Implementation
I want
to show you the core part in this
article.
How to make a
CListCtrl
,
and then how to load images and attach
that image to an
ImageList
.
1.
Creating CListCtrl
and CImageList
I used
a
CListView
instead of
CListCtrl
,
but you know that
CListView
uses
CListCtrl
internally. So overriding
Create(...)
will make your icon view
CListCtrl
initially. And then on
OnInitialUpdate()
,
make
ImageList
which can support 24 bit color images
and attach to
CListCtrl
.
return CListView::Create(lpszClassName, _T("ListView"),
dwStyle|LVS_SHOWSELALWAYS|LVS_ALIGNTOP|LVS_ICON|LVS_SINGLESEL|
LVS_AUTOARRANGE, rect, pParentWnd, nID, pContext);
....
m_ImageListThumb.Create(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, ILC_COLOR24, 0, 1);
ListCtrl.SetImageList(&m_ImageListThumb, LVSIL_NORMAL);
2.
Load Images and Insert Items
Create
a Compatible DC and a Bitmap Handle.
Stretch a
loaded image to the Bitmap
Handle and then attach it to
CBitmap
.
Finally, replace
CBitmap
with an image in the
ImageList
.
unsigned __stdcall CMyView::LoadThumbNail(LPVOID lpParam)
{
CMyView* pView=(CMyView*)lpParam;
CThumbViewerDoc* pDoc=pView->GetDocument();
CListCtrl& ListCtrl=pView->GetListCtrl();
CImageList* pImgList=&pView->m_ImageListThumb;
for(int i=0; i<pImgList->GetImageCount(); i++)
pImgList->Remove(i);
ListCtrl.DeleteAllItems();
pImgList->SetImageCount(pDoc->m_vFileName.size());
char path[MAX_PATH];
vector<CString>::iterator iter;
ListCtrl.SetRedraw(FALSE);
int nIndex=0;
for(iter=pDoc->m_vFileName.begin();
iter!=pDoc->m_vFileName.end() && pView->m_bTerminate!=true;
iter++, nIndex++)
{
ListCtrl.InsertItem(nIndex, *iter, nIndex);
}
ListCtrl.SetRedraw(TRUE);
ListCtrl.Invalidate();
HBRUSH hBrushBorder=::CreateSolidBrush(RGB(192, 192, 192));
HBRUSH hBrushBk=::CreateSolidBrush(RGB(255, 255, 255));
RECT rcBorder;
rcBorder.left=rcBorder.top=0;
rcBorder.right=THUMBNAIL_WIDTH;
rcBorder.bottom=THUMBNAIL_HEIGHT;
const float fRatio=(float)THUMBNAIL_HEIGHT/THUMBNAIL_WIDTH;
int XDest, YDest, nDestWidth, nDestHeight;
nIndex=0;
for(iter=pDoc->m_vFileName.begin();
iter!=pDoc->m_vFileName.end() && pView->m_bTerminate!=true;
iter++, nIndex++)
{
sprintf(path, "%s\\%s", pDoc->m_strCurrentDirectory, *iter);
int nImageType=pDoc->GetTypeFromFileName(path);
if(nImageType==CXIMAGE_FORMAT_UNKNOWN)
continue;
CxImage image(path, nImageType);
if(image.IsValid()==false)
continue;
const float fImgRatio=(float)image.GetHeight()/image.GetWidth();
if(fImgRatio > fRatio)
{
nDestWidth=THUMBNAIL_HEIGHT/fImgRatio;
XDest=(THUMBNAIL_WIDTH-nDestWidth)/2;
YDest=0;
nDestHeight=THUMBNAIL_HEIGHT;
}
else
{
XDest=0;
nDestWidth=THUMBNAIL_WIDTH;
nDestHeight=THUMBNAIL_WIDTH*fImgRatio;
YDest=(THUMBNAIL_HEIGHT-nDestHeight)/2;
}
CClientDC cdc(pView);
HDC hDC=::CreateCompatibleDC(cdc.m_hDC);
HBITMAP bm = CreateCompatibleBitmap(cdc.m_hDC, THUMBNAIL_WIDTH,
THUMBNAIL_HEIGHT);
HBITMAP pOldBitmapImage = (HBITMAP)SelectObject(hDC,bm);
::FillRect(hDC, &rcBorder, hBrushBk);
image.Stretch(hDC, XDest, YDest, nDestWidth, nDestHeight);
::FrameRect(hDC, &rcBorder, hBrushBorder);
SelectObject(hDC, pOldBitmapImage);
CBitmap bitmap;
bitmap.Attach(bm);
pImgList->Replace(nIndex, &bitmap, NULL);
ListCtrl.RedrawItems(nIndex, nIndex);
DeleteDC(hDC);
DeleteObject(bm);
}
DeleteObject(hBrushBorder);
DeleteObject(hBrushBk);
ListCtrl.Invalidate();
pView->m_bRunning=false;
pView->m_bTerminate=false;
_endthreadex( 0 );
return 0;
}
Other
You
can download
CxImage
freely from
here.