|

Introduction
There are several image libraries 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, CImageList, 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 CThumbViewerView::LoadThumbNail(LPVOID lpParam)
{
CThumbViewerView* pView=(CThumbViewerView*)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;
}
Acknowledgment
You can download CxImage freely from here.
History
- Ver. 1.0 15, Sep. 2003
- Ver. 1.1 24, Mar. 2005
- Fixed crashing when changing a directory fast.
- Supports Unicode option using preprocessor
_UNICODE.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 133 (Total in Forum: 133) (Refresh) | FirstPrevNext |
|
|
 |
|
|
hi, do you know how to upload pictures as thumbnails inside datagrid and if user click on any picture, the picture opens in bigger size? will appriciate any help
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
First of all very good work the one i was actually looking for but I need to load the images into a list control. I tried with the following code. I added 12 fully qualified file names into the vector m_vFileName but after loading i was only able to see the file names in the list control. Please help me.
//////////////////////// CODE //////////////////////
CListCtrl& ListCtrl=m_listImages;//The CListCtrl object in the dialog class m_ImageListThumb.Create(THUMBNAIL_WIDTH,THUMBNAIL_HEIGHT,ILC_COLOR,m_vFileName.size(),1); CImageList* pImgList=&m_ImageListThumb;
// reset our image list for(int i=0; i<pImgList->GetImageCount(); i++) pImgList->Remove(i);
// remove all items from list view ListCtrl.DeleteAllItems();
pImgList->SetImageCount(m_vFileName.size());
TCHAR path[MAX_PATH]; vector<CString>::iterator iter; // Set redraw to FALSE to avoid flickering during adding new items ListCtrl.SetRedraw(FALSE); int nIndex=0; for(iter=m_vFileName.begin(); iter!=m_vFileName.end(); iter++, nIndex++) { ListCtrl.InsertItem(nIndex, *iter, nIndex); }
ListCtrl.SetRedraw(TRUE); ListCtrl.Invalidate();
// Create Brushes for Border and BackGround HBRUSH hBrushBorder=::CreateSolidBrush(RGB(192, 192, 192)); HBRUSH hBrushBk=::CreateSolidBrush(RGB(255, 255, 255));
// Border Size 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=m_vFileName.begin(); iter!=m_vFileName.end(); iter++, nIndex++) { // Load Image File _stprintf(path, _T("%s"),*iter);
int nImageType=GetTypeFromFileName(path); if(nImageType==CXIMAGE_FORMAT_UNKNOWN) continue;
CxImage image(path, nImageType);
if(image.IsValid()==false) continue;
// Calculate Rect to fit to canvas 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; }
CDC *cdc=GetDC(); HDC hDC=::CreateCompatibleDC(cdc->m_hDC); HBITMAP bm = CreateCompatibleBitmap(cdc->m_hDC, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT); HBITMAP pOldBitmapImage = (HBITMAP)SelectObject(hDC,bm); // Draw Background ::FillRect(hDC, &rcBorder, hBrushBk);
// Draw Image image.Stretch(hDC, XDest, YDest, nDestWidth, nDestHeight);
// Draw Border ::FrameRect(hDC, &rcBorder, hBrushBorder);
SelectObject(hDC, pOldBitmapImage);
// Attach to Bitmap and Replace image in CImageList CBitmap bitmap; bitmap.Attach(bm); pImgList->Replace(nIndex, &bitmap, NULL);
// Redraw only a current item for removing flickering and fast speed. ListCtrl.RedrawItems(nIndex, nIndex);
// Release used DC and Object DeleteDC(hDC); DeleteObject(bm); } DeleteObject(hBrushBorder); DeleteObject(hBrushBk);
ListCtrl.Invalidate();
Thanks In advance
www.ktsinfotech.com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I'm using a parallel list box for selecting images in the thumbnail list viewer. However when I select one , its hard to see the images when they are highlighted. I wonder how it could be made so that it doesn't highlight the image, just the name?
Also, would it be possible to not include ".jpg" on end of items and still have them display?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
hi~
last 2~3 years ago had met a Korean in the face here is..(perfectly conglish..understand do ju sam(hae joo sam~^^)
wow~ realy how no long time see korean here.
leave traces because very very glad.
bye~^^
modified on Monday, March 17, 2008 9:28 PM
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
I don't know why,but if you change the code
// Draw Image image.Stretch(hDC, XDest, YDest, nDestWidth, nDestHeight);
to this:
// Draw Image RGBQUAD col = {255,255,255,255}; image.Thumbnail(nDestWidth,nDestHeight,col); image.Draw2(hDC, XDest, YDest, nDestWidth, nDestHeight);
and then chang the code:
pDoc->m_pSelectedImage->Draw(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem);
to:
// Draw Image RGBQUAD col = {255,255,255,255}; CxImage image; if(pDoc->m_pSelectedImage) { image = *pDoc->m_pSelectedImage; CRect rect = lpDrawItemStruct->rcItem; image.Thumbnail(rect.Width(),rect.Height(),col); image.Draw(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem); }
//pDoc->m_pSelectedImage->Draw(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem);
you will get the more smooth and better look pictures!
======================================== www.PhysDev.com (chinese)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hi ,
Im getting this error if i download your source and run it LINK : fatal error LNK1181: cannot open input file "./lib/cximagecrtu.lib" im not able to find cximagecrtu.lib file
i want the UNICODE compatibility
kinldy help me
regards Sandeep
Sandeep/-
|
| Sign In·View Thread·PermaLink | 1.90/5 (7 votes) |
|
|
|
 |
|
|
pls send me the solution as soon as possilbe . im in very hurry only your project will save me... my mail ids are skhokalay@yahoo.co.in khokalay_s@hotmail.com sandeep.khokalay@gmail.com
Sandeep/-
|
| Sign In·View Thread·PermaLink | 1.50/5 (3 votes) |
|
|
|
 |
|
|
Hi! The library is for unicode release only. So if you want to compile the code without Unicode support, here is what you must do: 1) Remove this library from the Link Tab (Project->Settings ...) 2) Go to Build->Set Active Configuration and choose Win32 - Debug The code will now compile cleanly. All best!
I am in love with VC++
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
|
I want to add a new bar to show some infos of the files.
I think it better to use a dialog so it will be easy to use some controls.
So i try to use CViewBar(see http://www.codeproject.com/docking/dockview.asp)to do it.
But i failed to send a message to the dialog.
My code:
//CFuncView.h
#ifndef WM_MSG1 #define WM_MSG1 (WM_USER+101) #endif
class CFuncView : public CFormView ...... //MainFrm.h
CViewBar m_wndFuncView; //MainFrm.cpp
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
......
CString sTitle; sTitle.Format(_T("FuncView")); if (!m_wndFuncView.Create(this, RUNTIME_CLASS (CFuncView), (CCreateContext *)(lpCreateStruct->lpCreateParams), sTitle, WS_CHILD | WS_VISIBLE | CBRS_TOP, AFX_IDW_CONTROLBAR_FIRST + 33 )) { TRACE0("Failed to create ViewBar\n"); return -1; // fail to create } m_wndFuncView.SetBarStyle(m_wndFuncView.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
m_wndFuncView.EnableDocking(CBRS_ALIGN_TOP);
EnableDocking(CBRS_ALIGN_ANY);
......
DockControlBar(&m_wndFuncView, AFX_IDW_DOCKBAR_TOP);
......
} I send the msg when the document changes. for example:
//CThumbViewerView::OnFileNew()
CMainFrame* pFrame=(CMainFrame*)AfxGetMainWnd(); pFrame->m_wndPreviewBar.SendMessage(WM_SIZE); pFrame->m_wndFuncView.SendMessage(WM_MSG1);
But the dialog don't recieve any msg, plz give me some advice.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Is a new window successfully attached to your MainFrame window? If it is, how is the WM_MSG1 defined? How about sending another Win32 message, such as WM_SIZE.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
moah wrote: Is a new window successfully attached to your MainFrame window?
yes
moah wrote: If it is, how is the WM_MSG1 defined?
it's defined in CFuncView.h .
moah wrote: How about sending another Win32 message, such as WM_SIZE.
The sub function can response to the WIn32 message.
Thank u for your help.
|
| Sign In·View Thread·PermaLink | 2.80/5 (2 votes) |
|
|
|
 |
|
|
i don't want to use any library like CXImage, want to get the preview of only the availabe .bmp images in my pc, then how can i do that? Does it need a huge change?plz help, i'm very new in MFC.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi tahinn.
It is your choice to select a Image Library. And I chose CxImage because it is one of the finest Image Library which can be freely obtained from the Internet.
Although you may decide not to use CxImage, you should choose an alternative image library for BMP File. Or maybe you can use CBitmap class(MFC include the class) and SetBitmapBits method of the CBitmap.
CxImage is just Image Library to help load a image file and draw to DC(Device Context).
Refer following two articles. Then you can build your own Bitmap(BMP) image library.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/resources/introductiontoresources/resourcereference/resourcefunctions/loadimage.asp http://www.codeguru.com/cpp/g-m/bitmap/viewers/article.php/c1775/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Congratulations! This is a really good project. But I can't build in my machine I am using Visual C++ 8 and receive the following erros:
c:\test\scbarg.cpp(57) : error C2440: 'static_cast' : cannot convert from 'UINT (__thiscall CSizingControlBarG::* )(CPoint)' to 'LRESULT (__thiscall CWnd::* )(CPoint)' Cast from base to derived requires dynamic_cast or static_cast sizecbar.cpp
// My comments Just in line: ON_WM_NCHITTEST()
c:\test\control_bar\sizecbar.cpp(109) : error C2440: 'static_cast' : cannot convert from 'UINT (__thiscall CSizingControlBar::* )(CPoint)' to 'LRESULT (__thiscall CWnd::* )(CPoint)' Cast from base to derived requires dynamic_cast or static_cast
// My comments Just in line: ON_WM_NCHITTEST()
Anderson Luís Oliveira e Silva nosredna@terra.com.br
|
| Sign In·View Thread·PermaLink | 1.50/5 (2 votes) |
|
|
|
 |
|
|
The errors are occured from the 3rd party library, CSizingControlBar. And unfortunately it was published a little long time ago. 
You can infer that the problems are because of mismatching return type of two functions. Therefore you can simply fix the problem. 
1. Open scbarg.h, and see line 103. Change afx_msg UINT OnNcHitTest(CPoint point); to afx_msg LRESULT OnNcHitTest(CPoint point);
2. Open scbarg.cpp and see line 145 Change UINT CSizingControlBarG::OnNcHitTest(CPoint point) to LRESULT CSizingControlBarG::OnNcHitTest(CPoint point)
3. Open sizecbar.h and see line 167 Change afx_msg UINT OnNcHitTest(CPoint point); to afx_msg LRESULT OnNcHitTest(CPoint point);
4. Open sizecbar.cpp and see line 573 Change UINT CSizingControlBar::OnNcHitTest(CPoint point) to LRESULT CSizingControlBar::OnNcHitTest(CPoint point)
Now, you'll see no more error.
|
| Sign In·View Thread·PermaLink | 2.00/5 (4 votes) |
|
|
|
 |
|
|
f:\cpa\jpg\thumbviewer_src_1_1\dirtreectrl.cpp(463) : error C2065: “SHGDN_INCLUDE_NONFILESYS”: 未声明的标识符 >f:\cpa\jpg\thumbviewer_src_1_1\control_bar\sizecbar.cpp(1297) : error C2065: “afxChNil”: 未声明的标识符 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hi tahinn. It's quite easy to restrict a kind of imagefile types.
In my example, see ThumbViewerDoc.cpp file which has a implementation of CThumbViewerDoc Class.
On line 198, you can also see a function named int CThumbViewerDoc::GetTypeFromFileName(LPCTSTR pstr). Modify the function like this.
int CThumbViewerDoc::GetTypeFromFileName(LPCTSTR pstr) { CString fileName(pstr); CString ext3=fileName.Right(3); CString ext4=fileName.Right(4); #if CXIMAGE_SUPPORT_BMP if(ext3.CompareNoCase(_T("bmp"))==0) return CXIMAGE_FORMAT_BMP; #endif return CXIMAGE_FORMAT_UNKNOWN; }
It's very easy, isn't it?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hello
Very good work! Have a question nevertheless.
Would like to have the pictures announced in a CFormView (CListCtrl) and a little support would need for it. An example project would be extremely super.
Thanks Kind greetings Karl
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hi, Karl.
First of all, I feel very happy that you like my stuff. However, I can't understand your question fully.
You mean, you need pictures that I used for a Screen Shot? Four of six of the pictures are basically included in Windows XP 
If you need the rest pictures, I'll certainly send them to you
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi moah,
i am a friend of Karl. Your stuff is really awesome and i also like it alot!!
What Karl ment is how to put the Thumbnailviewer into a CFormView that includes a CListCtrl where the thumbnails should be shown. So basically the question is how to put the Thumnailviewer into the CListControl he wants to create?
Do you have an idea how he could do that? Perhaps you have another example for that case.
Thanks alot in advance and keep up your great work!!
Best regards
Rene
-- modified at 12:27 Tuesday 4th July, 2006
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|