#include "AlbumArtListView.h" #include "api__ml_pmp.h" #include "resource1.h" #include "../tataki/export.h" #include #include #include "./local_menu.h" extern winampMediaLibraryPlugin plugin; #define WM_EX_GETREALLIST (WM_USER + 0x01) #define HORZ_SPACING 4 #define VERT_SPACING 4 AlbumArtListView::AlbumArtListView(ListContents * lc, int dlgitem, HWND libraryParent, HWND parent, bool enableHeaderMenu) : SkinnedListView(lc,dlgitem,libraryParent,parent,enableHeaderMenu), hbmpNames(NULL), classicnotfoundW(0), classicnotfoundH(0), ratingrow(-1), itemHeight(0), textHeight(0), ratingTop(0), notfound(L"winamp.cover.notfound"), notfound60(L"winamp.cover.notfound.60"), notfound90(L"winamp.cover.notfound.90") { this->hwndDlg = parent; this->dlgitem = dlgitem; mode = lc->config->ReadInt(L"albumartviewmode",0); lc->SetMode(mode); ZeroMemory(classicnotfound, sizeof(classicnotfound)); } AlbumArtListView::~AlbumArtListView() { if (hbmpNames) DeleteObject(hbmpNames); } int AlbumArtListView::GetFindItemColumn() { if(mode > 1) return 1; return contents->GetSortColumn(); } static COLORREF GetWAColor(INT index) { static int (*wad_getColor)(int idx) = NULL; if (!wad_getColor) *(void **)&wad_getColor=(void*)SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,1,ML_IPC_SKIN_WADLG_GETFUNC); return (wad_getColor) ? wad_getColor(index) : 0xFF00FF; } static void getImgSize(int mode, int &w, int &h) { switch(mode) { case 0: w=h=60; break; case 1: w=h=90; break; case 2: w=h=120; break; case 3: w=h=60; break; case 4: w=h=90; break; case 5: w=h=120; break; } } static bool isDetailsMode(int mode) { return mode == 0 || mode == 1 || mode == 2; } void DrawRect(HDC dc, int x, int y, int w, int h) { w-=1; h-=1; MoveToEx(dc,x,y,NULL); LineTo(dc,x,y+h); MoveToEx(dc,x,y+h,NULL); LineTo(dc,x+w,y+h); MoveToEx(dc,x+w,y+h,NULL); LineTo(dc,x+w,y); MoveToEx(dc,x+w,y,NULL); LineTo(dc,x,y); } static int getStrExtent(HDC dc, const wchar_t * s) { int ret=0; while(s && *s) { int f=0; GetCharWidth32(dc,*s,*s,&f); s++; ret+=f; } return int(ret); } ARGB32 * loadImg(const void * data, int len, int *w, int *h, bool ldata=false) { FOURCC imgload = svc_imageLoader::getServiceType(); int n = plugin.service->service_getNumServices(imgload); for(int i=0; iservice_enumService(imgload,i); if(sf) { svc_imageLoader * l = (svc_imageLoader*)sf->getInterface(); if(l) { if(l->testData(data,len)) { ARGB32* ret; if(ldata) ret = l->loadImageData(data,len,w,h); else ret = l->loadImage(data,len,w,h); sf->releaseInterface(l); return ret; } sf->releaseInterface(l); } } } return NULL; } ARGB32 * loadRrc(int id, char * sec, int *w, int *h, bool data=false) { DWORD size = 0; // as a nice little treat, allow lang packs to contain a custom IDR_IMAGE_NOTFOUND file HGLOBAL resourceHandle = WASABI_API_LOADRESFROMFILEA((LPCSTR)sec, (LPCSTR)MAKEINTRESOURCEA(id), &size); if(resourceHandle) { ARGB32* ret = loadImg(resourceHandle,size,w,h,data); UnlockResource(resourceHandle); return ret; } return NULL; } void adjustbmp(ARGB32 * p, int len, COLORREF fg) { ARGB32 * end = p+len; while (p < end) { int a = (*p>>24)&0xff ; int b = a*((*p&0xff) * (fg&0xff)) / (0xff*0xff); int g = a*(((*p>>8)&0xff) * ((fg>>8)&0xff)) / (0xff*0xff); int r = a*(((*p>>16)&0xff) * ((fg>>16)&0xff)) / (0xff*0xff); *p = (a<<24) | (r&0xff) | ((g&0xff)<<8) | ((b&0xff)<<16); p++; } } void AlbumArtListView::drawArt(pmpart_t art, DCCanvas *pCanvas, RECT *prcDst, int itemid, int imageIndex) { int x = prcDst->left; int y = prcDst->top; int w = prcDst->right - prcDst->left; int h = prcDst->bottom - prcDst->top; HDC dc = pCanvas->getHDC(); if(art) contents->dev->setArtNaturalSize(art,w,h); // draw image 4,4,w,h if(art && contents->dev->drawArt(art,pCanvas->getHDC(),x,y,w,h)) { // drawn by plugin! } else { SkinBitmap *noart; int h = prcDst->right - prcDst->left; if (h == 60) noart = notfound60.getBitmap(); else if (h == 90) noart = notfound90.getBitmap(); else noart = notfound.getBitmap(); if (!noart || noart->isInvalid()) { if(classicnotfound[imageIndex]) SkinBitmap(classicnotfound[imageIndex],classicnotfoundW,classicnotfoundH).stretchToRectAlpha(pCanvas, prcDst); else { DrawRect(dc,x,y,w,h); wchar_t str1[32] = {0}, str2[32] = {0}; WASABI_API_LNGSTRINGW_BUF(IDS_NO_IMAGE,str1,32); WASABI_API_LNGSTRINGW_BUF(IDS_AVAILABLE,str2,32); ExtTextOutW(dc, w/2 - 22 + x, w/2 - 14 + y, 0,NULL,str1,wcslen(str1),0); ExtTextOutW(dc, w/2 - 22 + x, w/2 + 1 + y, 0,NULL,str2,wcslen(str2),0); } } else noart->stretch(pCanvas,x,y,w,h); } } // icon view BOOL AlbumArtListView::DrawItemIcon(NMLVCUSTOMDRAW *plvcd, DCCanvas *pCanvas, UINT itemState, RECT *prcClip, BOOL bWndActive) { HDC hdc = plvcd->nmcd.hdc; RECT ri, re, rcText; int w=0,h=0, imageIndex; getImgSize(mode,w,h); SetBkColor(hdc, plvcd->clrTextBk); SetTextColor(hdc, plvcd->clrText); SetRect(&rcText, plvcd->nmcd.rc.left, plvcd->nmcd.rc.bottom - (textHeight + 2), plvcd->nmcd.rc.right, plvcd->nmcd.rc.bottom); imageIndex = 0; if ((LVIS_SELECTED | LVIS_FOCUSED) & itemState) { SetRect(&re, plvcd->nmcd.rc.left, plvcd->nmcd.rc.top, plvcd->nmcd.rc.right, rcText.top - 4); if (IntersectRect(&ri, &re, prcClip)) ExtTextOutW(hdc,0, 0, ETO_OPAQUE, &ri, L"", 0, 0); if (LVIS_SELECTED & itemState) imageIndex = (bWndActive) ? 1 : 2; } SetRect(&re, plvcd->nmcd.rc.left + 2, plvcd->nmcd.rc.top + 2, plvcd->nmcd.rc.left + 2 + w, plvcd->nmcd.rc.top + 2 + h); if (IntersectRect(&ri, &re, prcClip)) { pmpart_t art = contents->GetArt(plvcd->nmcd.dwItemSpec); drawArt(art, pCanvas, &re, plvcd->nmcd.dwItemSpec, imageIndex); } if (IntersectRect(&ri, &rcText, prcClip)) { if ((LVIS_SELECTED | LVIS_FOCUSED) & itemState) ExtTextOutW(hdc,0, 0, ETO_OPAQUE, &ri, L"", 0, 0); wchar_t buf[104] = {0}; contents->GetCellText(plvcd->nmcd.dwItemSpec,1,buf,100); const wchar_t *p = buf; if (p && *p) { SetRect(&ri, rcText.left + 2, rcText.top + 1, rcText.right - 2, rcText.bottom -1); DrawTextW(hdc, p, -1, &ri, DT_CENTER | DT_SINGLELINE | DT_WORD_ELLIPSIS | DT_NOPREFIX); } if ((LVIS_FOCUSED & itemState) && bWndActive) { HWND hwndRealList; hwndRealList = (HWND)SendMessageW(plvcd->nmcd.hdr.hwndFrom, WM_EX_GETREALLIST, 0, 0L); if (hwndRealList && 0 == (0x01/*UISF_HIDEFOCUS*/ & SendMessageW(hwndRealList, 0x0129/*WM_QUERYUISTATE*/, 0, 0L))) { SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); SetBkColor(hdc, GetSysColor(COLOR_WINDOW)); DrawFocusRect(hdc, &rcText); } } } return TRUE; } //detail view BOOL AlbumArtListView::PrepareDetails(HDC hdc) { INT width(0), height, len; HFONT hFont,hFontBold, hOldFont; HDC hdcTmp; HBITMAP hbmpOld; LOGFONT l={0}; RECT ri = {0}; wchar_t ratingstr[100] = {0}, buf[100] = {0}; hdcTmp = CreateCompatibleDC(hdc); if (!hdcTmp) return FALSE; hFont = (HFONT)GetCurrentObject(hdc, OBJ_FONT); GetObject(hFont, sizeof(LOGFONT), &l); l.lfWeight = FW_BOLD; hFontBold = CreateFontIndirect(&l); hOldFont = (HFONT)SelectObject(hdcTmp, hFontBold); for (int i=0; i < contents->GetNumColumns(); i++) { int of = getStrExtent(hdcTmp, contents->GetColumnTitle(i)); if (of > width) width = of; } if(width) width += 20; height = contents->GetNumColumns() * textHeight; hbmpNames = CreateCompatibleBitmap(hdc, width * 3, height); hbmpOld = (HBITMAP)SelectObject(hdcTmp, hbmpNames); SetRect(&ri, 0, 0, width, height); WASABI_API_LNGSTRINGW_BUF(IDS_RATING,ratingstr,100); INT clrText[3] = { WADLG_ITEMFG, WADLG_SELBAR_FGCOLOR, WADLG_INACT_SELBAR_FGCOLOR, }; INT clrBk[3] = { WADLG_ITEMBG, WADLG_SELBAR_BGCOLOR, WADLG_INACT_SELBAR_BGCOLOR, }; for (int j = 0; j < 3; j++) { SetTextColor(hdcTmp, GetWAColor(clrText[j])); SetBkColor(hdcTmp, GetWAColor(clrBk[j])); ExtTextOutW(hdcTmp,0, 0, ETO_OPAQUE, &ri, L"", 0, 0); for (int i=0, top = 0; i < contents->GetNumColumns(); i++, top += textHeight) { if (-1 == ratingrow && 0 == lstrcmpW(contents->GetColumnTitle(i), ratingstr)) ratingrow = i; StringCchCopyW(buf, 100, contents->GetColumnTitle(i)); len = wcslen(buf); if (len > 0 && len < 99) { buf[len] = L':'; len ++; } ExtTextOutW(hdcTmp, ri.left + 1, top, ETO_CLIPPED, &ri, buf, len, NULL); } OffsetRect(&ri, width, 0); } SelectObject(hdcTmp, hbmpOld); SelectObject(hdcTmp, hOldFont); DeleteObject(hFontBold); DeleteDC(hdcTmp); return TRUE; } BOOL AlbumArtListView::DrawItemDetail(NMLVCUSTOMDRAW *plvcd, DCCanvas *pCanvas, UINT itemState, RECT *prcClip, BOOL bWndActive, HDC hdcNames, INT namesWidth) { RECT ri, re; HDC hdc; INT imageIndex; hdc = plvcd->nmcd.hdc; SetTextColor(hdc, plvcd->clrText); SetBkColor(hdc, plvcd->clrTextBk); if (LVIS_SELECTED & itemState) { // background SetRect(&re, plvcd->nmcd.rc.left + 4, plvcd->nmcd.rc.top, plvcd->nmcd.rc.right, plvcd->nmcd.rc.bottom - 5); if (IntersectRect(&ri, &re, prcClip)) ExtTextOutW(hdc,0, 0, ETO_OPAQUE, &ri, L"", 0, 0); imageIndex = (bWndActive) ? 1 : 2; } else imageIndex = 0; int w, h; getImgSize(mode, w, h); SetRect(&re, 6+plvcd->nmcd.rc.left, 3+plvcd->nmcd.rc.top, 6+ plvcd->nmcd.rc.left + w, 3+ plvcd->nmcd.rc.top + h); if (IntersectRect(&ri, &re, prcClip)) { pmpart_t art = contents->GetArt(plvcd->nmcd.dwItemSpec); drawArt(art, pCanvas, &re, plvcd->nmcd.dwItemSpec, imageIndex); } // text int limCY, limCX; wchar_t buf[100] = {0}; limCY = plvcd->nmcd.rc.bottom; if (prcClip->bottom < plvcd->nmcd.rc.bottom) limCY = prcClip->bottom; limCX = plvcd->nmcd.rc.right -1; if (prcClip->right < plvcd->nmcd.rc.right) limCX = prcClip->right; SetRect(&ri, w+16+plvcd->nmcd.rc.left, 3+plvcd->nmcd.rc.top, limCX, limCY); if (hdcNames && ri.left < ri.right) { BitBlt(hdc, ri.left, ri.top, min(ri.right - ri.left, namesWidth), ri.bottom - ri.top, hdcNames, namesWidth*imageIndex, 0, SRCCOPY); ri.left += namesWidth; } ri.bottom = ri.top; if (ri.left < ri.right) { for (int i=0; i < contents->GetNumColumns() && ri.top < limCY; i++, ri.top += textHeight) { contents->GetCellText(plvcd->nmcd.dwItemSpec,i,buf,100); const wchar_t *p = buf; ri.bottom += textHeight; if (ri.bottom > limCY) ri.bottom = limCY; if ((INT)i == ratingrow) // this is the ratings column, so draw graphical stars { int rating = wcslen(buf); RATINGDRAWPARAMS p = {sizeof(RATINGDRAWPARAMS),hdc, {ri.left, ri.top + ratingTop, ri.right,ri.bottom}, rating,5,0,RDS_SHOWEMPTY,NULL,0}; MLRating_Draw(plugin.hwndLibraryParent,&p); } else ExtTextOutW(hdc, ri.left, ri.top, ETO_CLIPPED ,&ri,p,wcslen(p),NULL); } } // bottom line MoveToEx(hdc,plvcd->nmcd.rc.left + 4,plvcd->nmcd.rc.bottom - 3,NULL); LineTo(hdc,plvcd->nmcd.rc.right, plvcd->nmcd.rc.bottom - 3); // focus rect SetRect(&ri, plvcd->nmcd.rc.left + 4, plvcd->nmcd.rc.top, plvcd->nmcd.rc.right, plvcd->nmcd.rc.bottom - 5); if ((LVIS_FOCUSED & itemState) && bWndActive) { HWND hwndRealList; hwndRealList = (HWND)SendMessageW(plvcd->nmcd.hdr.hwndFrom, WM_EX_GETREALLIST, 0, 0L); if (hwndRealList && 0 == (0x01/*UISF_HIDEFOCUS*/ & SendMessageW(hwndRealList, 0x0129/*WM_QUERYUISTATE*/, 0, 0L))) { SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); SetBkColor(hdc, GetSysColor(COLOR_WINDOW)); DrawFocusRect(hdc, &ri); } } return TRUE; } static HWND CreateSmoothScrollList(HWND parent, int x, int y, int cx, int cy, int dlgid) { DWORD flags = WS_CHILD | WS_VSCROLL | DS_CONTROL | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; HWND h = CreateWindowExW(WS_EX_CONTROLPARENT, L"SmoothScrollList", L"",flags, x, y, cx, cy, parent,(HMENU)dlgid, NULL, (LPVOID)0); SendMessage(h,WM_INITDIALOG,0,0); return h; } static HWND CreateHeaderIconList(HWND parent, int x, int y, int cx, int cy, int dlgid) { DWORD flags = WS_CHILD | WS_VSCROLL | DS_CONTROL | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; HWND h = CreateWindowExW(WS_EX_CONTROLPARENT, L"HeaderIconList", L"",flags, x, y, cx, cy, parent,(HMENU)dlgid, NULL, (LPVOID)0); SendMessage(h,WM_INITDIALOG,0,0); return h; } BOOL AlbumArtListView::OnKeyDown(NMLVKEYDOWN *plvkd) { switch (plvkd->wVKey) { case 'A': if (GetAsyncKeyState(VK_CONTROL) && !GetAsyncKeyState(VK_SHIFT)) { LVITEM item; item.state = LVIS_SELECTED; item.stateMask = LVIS_SELECTED; SendMessageW(plvkd->hdr.hwndFrom, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&item); return TRUE; } break; } return FALSE; } BOOL AlbumArtListView::OnCustomDrawIcon(NMLVCUSTOMDRAW *plvcd, LRESULT *pResult) { static RECT rcClip; static BOOL bActive; static DCCanvas activeCanvas; *pResult = CDRF_DODEFAULT; switch(plvcd->nmcd.dwDrawStage) { case CDDS_PREPAINT: if (0 == plvcd->nmcd.rc.bottom && 0 == plvcd->nmcd.rc.right) { *pResult = CDRF_SKIPDEFAULT; return TRUE; } CopyRect(&rcClip, &plvcd->nmcd.rc); bActive = (GetFocus() == (HWND)SendMessageW(plvcd->nmcd.hdr.hwndFrom, WM_EX_GETREALLIST, 0, 0L)); activeCanvas.cloneDC(plvcd->nmcd.hdc, NULL); *pResult = CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT; return TRUE; case CDDS_ITEMPREPAINT: { UINT itemState; itemState = SendMessageW(plvcd->nmcd.hdr.hwndFrom, LVM_GETITEMSTATE, plvcd->nmcd.dwItemSpec, LVIS_FOCUSED | LVIS_SELECTED | LVIS_DROPHILITED | LVIS_CUT); plvcd->nmcd.rc.left = LVIR_BOUNDS; SendMessageW(plvcd->nmcd.hdr.hwndFrom, LVM_GETITEMRECT, plvcd->nmcd.dwItemSpec, (LPARAM)&plvcd->nmcd.rc); plvcd->nmcd.rc.right -= HORZ_SPACING; if (rcClip.left < plvcd->nmcd.rc.right) { DrawItemIcon(plvcd, &activeCanvas, itemState, &rcClip, bActive); *pResult = CDRF_SKIPDEFAULT; } } return TRUE; case CDDS_POSTPAINT: return TRUE; } return FALSE; } BOOL AlbumArtListView::OnCustomDrawDetails(NMLVCUSTOMDRAW *plvcd, LRESULT *pResult) { static RECT rcClip; static BOOL bActive; static HDC hdcNames; static INT namesWidth; static HBITMAP hbmpOld; static HPEN penOld; static DCCanvas activeCanvas; *pResult = CDRF_DODEFAULT; switch(plvcd->nmcd.dwDrawStage) { case CDDS_PREPAINT: if (0 == plvcd->nmcd.rc.bottom && 0 == plvcd->nmcd.rc.right) { *pResult = CDRF_SKIPDEFAULT; return TRUE; } CopyRect(&rcClip, &plvcd->nmcd.rc); if (!hbmpNames) PrepareDetails(plvcd->nmcd.hdc); if (hbmpNames) { BITMAP bi; GetObject(hbmpNames, sizeof(BITMAP), &bi); namesWidth = bi.bmWidth/3; hdcNames = CreateCompatibleDC(plvcd->nmcd.hdc); hbmpOld = (hdcNames) ? (HBITMAP)SelectObject(hdcNames, hbmpNames) : NULL; } else { hdcNames = NULL; namesWidth = 0; } bActive = (GetFocus() == (HWND)SendMessageW(plvcd->nmcd.hdr.hwndFrom, WM_EX_GETREALLIST, 0, 0L)); penOld = (HPEN)SelectObject(plvcd->nmcd.hdc, CreatePen(PS_SOLID,1, GetWAColor(WADLG_HILITE))); activeCanvas.cloneDC(plvcd->nmcd.hdc, NULL); *pResult = CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT; return TRUE; case CDDS_ITEMPREPAINT: { UINT itemState; itemState = SendMessageW(plvcd->nmcd.hdr.hwndFrom, LVM_GETITEMSTATE, plvcd->nmcd.dwItemSpec, LVIS_FOCUSED | LVIS_SELECTED | LVIS_DROPHILITED | LVIS_CUT); plvcd->nmcd.rc.left = LVIR_BOUNDS; SendMessageW(plvcd->nmcd.hdr.hwndFrom, LVM_GETITEMRECT, plvcd->nmcd.dwItemSpec, (LPARAM)&plvcd->nmcd.rc); if (rcClip.left < plvcd->nmcd.rc.right) { DrawItemDetail(plvcd, &activeCanvas, itemState, &rcClip, bActive, hdcNames, namesWidth); *pResult = CDRF_SKIPDEFAULT; } } return TRUE; case CDDS_POSTPAINT: if (hdcNames) { SelectObject(hdcNames, hbmpOld); DeleteDC(hdcNames); } if (penOld) { HPEN pen; pen = (HPEN)SelectObject(plvcd->nmcd.hdc, penOld); if (pen) DeleteObject(pen); penOld = NULL; } return TRUE; } return FALSE; } BOOL AlbumArtListView::CalcuateItemHeight(void) { int w, h; HWND hwndList = GetDlgItem(hwndDlg, dlgitem); TEXTMETRIC tm = {0}; getImgSize(mode, w, h); textHeight = 0; HDC hdc = GetDC(hwndDlg); if (hdc) { HFONT hFont = (HFONT)SendMessageW(hwndList, WM_GETFONT, 0, 0L); if (!hFont) hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); HFONT hFontOld = (HFONT)SelectObject(hdc, hFont); GetTextMetrics(hdc, &tm); textHeight = tm.tmHeight; SelectObject(hdc, hFontOld); ReleaseDC(hwndDlg, hdc); } if (isDetailsMode(mode)) { if (textHeight < 14) textHeight = 14; RECT r; MLRating_CalcRect(plugin.hwndLibraryParent, NULL, 5, &r); r.bottom -= r.top; if ( r.bottom >= textHeight ) ratingTop = 0; else { if (tm.tmAscent > (r.bottom + (r.bottom/2))) ratingTop = tm.tmAscent - r.bottom; else ratingTop = (textHeight - r.bottom)/2 + 1; } int newHeight = max(h, textHeight * (INT)contents->GetNumColumns()) + 12; if (newHeight != itemHeight) { itemHeight = newHeight; RECT rw; GetWindowRect(hwndList, &rw); SetWindowPos(hwndList, NULL, 0, 0, rw.right - rw.left - 1, rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW); SetWindowPos(hwndList, NULL, 0, 0, rw.right - rw.left, rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER); } } else { HIMAGELIST hIL = (HIMAGELIST)SendMessageW(hwndList, LVM_GETIMAGELIST, 0, 0L); if (!hIL || !ImageList_GetIconSize(hIL, &w, &h)) { h += 4; w+= 4; } SendMessageW(hwndList, LVM_SETICONSPACING, 0, MAKELPARAM(w + HORZ_SPACING, h + textHeight + 6 + VERT_SPACING)); if (!tm.tmAveCharWidth) tm.tmAveCharWidth = 2; itemHeight = w / tm.tmAveCharWidth; } return TRUE; } BOOL AlbumArtListView::DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) { switch(uMsg) { case WM_INITDIALOG: { HWND hwnd = GetDlgItem(hwndDlg,dlgitem); RECT r; if (hwnd) { GetWindowRect(hwnd,&r); MapWindowPoints(HWND_DESKTOP, hwndDlg, (POINT*)&r, 2); } else SetRect(&r, 0, 0, 1, 1); if (isDetailsMode(mode)) { if (hwnd) DestroyWindow(hwnd); hwnd = CreateSmoothScrollList(hwndDlg, r.left, r.top, r.right - r.left, r.bottom - r.top, dlgitem); SendMessage(hwnd,WM_USER+6,0,0); ShowWindow(hwnd, SW_SHOWNORMAL); } else { if (hwnd) DestroyWindow(hwnd); hwnd = CreateHeaderIconList(hwndDlg, r.left, r.top, r.right - r.left, r.bottom - r.top, dlgitem); ShowWindow(hwnd,SW_SHOWNORMAL); int w=0,h=0; getImgSize(mode,w,h); HIMAGELIST il = ImageList_Create(w + 4,h + 4,ILC_COLOR24,0,1); // add borders ListView_SetImageList(hwnd,il,LVSIL_NORMAL); } } break; case WM_DISPLAYCHANGE: { if (hbmpNames) DeleteObject(hbmpNames); hbmpNames = NULL; ratingrow = -1; CalcuateItemHeight(); int rw,rh; ARGB32 * bmp = loadRrc(IDR_IMAGE_NOTFOUND,"PNG",&rw,&rh,true); classicnotfoundW = rw; classicnotfoundH = rh; INT color[] = { WADLG_ITEMFG, WADLG_SELBAR_FGCOLOR, WADLG_INACT_SELBAR_FGCOLOR, }; for (int i = sizeof(classicnotfound)/sizeof(classicnotfound[0]) -1; i > -1; i--) { if(classicnotfound[i]) WASABI_API_MEMMGR->sysFree(classicnotfound[i]); classicnotfound[i] = NULL; if(bmp) { if (0 != i) { classicnotfound[i] = (ARGB32*)WASABI_API_MEMMGR->sysMalloc(sizeof(ARGB32)*rw*rh); CopyMemory(classicnotfound[i], bmp, sizeof(ARGB32)*rw*rh); } else classicnotfound[i] = bmp; adjustbmp(classicnotfound[i],rw*rh, GetWAColor(color[i])); } } if(uMsg == WM_DISPLAYCHANGE) PostMessageW(GetDlgItem(hwndDlg,dlgitem),uMsg,wParam,lParam); } break; case WM_DESTROY: for (int i = sizeof(classicnotfound)/sizeof(classicnotfound[0]) -1; i > -1; i--) { if(classicnotfound[i]) WASABI_API_MEMMGR->sysFree(classicnotfound[i]); classicnotfound[i] = NULL; } break; case WM_MEASUREITEM: if (wParam == (WPARAM)dlgitem) { ((MEASUREITEMSTRUCT*)lParam)->itemHeight = itemHeight; return TRUE; } break; case WM_NOTIFY: if (wParam == (WPARAM)dlgitem) { BOOL bProcessed(FALSE); LRESULT result(0); switch (((NMHDR*)lParam)->code) { case LVN_KEYDOWN: bProcessed = OnKeyDown((NMLVKEYDOWN*)lParam); break; case NM_CUSTOMDRAW: bProcessed = (isDetailsMode(mode)) ? OnCustomDrawDetails((NMLVCUSTOMDRAW*)lParam, &result) : OnCustomDrawIcon((NMLVCUSTOMDRAW*)lParam, &result); break; case LVN_GETDISPINFOW: return TRUE; case LVN_GETINFOTIPW: { wchar_t buf[256]=L""; contents->GetCellText(((NMLVGETINFOTIPW*)lParam)->iItem,1,buf,256); const wchar_t *p = buf; if (p && *p && lstrlenW(p) > itemHeight) // we use itemHeight to write number of average characters that fits label in icon mode { StringCchCopyW(((NMLVGETINFOTIPW*)lParam)->pszText, ((NMLVGETINFOTIPW*)lParam)->cchTextMax, p); } } return TRUE; } if (bProcessed) SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)result); return bProcessed; } { LPNMHDR l=(LPNMHDR)lParam; if(l->code == NM_RCLICK && l->hwndFrom == ListView_GetHeader(listview.getwnd())) { extern HMENU m_context_menus; HMENU menu = GetSubMenu(m_context_menus, 10); POINT p; GetCursorPos(&p); int checked=0; switch(mode) { case 0: checked=ID_ARTHEADERMENU_SMALLDETAILS; break; case 1: checked=ID_ARTHEADERMENU_MEDIUMDETAILS; break; case 2: checked=ID_ARTHEADERMENU_LARGEDETAILS; break; case 3: checked=ID_ARTHEADERMENU_SMALLICON; break; case 4: checked=ID_ARTHEADERMENU_MEDIUMICON; break; case 5: checked=ID_ARTHEADERMENU_LARGEICON; break; } CheckMenuItem(menu,checked,MF_CHECKED | MF_BYCOMMAND); int r = Menu_TrackSkinnedPopup(menu, TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTBUTTON, p.x, p.y, l->hwndFrom, NULL); CheckMenuItem(menu,checked,MF_UNCHECKED | MF_BYCOMMAND); if(!r) return TRUE; ProcessMenuResult(r,false,0,NULL,hwndDlg); return TRUE; } else if(l->code == LVN_GETINFOTIP && l->idFrom == dlgitem) { NMLVGETINFOTIP *n = (NMLVGETINFOTIP*)l; wchar_t artist[100] = {0}, album[100] = {0}, tracks[10] = {0}, year[10] = {0}; contents->GetCellText(n->iItem,0,artist,100); contents->GetCellText(n->iItem,1,album,100); contents->GetCellText(n->iItem,2,tracks,10); contents->GetCellText(n->iItem,3,year,10); wchar_t trackstr[100] = {0}; WASABI_API_LNGSTRINGW_BUF(IDS_TRACKS,trackstr,100); CharLower(trackstr); if(year[0]) StringCchPrintf(n->pszText,n->cchTextMax,L"%s - %s (%s): %s %s",artist,album,year,tracks,trackstr); else StringCchPrintf(n->pszText,n->cchTextMax,L"%s - %s: %s %s",artist,album,tracks,trackstr); } } break; case LVM_REDRAWITEMS: { RECT ri; HWND hwndList = GetDlgItem(hwndDlg, dlgitem); if (hwndList) { HWND hwndRealList = (HWND)SendMessageW(hwndList, WM_EX_GETREALLIST, 0, 0L); if (hwndRealList) { int w, h; getImgSize(mode, w, h); if (isDetailsMode(mode)) { for(int i = (INT)wParam; i <= (INT)lParam; i++) { ri.left = LVIR_BOUNDS; if (SendMessageW(hwndRealList, LVM_GETITEMRECT, i, (LPARAM)&ri)) { ri.left += 6; ri.top += 3; ri.right = ri.left + w; ri.bottom = ri.top + h; InvalidateRect(hwndRealList, &ri, FALSE); } } } else { for(int i = (INT)wParam; i <= (INT)lParam; i++) { ri.left = LVIR_ICON; if (SendMessageW(hwndRealList, LVM_GETITEMRECT, i, (LPARAM)&ri)) { ri.left += 2; ri.top += 2; ri.right = ri.left + w; ri.bottom = ri.top + h; InvalidateRect(hwndRealList, &ri, FALSE); } } } } else SendMessageW(hwndList, LVM_REDRAWITEMS, wParam, lParam); } } return TRUE; } return SkinnedListView::DialogProc(hwndDlg,uMsg,wParam,lParam); } HMENU AlbumArtListView::GetMenu(bool isFilter, int filterNum, C_Config *c, HMENU themenu) { HMENU menu = GetSubMenu(themenu, 10); int checked=0; switch(mode) { case 0: checked=ID_ARTHEADERMENU_SMALLDETAILS; break; case 1: checked=ID_ARTHEADERMENU_MEDIUMDETAILS; break; case 2: checked=ID_ARTHEADERMENU_LARGEDETAILS; break; case 3: checked=ID_ARTHEADERMENU_SMALLICON; break; case 4: checked=ID_ARTHEADERMENU_MEDIUMICON; break; case 5: checked=ID_ARTHEADERMENU_LARGEICON; break; } CheckMenuItem(menu,checked,MF_CHECKED | MF_BYCOMMAND); if(isFilter) { MENUITEMINFO m={sizeof(m),MIIM_ID,0}; int i=0; while(GetMenuItemInfo(menu,i,TRUE,&m)) { m.wID |= (1+filterNum) << 16; SetMenuItemInfo(menu,i,TRUE,&m); i++; } } return menu; } void AlbumArtListView::ProcessMenuResult(int r, bool isFilter, int filterNum, C_Config *c, HWND parent) { int mid = (r >> 16); if(!isFilter && mid) return; if(isFilter && mid-1 != filterNum) return; r &= 0xFFFF; switch(r) { case ID_ARTHEADERMENU_SMALLDETAILS: mode=0; break; case ID_ARTHEADERMENU_MEDIUMDETAILS: mode=1; break; case ID_ARTHEADERMENU_LARGEDETAILS: mode=2; break; case ID_ARTHEADERMENU_SMALLICON: mode=3; break; case ID_ARTHEADERMENU_MEDIUMICON: mode=4; break; case ID_ARTHEADERMENU_LARGEICON: mode=5; break; default: return; } contents->config->WriteInt(L"albumartviewmode",mode); contents->SetMode(mode); while (ListView_DeleteColumn(listview.getwnd(), 0)); DialogProc(parent,WM_INITDIALOG,0,0); HWND hwndList = GetDlgItem(parent,dlgitem); if (hwndList) { MLSkinnedWnd_SkinChanged(hwndList, TRUE, TRUE); ListView_SetItemCount(hwndList, contents->GetNumRows()); CalcuateItemHeight(); } }