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.