分类:
2012-08-17 09:47:16
原文地址:zz Clistctrl实现了缩略图效果... 作者:Ryanliang
codewarrior(会思考的草)回复于 2006-05-15 16:44:43 得分 13
OnPaint的那部分代码贴出来看看。
Using images
//初始化对话框
BOOL CImageTabDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//指定listctrl样式
//m_ListCtrlView.ModifyStyle(LVS_REPORT|LVS_SMALLICON|LVS_LIST|LVS_ICON,WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_SINGLESEL|LVS_EDITlabel1S ,SWP_NOSIZE);
//m_ListCtrlView.ModifyStyle(WS_HSCROLL|LVS_EDITlabel1S,WS_VSCROLL);
UINT style=::GetWindowLong(m_ListCtrlView.m_hWnd,GWL_STYLE);
style=style|WS_VSCROLL|LVS_ICON|LVS_SINGLESEL;
style=style&~WS_HSCROLL;
::SetWindowLong(m_ListCtrlView.m_hWnd,GWL_STYLE,style);
//CRect rect;
//m_ListCtrlView.GetWindowRect(&rect);
//m_ListCtrlView.Create(WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_SINGLESEL|WS_VSCROLL,rect,this,IDC_LISTVIEW);
//初始化标签页
for(int i=0;i
TabCtrlItem.mask = TCIF_TEXT;
TabCtrlItem.pszText =label1[i].GetBuffer();
m_TabCtrlView.InsertItem(i, &TabCtrlItem);
}
//隐藏增加删除按钮
((CButton*)GetDlgItem(IDC_ADD))->ShowWindow(false);
((CButton*)GetDlgItem(IDC_DEL))->ShowWindow(false);
ShowATab();
DrawThumbnails();
// TODO: Add ext1ra initialization here
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
//这个函数绘制缩略图
void CImageTabDlg::DrawThumbnails(void)
{
//==================================================
//定义缩略图的画布的大小
const THUMBNAIL_WIDTH=100;
const THUMBNAIL_HEIGHT=100;
// Create Brushes for Border and BackGround
HBRUSH hBrushBorder=::CreateSolidBrush(RGB(0, 0, 0));
HBRUSH hBrushBk=::CreateSolidBrush(RGB(255, 255, 255));
if(m_ImageList && m_ImageList.GetImageCount()){
// reset our image list
for(int i=0; i
}
if(m_ListCtrlView){
m_ListCtrlView.DeleteAllItems();
}
//创建imagelist
HIMAGELIST hImageList=ImageList_Create(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, ILC_COLOR32, 0,(int)m_FileNames.GetCount());
m_ImageList.Attach(hImageList);
// Use the image list in the list view
m_ListCtrlView.SetImageList(&m_ImageList, LVSIL_NORMAL);
m_ListCtrlView.SetImageList(&m_ImageList, LVSIL_SMALL);
// 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;
//m_ListCtrlView.SetRedraw(FALSE);
for(int i=0;i
CBitmap dummy;
dummy.LoadBitmap(IDB_BITMAPDEFAULT);
m_ImageList.Add(&dummy, RGB(0, 0, 0));
m_ListCtrlView.InsertItem(i,m_FileNames[i],i);
CString imagePath(m_strCurrentPath+m_FileNames[i]);
CxImage image(imagePath.GetBuffer(), getImageTypeFromName(m_FileNames[i])); //CxImage image(path, nimagetype1);
// Calculate Rect to fit to canvas
const float fImgRatio=(float)image.GetHeight()/image.GetWidth();
if(image.GetWidth()>THUMBNAIL_WIDTH || image.GetHeight()>THUMBNAIL_HEIGHT){
if(fImgRatio > fRatio)
{
nDestWidth=(int)(THUMBNAIL_HEIGHT/fImgRatio);
XDest=(THUMBNAIL_WIDTH-nDestWidth)/2;
YDest=0;
nDestHeight=THUMBNAIL_HEIGHT;
}
else
{
XDest=0;
nDestWidth=THUMBNAIL_WIDTH;
nDestHeight=(int)(THUMBNAIL_WIDTH*fImgRatio);
YDest=(THUMBNAIL_HEIGHT-nDestHeight)/2;
}
}else{
XDest=(THUMBNAIL_WIDTH-image.GetWidth())/2;
nDestWidth=image.GetWidth();
nDestHeight=image.GetHeight();
YDest=(THUMBNAIL_HEIGHT-image.GetHeight())/2;
}
CClientDC cdc(this);
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);
m_ImageList.Replace(i, &bitmap, NULL);
// Redraw only a current item for removing flickering and fast speed.
m_ListCtrlView.RedrawItems(i, i);
// Release used DC and Object
DeleteDC(hDC);
DeleteObject(bm);
DeleteObject(dummy);
}
//m_ListCtrlView.SetRedraw(TRUE);
DeleteObject(hBrushBorder);
DeleteObject(hBrushBk);
m_ImageList.Detach();
m_ListCtrlView.Invalidate();
}
onpaint中没有代码
收藏...
onpaint中没有代码?
会不会是onpaint没有执行相关操作啊?
移植到一个更大的工程中就出现了这个问题,
我快抓狂了
OnPaint中没有代码?我!@#$%^&*(),无语了……
没有代码你画什么?OnInitDialog只执行一次,以后重绘的时候还是调用MFC提供的OnPaint,谁来替你画缩略图?
WM_PAINT必须要自己写!可以另开一个线程来画,在OnPaint里通知这个线程重绘。
只是执行的速度慢一些,可是没有什么问题呀,
,我只是不明白,为什么缩略图会消失,
获得焦点之后默认应该是灰色亚?
to codewarrior(会思考的草)
我市菜鸟
第一,从CListCtrl派生出一个类,把DrawThumbnail所做的动作移植到你的派生类的OnPaint中。
然后,在CImageTabDlg中创建一个你这个派生类的对象(别创建成CListCtrl了!)。个么就ok了。
进一步改进:
对于获得焦点后的OnPaint,你参考一下ACDSee吧,它是在缩略图外面画了一个粗的框。具体什么效果你可以自定义。
这是我的缩略图列表类的OnPaint函数,完全模仿ACDSee 6.0,你姑且作个参考吧:
void CThumbnailListCtrl::OnPaint()
{
Dump();
if(IsThumbnailView())
{
BOOL bFocused = (GetFocus()==this);
CFont fontLabel;
CRect rectIcon(0,0,0,0);
CRect rectLabel(0,0,0,0);
CPaintDC dc(this); // device context for painting
//创建标签字体
// fontLabel.CreateFont(13,0,0,0,9, FALSE, FALSE, 0, GB2312_CHARSET, OUT_DEFAULT_PRECIS,
// CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_SWISS, "Tahoma");
LOGFONT LogFont = {0};
::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &LogFont, 0);
fontLabel.CreateFontIndirect(&LogFont);
for(int i=0; i
GetItemRect(i, &rectIcon, LVIR_ICON);
rectIcon.DeflateRect(WIDTH_STEP,WIDTH_STEP,HEIGHT_STEP,HEIGHT_STEP); //向内缩
//涂底色
dc.FillSolidRect(rectIcon, COLOR_THUMBNAIL_BACKGROUND);
//画焦点
if(GetItemState(i, LVIS_SELECTED)== LVIS_SELECTED)
{
if(bFocused)
{
rectIcon.InflateRect(3,3,3,3);
dc.Draw3dRect(&rectIcon, COLOR_THUMBNAIL_DBLUEFRAME, COLOR_THUMBNAIL_DBLUEFRAME);
rectIcon.InflateRect(1,1,1,1);
dc.Draw3dRect(&rectIcon, COLOR_THUMBNAIL_DBLUEFRAME, COLOR_THUMBNAIL_DBLUEFRAME);
rectIcon.InflateRect(1,1,1,1);
dc.Draw3dRect(&rectIcon, COLOR_THUMBNAIL_DBLUEFRAME, COLOR_THUMBNAIL_DBLUEFRAME);
rectIcon.DeflateRect(5,5,5,5);
dc.Draw3dRect(rectIcon, COLOR_THUMBNAIL_FRAME, COLOR_THUMBNAIL_FRAME);
}
else
{
dc.Draw3dRect(&rectIcon, COLOR_THUMBNAIL_CBLUEFRAME, COLOR_THUMBNAIL_CBLUEFRAME);
rectIcon.InflateRect(1,1,1,1);
dc.Draw3dRect(&rectIcon, COLOR_THUMBNAIL_CBLUEFRAME, COLOR_THUMBNAIL_CBLUEFRAME);
rectIcon.DeflateRect(2,2,2,2);
}
}
//画缩略图
LVITEM lvItem = {0};
lvItem.iItem = i;
lvItem.mask = LVIF_IMAGE|LVIF_PARAM|LVIF_STATE;
GetItem(&lvItem);
PLVITEM_EXINFO pItemInfo = (PLVITEM_EXINFO)lvItem.lParam;
CPoint ptTopleft(0,0);
IMAGEINFO ImgInfo = {0};
if(pItemInfo->hThumbnail == NULL)//尚未读取缩略图,我们用大图标代替
{
m_imglstLargeIcon.GetImageInfo(lvItem.iImage, &ImgInfo);
DWORD dwWidth = ImgInfo.rcImage.right-ImgInfo.rcImage.left;
DWORD dwHeight = ImgInfo.rcImage.bottom-ImgInfo.rcImage.top;
ptTopleft.x = rectIcon.left + ((rectIcon.Width()-dwWidth)/2);
ptTopleft.y = rectIcon.top + ((rectIcon.Height()-dwHeight)/2);
if(GetItemState(i, LVIS_CUT) == LVIS_CUT)
{
ImageList_DrawEx(
m_imglstLargeIcon.GetSafeHandle(), lvItem.iImage, dc.m_hDC,
ptTopleft.x, ptTopleft.y, dwWidth, dwHeight,
COLOR_THUMBNAIL_BACKGROUND, //背景色
COLOR_THUMBNAIL_BACKGROUND, //前景色
ILD_BLEND //和前景色混合50%
);
}
else
{
m_imglstLargeIcon.Draw(&dc, lvItem.iImage, ptTopleft, ILD_TRANSPARENT);
}
}
else
{
CRect TmpRect(0, 0, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);
TmpRect.DeflateRect(WIDTH_STEP,WIDTH_STEP,HEIGHT_STEP,HEIGHT_STEP);
ptTopleft.x = rectIcon.left + ((rectIcon.Width()-TmpRect.Width())/2);
ptTopleft.y = rectIcon.top + ((rectIcon.Height()-TmpRect.Height())/2);
HDC hMemDC = CreateCompatibleDC(dc.m_hDC);
::SelectObject(hMemDC, pItemInfo->hThumbnail);
StretchBlt(dc.m_hDC, ptTopleft.x, ptTopleft.y, TmpRect.Width(), TmpRect.Height(),
hMemDC, 0, 0, TmpRect.Width(), TmpRect.Height(), SRCCOPY);
::DeleteDC(hMemDC);
}
//右上角画小图标
ZeroMemory(&ImgInfo, sizeof(IMAGEINFO));
m_imglstSmallIcon.GetImageInfo(lvItem.iImage, &ImgInfo);
ptTopleft.x = rectIcon.right - (ImgInfo.rcImage.right-ImgInfo.rcImage.left) - 11;
ptTopleft.y = rectIcon.top + 3;
m_imglstSmallIcon.Draw(&dc, lvItem.iImage, ptTopleft, ILD_TRANSPARENT);
//画边框
dc.Draw3dRect(rectIcon, COLOR_THUMBNAIL_FRAME, COLOR_THUMBNAIL_FRAME);
GetItemRect(i, &rectLabel, LVIR_LABEL);
rectLabel.left = rectIcon.left;
rectLabel.right = rectIcon.right;
rectLabel -= CSize(0, 3);
CFont* pOldFont = dc.SelectObject(&fontLabel);
UINT nOldMode = dc.SetBkMode(TRANSPARENT);
dc.DrawText(GetItemText(i,0), rectLabel, DT_CENTER|DT_VCENTER|DT_WORDBREAK|DT_END_ELLIPSIS);
dc.SelectObject(pOldFont);
dc.SetBkMode(nOldMode);
}
fontLabel.DeleteObject();
if(m_bDragStart && m_nLandPos!=-1)
{
CPen RedPen(PS_SOLID, 1, RGB(255, 0, 0));
CPen* pOldPen = dc.SelectObject(&RedPen);
CRect SpcRect(0,0,0,0);
//计算分割条所在的矩形
CalcInsMarkRect(m_nLandPos, SpcRect);
CPoint pt1(SpcRect.TopLeft()); //取左上角
CPoint pt2(SpcRect.BottomRight());//取右下角
pt2.x = pt1.x = (pt1.x+pt2.x)/2; //计算上边中点和下边中点
pt1.y += 3;
pt2.y -= 5;
if(m_nLandPos < GetItemCount()) //靠右画
{
//中垂线
dc.MoveTo(pt1.x+2, pt1.y);
dc.LineTo(pt2.x+2, pt2.y);
dc.MoveTo(pt1.x+3, pt1.y);
dc.LineTo(pt2.x+3, pt2.y);
//上横边
dc.MoveTo(pt1.x, pt1.y);
dc.LineTo(pt1.x+6, pt1.y);
dc.MoveTo(pt1.x, pt1.y+1);
dc.LineTo(pt1.x+6, pt1.y+1);
//下横边
dc.MoveTo(pt2.x, pt2.y);
dc.LineTo(pt2.x+6, pt2.y);
dc.MoveTo(pt2.x, pt2.y-1);
dc.LineTo(pt2.x+6, pt2.y-1);
}
else //靠左画
{
//中垂线
dc.MoveTo(pt1.x-1, pt1.y);
dc.LineTo(pt2.x-1, pt2.y);
dc.MoveTo(pt1.x-2, pt1.y);
dc.LineTo(pt2.x-2, pt2.y);
//上横边
dc.MoveTo(pt1.x-4, pt1.y);
dc.LineTo(pt1.x+2, pt1.y);
dc.MoveTo(pt1.x-4, pt1.y+1);
dc.LineTo(pt1.x+2, pt1.y+1);
//下横边
dc.MoveTo(pt2.x-4, pt2.y);
dc.LineTo(pt2.x+2, pt2.y);
dc.MoveTo(pt2.x-4, pt2.y-1);
dc.LineTo(pt2.x+2, pt2.y-1);
}
dc.SelectObject(pOldPen);
}
}
else
{
SetIconSpacing(-1, -1);
CListCtrl::OnPaint();
}
}
我以前遇到过这个问题,记不清了,好像是CImageList的参数设置问题,很容易就搞定了。
不过你的实现代码也太麻烦了点。
这个问题我也遇到了,至今还没有解决。原来的工程在vc6下好用,但在vs2005下 采用Unicode编码就不好用,更奇怪的是采用多字节编码就好用,快要郁闷死了。我采用的代码和你的差不多,是从codeproject上找到的。
现在初步认定 是 HIMAGELIST hImageList=ImageList_Create(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT
这个函数出了问题,但不知道如何解决。
ps:不指导楼主发现了没有,采用不同的字符集(unicode,多字节),绘制出来的图标位置是不一样的,具体原因不明。
这个现象我们早就发现了。之前我参与的项目要做多国化,在繁体,简体,英语,俄语,韩语,西班牙语等十几个版本的windows上做过测试,有些语种的windows本身的图标之间的间隔就很大,不是程序的原因。我记得原因是这些国家的人种的瞳距不一样,所以图标的间隙要大一点。
哈哈 我好像找到问题了 搂主代码中这一句
HIMAGELIST hImageList=ImageList_Create(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, ILC_COLOR32, 0,(int)m_FileNames.GetCount());
第三个参数改为ILC_COLOR24 就应该可以正常显示了。
ccaccbccc(好吃的雪糕)
真强,果然是这个问题
感谢大家的鼓励和支持,我会在再散100分给大家.
本贴留给大家继续发言
过两天总结并揭帖
揭帖,
请大家到
继续接分