我准备做一个简单的图片浏览器。
创建MFC选择的是对话框,在Foram中放了一个ListCtrl,设置为ICON的style,并添加了NM_CUSTOMDRAW这个事件的响应函数。可我在ListCtrl中添加一个Item后,无法在NM_CUSTOMDRAW这个函数中的LPNMCUSTOMDRAW结构体中获得这个item的rect。
用GetItemRect得到也不对。不知道那位大侠做过类似这样的东东,指导小弟一下。谢谢。
解决马上给分。
创建MFC选择的是对话框,在Foram中放了一个ListCtrl,设置为ICON的style,并添加了NM_CUSTOMDRAW这个事件的响应函数。可我在ListCtrl中添加一个Item后,无法在NM_CUSTOMDRAW这个函数中的LPNMCUSTOMDRAW结构体中获得这个item的rect。
用GetItemRect得到也不对。不知道那位大侠做过类似这样的东东,指导小弟一下。谢谢。
解决马上给分。
解决方案 »
- win32环境 怎样在picture control中显示bitmap?
- 求助Querynterface的问题
- 关于对话框间数据传递!~~(菜鸟提问)有说的不对的,请不要笑话!~~
- 当系统的画面设定改为32位真彩时,CreateDIBitmap无法创建HBITMAP对象
- 进程,线程,时间片
- 如何在vc6中做soap 的客户端访问web service(c#的程序)
- 小菜:来者有分,在线等待
- www.csdn.com.cn已经开通~目前正在测试阶段~!!
- VC怎样调用AutoCAD
- 谁能给我讲讲CBitmap::GetBitmapBits这个函数是干什么用的??
- 结构体指针如何new或者malloc??
- 问一下,接口IWebBrowser2中哪个成员函数是获得HTML的反馈内容的或者HTML源代码的?
http://www.codeproject.com/KB/combobox/thumbnailview.aspx
The solution presented in this article uses a JPEG reader class to read JPEG images and display them into a CListCtrl. The idea is to create an image list that holds the icons created from the JPEG thumbails.The first problem arises with the fact that MFC class CImageList does not support higher color depths than 16 colors (4 bits per pixel). Another interesting issue is that image loading takes quite some time. This article addresses both these issues.
1. Creating an image list with higher color depth.The less-known SDK macro ImageList_Create meets this problem.// Create the image list with 100*100 icons and 32 bpp color depthHIMAGELIST hImageList=ImageList_Create(100, 100, ILC_COLOR32, 0, 10);
m_imageList.Attach(hImageList);// load the starting bitmap ("Loading..." and "Corrupt file")CBitmap dummy;
dummy.LoadBitmap(IDB_NAILS100);
m_imageList.Add(&dummy, RGB(0, 0, 0));// Use the image list in the list viewGetListCtrl().SetImageList(&m_imageList, LVSIL_NORMAL);
GetListCtrl().SetImageList(&m_imageList, LVSIL_SMALL);
Collapse// structure used to pass parameters to a image adder threadstruct threadParamImage
{
CString folder; // the folder to be scanned for thumbnails CThumbnailView* pView; // the view that accomodates them HANDLE readPipe; // the pipe used to pass thumbnail filenames to the // JPEG loader thread};// structure used to pass parameters to a JPEG image loader threadstruct threadParam
{
CThumbnailView* pView; // the view that shows thumbnails HANDLE readPipe; // the pipe used to pass thumbnail filenames to the // JPEG loader thread};HANDLE hThread = NULL; // handle to the JPEG image loader threadHANDLE readPipe = NULL; // read and write ends of the communication pipeHANDLE writePipe = NULL;
HANDLE skipImages = NULL; // handle to the semaphore that signals the pipe //does no longer hold consistent dataHANDLE imageFiller = NULL; // handle to the thumbnail adder threadHANDLE imageFillerSemaphore = NULL; // thread termination flag (when this semaphore // goes signaled, the thread must exit)HANDLE imageFillerCR = NULL; // thumbnail adder thread critical section semaphoreHANDLE imageFillerWait = NULL; // second thumbnail adder thread critical section semaphore
// Fill in list control with thumbails from a specified folderBOOL CThumbnailView::FillInImages(CString folder)
{
// create semaphores the first time only if (!imageFillerSemaphore)
{
imageFillerSemaphore=CreateSemaphore(NULL, 0,1, NULL);
imageFillerCR=CreateSemaphore(NULL, 1,1, NULL);
imageFillerWait=CreateSemaphore(NULL, 1,1, NULL);
} // critical region starts here WaitForSingleObject(imageFillerCR, 0); // create thread parameters threadParamImage* pParam=new threadParamImage;
pParam->folder=folder;
pParam->pView=this; // and the thread DWORD dummy;
imageFiller=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ImageFillerThread,
pParam, 0, &dummy); return TRUE;
}While the image filler thread is:
Collapse// thumbnail adder threadDWORD ImageFillerThread(DWORD param)
{
// get thread parameters threadParamImage* pParam=(threadParamImage*)param;
CString folder=pParam->folder;
CThumbnailView* pView=pParam->pView;
HANDLE readPipe=pParam->readPipe;
// cleanup delete pParam; // wait for previous copies to stop WaitForSingleObject(imageFillerWait, INFINITE); // clear previous images from list control pView->GetListCtrl().DeleteAllItems(); // start scanning designated folder for thumbnails WIN32_FIND_DATA fd;
HANDLE find;
BOOL ok=TRUE;
fd.dwFileAttributes=FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_COMPRESSED|
FILE_ATTRIBUTE_READONLY;
find=FindFirstFile(folder+"\\_thumbs\\*.*", &fd); // return if operation failed if (find==INVALID_HANDLE_VALUE)
{
ReleaseSemaphore(imageFillerWait, 1, NULL);
ExitThread(0);
return 0;
} // critical section ends here ReleaseSemaphore(imageFillerCR, 1, NULL); // start adding items to the list control do
{
if (WaitForSingleObject(imageFillerSemaphore, 0)==WAIT_OBJECT_0)
{
// thread is signaled to stop // signal skip to JPEG file loader int skip=-1;
DWORD dummy;
WriteFile(writePipe, &skip, sizeof(int), &dummy, NULL);
ReleaseSemaphore(skipImages, 1, NULL);
break;
} ok=FindNextFile(find, &fd);
if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)continue; if (ok)
{
int item=pView->GetListCtrl().InsertItem(pView->GetListCtrl().GetItemCount(),
fd.cFileName, 0);
pView->GetListCtrl().SetItemPosition(item, CPoint(105*item, 5));
pView->AddImage(CString(folder+"\\_thumbs\\")+fd.cFileName, item);
}
}
while (find&&ok); // done adding items
FindClose(find);
ReleaseSemaphore(imageFillerWait, 1, NULL); ExitThread(0);
return 0;
}The last but not the least is the JPEG image loader thread:
Collapse// JPEG image loader threadDWORD ImageLoaderThread(DWORD param)
{
// wait to get a filename, then build the image, add it to the image list // then update list control CThumbnailView* pView=(CThumbnailView*)param;
DWORD dummy;
char buffer[1024]; while(1)
{
int itemIndex;
int size; if (WaitForSingleObject(skipImages, 0)==WAIT_OBJECT_0)
{
// skip to er do
{
ReadFile(readPipe, &itemIndex, sizeof(int), &dummy,
NULL);
if(itemIndex==-1)break;
ReadFile(readPipe, &size, sizeof(int), &dummy, NULL);
ReadFile(readPipe, buffer, size, &dummy, NULL);
}
while (1);
} // get data from pipe ReadFile(readPipe, &itemIndex, sizeof(int), &dummy, NULL);
ReadFile(readPipe, &size, sizeof(int), &dummy, NULL);
ReadFile(readPipe, buffer, size, &dummy, NULL);
buffer[size]=0; // is the file name valid ? OFSTRUCT ofs;
if(OpenFile(buffer, &ofs, OF_EXIST)==HFILE_ERROR)continue; // load an image from disk (using PaintLib) CWinBmp bitmap;
CAnyPicDecoder decoder;
try
{
decoder.MakeBmpFromFile(buffer, &bitmap, 0);
}
catch (CTextException exc)
{
pView->GetListCtrl().SetItem(itemIndex, 0, LVIF_IMAGE, NULL,
1, 0, 0, 0);
continue;
} // create a CBitmap object from the data within the CWinBmp object BITMAPINFOHEADER& bmiHeader=*bitmap.GetBMI();
BITMAPINFO& bmInfo=*(BITMAPINFO*)bitmap.GetBMI();
LPVOID lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors +
bmInfo.bmiHeader.biClrUsed) +
((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
CClientDC dc(NULL);
HBITMAP hBmp=CreateDIBitmap(dc.m_hDC, &bmiHeader, CBM_INIT, lpDIBBits,
&bmInfo, DIB_RGB_COLORS); CBitmap bmp;
bmp.Attach(hBmp);
// add the thumbnail to the image list int imgPos=pView->m_imageList.Add(&bmp, RGB(0, 0, 0));
pView->GetListCtrl().SetItem(itemIndex, 0, LVIF_IMAGE, NULL, imgPos,
0, 0, 0);
} ExitThread(1);
return 0;
}The code uses SDK semaphores, pipes and threads because they are easier to handle and much straightforward than MFC threads and synchronization mechanisms.The code is quite easy to follow and change to meet your needs, but if you need assistance, contact me. Also please send me bugs or updates, to keep this solution up-to-date. For more details on the sample application, contact me.
我在MSDN中没有找到这个通知,还有,我不打算使用ImageList来添加图片。我就想得到新添加那个Item的ICON的大小,就是那个Rect。
在VS2005中,没有这个style。只有一个Owner Draw fixed。
选定后添加WM_DRAWITEM,可收不到这个消息啊
因为我需要在上边画我自己的图片。我在SDK下尝试也收不到这个消息。
可我不知道怎么得到当前新添加ITEM的ID?