diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/General/gen_ml/skinnedheader.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Plugins/General/gen_ml/skinnedheader.cpp')
-rw-r--r-- | Src/Plugins/General/gen_ml/skinnedheader.cpp | 832 |
1 files changed, 832 insertions, 0 deletions
diff --git a/Src/Plugins/General/gen_ml/skinnedheader.cpp b/Src/Plugins/General/gen_ml/skinnedheader.cpp new file mode 100644 index 00000000..ac0d7ea9 --- /dev/null +++ b/Src/Plugins/General/gen_ml/skinnedheader.cpp @@ -0,0 +1,832 @@ +#include "main.h" +#include "config.h" +#include "../winamp/wa_dlg.h" +#include "./skinnedheader.h" +#include "./skinning.h" +#include "./ml_imagelist.h" +#include "./imagefilters.h" +#include "./ml_cloudcolumn.h" +#include "./resource.h" + +// Timers +#define TIMER_UNBLOCKREDRAW_ID 1978 +#define TIMER_ENDTRACK_ID 1979 +#define TIMER_ENDTRACK_DELAY 5 + +// Header internal flags (LOWORD reserved to sort index) +#define HIF_ASCENDING 0x00010000 +#define HIF_OWNPARENTSW 0x00020000 // parent was subclassed by this control +#define HIF_REALCXY 0x00040000 +#define HIF_DEFSIZERULE 0x00100000 // item will use default size rule. +#define HIF_BLOCKCHANGING 0x10000000 +#define HIF_BLOCKCHANGED 0x20000000 +#define HIF_BLOCKWNDPOS 0x40000000 +#define HIF_BLOCKREDRAW 0x80000000 + +extern HMLIMGFLTRMNGR hmlifMngr; // default gen_ml fitler manager + +typedef struct _HDSIZE +{ + INT instanceRef; + INT *pCXY; // stored by index + INT *pOrder; // current left-to-right order of items (index values for items in the header). + INT count; + INT allocated; + INT headerCXY; + INT lastCXY; + HWND hwndParent; + HDITEMW hdi; // safe to use duaring size +} HDSIZE; + +typedef struct _HDCURSOR +{ + HWND hwndParent; + NMMOUSE nm; + HDHITTESTINFO hitTest; + DWORD pts; +} HDCURSOR; + +static HDSIZE hdrSize = {0,0,0, } ; + +static INT GetDefaultSizeRule(void) +{ + INT rule; + rule = g_config->ReadInt(L"column_resize_mode", 0); + switch(rule) + { + case 1: return SHS_SIZERULE_ADJUSTONE; + case 2: return SHS_SIZERULE_PROPORTIONAL; + case 3: return SHS_SIZERULE_ADJUSTALL; + } + return SHS_SIZERULE_WINDOWS; +} + +SkinnedHeader::SkinnedHeader(void) : SkinnedWnd(FALSE), hcurNormal(NULL), cloudColumn(-1) +{ + if (!hdrSize.instanceRef) + ZeroMemory(&hdrSize, sizeof(HDSIZE)); + + hdrSize.instanceRef++; + + hdrFlags = LOWORD(-1) | HIF_ASCENDING | HIF_DEFSIZERULE; + hdrSizeRule = (HIF_DEFSIZERULE & hdrFlags) ? GetDefaultSizeRule() : SHS_SIZERULE_WINDOWS; +} + +SkinnedHeader::~SkinnedHeader(void) +{ + if (hdrSize.instanceRef && !--hdrSize.instanceRef) + { + if (hdrSize.pCXY) + free(hdrSize.pCXY); // pOrder - use same buffer + ZeroMemory(&hdrSize, sizeof(HDSIZE)); + } +} + +extern HMLIMGLST hmlilCloud; +BOOL SkinnedHeader::Attach(HWND hwndHeader) +{ + HWND hwndParent; + + if(!__super::Attach(hwndHeader)) return FALSE; + + SetType(SKINNEDWND_TYPE_HEADER); + + hwndParent = GetParent(hwndHeader); + if (hwndParent) SkinWindow(hwndParent, SWS_NORMAL); + + hdrFlags = LOWORD(-1) | HIF_ASCENDING | HIF_DEFSIZERULE; + hdrSizeRule = (HIF_DEFSIZERULE & hdrFlags) ? GetDefaultSizeRule() : SHS_SIZERULE_WINDOWS; + + // set default height + SetHeight(-1); + + return TRUE; +} + +void SkinnedHeader::OnSkinChanged(BOOL bNotifyChildren, BOOL bRedraw) +{ + hcurNormal = (HCURSOR)SendMessageW(plugin.hwndParent, WM_WA_IPC, WACURSOR_NORMAL, IPC_GETSKINCURSORS); + __super::OnSkinChanged(bNotifyChildren, bRedraw); +} + +void SkinnedHeader::BlockRedraw(BOOL bBlock, UINT unblockDelay) +{ + KillTimer(hwnd, TIMER_UNBLOCKREDRAW_ID); + + if (FALSE != bBlock) + hdrFlags |= HIF_BLOCKREDRAW; + else + hdrFlags &= ~HIF_BLOCKREDRAW; + + CallDefWndProc(WM_SETREDRAW, (WPARAM)!bBlock, 0L); + + if (FALSE != bBlock && -1 != unblockDelay) + SetTimer(hwnd, TIMER_UNBLOCKREDRAW_ID, unblockDelay, NULL); +} + +DWORD SkinnedHeader::GetSortArrowSize(void) +{ + return MAKELPARAM(7, 8); +} + +BOOL SkinnedHeader::DrawSortArrow(HDC hdc, RECT *prc, COLORREF rgbBk, COLORREF rgbFg, BOOL bAscending) +{ + static HMLIMGLST hmlilSort = NULL; + IMAGELISTDRAWPARAMS ildp; + + if (!hmlilSort) + { + DWORD arrowSize = GetSortArrowSize(); + hmlilSort = MLImageListI_Create(GET_X_LPARAM(arrowSize)*2, GET_Y_LPARAM(arrowSize), MLILC_COLOR24_I, 1, 1, 1, hmlifMngr); + if (hmlilSort) + { + MLIMAGESOURCE_I mlis; + ZeroMemory(&mlis, sizeof(MLIMAGESOURCE_I)); + mlis.type = SRC_TYPE_PNG_I; + mlis.hInst = plugin.hDllInstance; + mlis.lpszName = MAKEINTRESOURCEW(IDB_SORTARROW); + MLImageListI_Add(hmlilSort, &mlis, MLIF_FILTER1_UID, 0); + } + } + + ZeroMemory(&ildp, sizeof(IMAGELISTDRAWPARAMS)); + ildp.cbSize = 56; // keep it hardcoded for now - otherwise brakes win2000. sizeof(IMAGELISTDRAWPARAMS); + + ildp.i = MLImageListI_GetRealIndex(hmlilSort, 0, rgbBk, rgbFg); + if (-1 != ildp.i) + { + ildp.hdcDst = hdc; + ildp.himl = MLImageListI_GetRealList(hmlilSort); + + ildp.cx = prc->right - prc->left; + ildp.cy = prc->bottom - prc->top; + ildp.x = prc->left; + ildp.y = prc->top; + ildp.fStyle = ILD_NORMAL; + ildp.dwRop = SRCCOPY; + ildp.xBitmap = (bAscending) ? ildp.cx : 0; + return ImageList_DrawIndirect(&ildp); + } + + return FALSE; +} + +BOOL SkinnedHeader::DrawCloudIcon(HDC hdc, RECT *prc, COLORREF rgbBk, COLORREF rgbFg) +{ + IMAGELISTDRAWPARAMS ildp; + + ZeroMemory(&ildp, sizeof(IMAGELISTDRAWPARAMS)); + ildp.cbSize = 56; // keep it hardcoded for now - otherwise brakes win2000. sizeof(IMAGELISTDRAWPARAMS); + + ildp.i = MLImageListI_GetRealIndex(hmlilCloud, 0, rgbBk, rgbFg); + if (-1 != ildp.i) + { + ildp.hdcDst = hdc; + ildp.himl = MLImageListI_GetRealList(hmlilCloud); + + ildp.cx = 16; + ildp.cy = 16; + ildp.x = prc->left - 7; + ildp.y = prc->top - 4; + ildp.fStyle = ILD_NORMAL; + ildp.dwRop = SRCCOPY; + ildp.xBitmap = 0; + return ImageList_DrawIndirect(&ildp); + } + return FALSE; +} + +void SkinnedHeader::DrawHeaderItem(LPNMCUSTOMDRAW pnmcd) +{ + HPEN pen, penOld; + HDC hdc; + RECT *prc, rcText; + INT textRight; + INT ox, oy; + + hdc = pnmcd->hdc; + prc = &pnmcd->rc; + + ox = (CDIS_SELECTED & pnmcd->uItemState) ? 1 : 0; + oy = 0; + + SetBkColor(hdc, WADlg_getColor(WADLG_LISTHEADER_BGCOLOR)); + ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, prc, L"", 0, 0); + + pen = (HPEN)MlStockObjects_Get((CDIS_SELECTED & pnmcd->uItemState) ? HEADERBOTTOM_PEN : HEADERTOP_PEN); + penOld = (HPEN)SelectObject(hdc, pen); + + MoveToEx(hdc, prc->left, prc->top, NULL); + LineTo(hdc, prc->right, prc->top); + MoveToEx(hdc, prc->left, prc->top, NULL); + LineTo(hdc, prc->left, prc->bottom); + + if (0 == (CDIS_SELECTED & pnmcd->uItemState)) + { + SelectObject(hdc, penOld); + + pen = (HPEN)MlStockObjects_Get(HEADERBOTTOM_PEN); + penOld = (HPEN)SelectObject(hdc, pen); + } + + MoveToEx(hdc, prc->right - 1, prc->top, NULL); + LineTo(hdc, prc->right - 1, prc->bottom); + MoveToEx(hdc, prc->right - 1, prc->bottom - 1, NULL); + LineTo(hdc, prc->left - 1, prc->bottom - 1); + + if (0 == (CDIS_SELECTED & pnmcd->uItemState)) + { + SelectObject(hdc, penOld); + + pen = (HPEN)MlStockObjects_Get(HEADERMIDDLE_PEN); + penOld = (HPEN)SelectObject(hdc, pen); + + MoveToEx(hdc, prc->right - 2, prc->top + 1, NULL); + LineTo(hdc, prc->right - 2, prc->bottom - 2); + MoveToEx(hdc, prc->right - 2, prc->bottom - 2, NULL); + LineTo(hdc, prc->left, prc->bottom - 2); + } + + textRight = prc->right - 5 + ox; + if (LOWORD(hdrFlags) == pnmcd->dwItemSpec || pnmcd->dwItemSpec == cloudColumn) + { + RECT r; + DWORD arrowSize; + int dividerArea; + + arrowSize = GetSortArrowSize(); + SetRect(&r, 0, 0, GET_X_LPARAM(arrowSize), GET_Y_LPARAM(arrowSize)); + + dividerArea = 4*GetSystemMetrics(SM_CXEDGE); + + OffsetRect(&r, prc->right - r.right - dividerArea, (((prc->bottom - prc->top) - r.bottom) + 1)/2); + + if (pnmcd->dwItemSpec != cloudColumn && (r.left > (prc->left + 16) && r.top > (prc->top + 2))) + { + if (DrawSortArrow(hdc, &r, + WADlg_getColor(WADLG_LISTHEADER_BGCOLOR), + WADlg_getColor(WADLG_LISTHEADER_FONTCOLOR), + (HIF_ASCENDING & hdrFlags))) textRight = r.left - 3; + } + else if (pnmcd->dwItemSpec == cloudColumn) + { + if ((prc->right - prc->left) >= MLCloudColumnI_GetMinWidth()) + { + DrawCloudIcon(hdc, &r, + WADlg_getColor(WADLG_LISTHEADER_BGCOLOR), + WADlg_getColor(WADLG_LISTHEADER_FONTCOLOR)); + } + } + } + + if (pnmcd->dwItemSpec != cloudColumn && (textRight > (prc->left + 4 + ox))) + { + WCHAR buffer[128] = {0}; + HDITEMW item; + + item.mask = HDI_TEXT | HDI_FORMAT; + item.pszText = buffer; + item.cchTextMax = sizeof(buffer)/sizeof(wchar_t) -1; + + if (CallPrevWndProc(HDM_GETITEMW, (WPARAM)pnmcd->dwItemSpec, (LPARAM)&item)) + { + DWORD format; + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, WADlg_getColor(WADLG_LISTHEADER_FONTCOLOR)); + + SetRect(&rcText, prc->left + 5 + ox, prc->top + 2 + oy, textRight, prc->bottom - 2); + format = DT_VCENTER | DT_SINGLELINE | DT_LEFT | DT_NOCLIP; + + switch(HDF_JUSTIFYMASK & item.fmt) + { + case HDF_RIGHT: format |= DT_RIGHT; break; + case HDF_CENTER: format |= DT_CENTER; break; + } + // because we draw with DT_NOCLIP, make sure we don't overhang to the right + RECT testRect = rcText; + DrawTextW(hdc, item.pszText, -1, &testRect, format | DT_CALCRECT); + if (testRect.right > textRight) + { + format &= ~(HDF_JUSTIFYMASK | DT_NOCLIP); + format |= DT_LEFT; + + if ((testRect.right - textRight) > 6) + format |= DT_END_ELLIPSIS; + } + + DrawTextW(hdc, item.pszText, -1, &rcText, format); + } + } + + SelectObject(hdc, penOld); +} + +BOOL SkinnedHeader::OnCustomDraw(HWND hwndFrom, NMCUSTOMDRAW *pnmcd, LRESULT *pResult) +{ + switch(pnmcd->dwDrawStage) + { + case CDDS_PREPAINT: + *pResult = (SWS_USESKINCOLORS & style) ? + CDRF_NOTIFYITEMDRAW : + CDRF_DODEFAULT; + return TRUE; + case CDDS_ITEMPREPAINT: + DrawHeaderItem(pnmcd); + *pResult = CDRF_SKIPDEFAULT; + return TRUE; + } + return FALSE; +} + +UINT SkinnedHeader::SizeRuleAdjustOne(HDITEMW *phdi, INT index, UINT uMsg) +{ + UINT result, flags; + + flags = hdrFlags; + hdrFlags |= HIF_REALCXY; + + result = 0; + if (index < hdrSize.count) + { + INT delta; + delta = phdi->cxy - hdrSize.pCXY[index]; + + hdrSize.hdi.mask = HDI_WIDTH; + phdi = &hdrSize.hdi; + + if (delta) + { + if(CallPrevWndProc(HDM_GETITEMW, index + 1, (LPARAM)phdi)) + { + INT temp = phdi->cxy; + phdi->cxy -= delta; + if (CallPrevWndProc(HDM_SETITEMW, index + 1, (LPARAM)phdi)) delta = temp - phdi->cxy; + else delta = 0; + } + hdrSize.pCXY[index] += delta; + result = 1; + } + } + + hdrFlags = flags; + + return result; +} + +UINT SkinnedHeader::SizeRuleProportional(HDITEMW *phdi, INT index, UINT uMsg) +{ + UINT flags; + INT o, delta; + + if (index >= hdrSize.count || + hdrSize.lastCXY == phdi->cxy || + 0 == (phdi->cxy - hdrSize.pCXY[index])) + { + return 0; + } + + flags = hdrFlags; + hdrFlags |= HIF_REALCXY; + + delta = phdi->cxy - hdrSize.pCXY[index]; + + hdrSize.lastCXY = phdi->cxy; + + for (o = 0; o < hdrSize.count; o++) + { + if (hdrSize.pOrder[o] == index) + break; + } + + phdi = &hdrSize.hdi; + phdi->mask = HDI_WIDTH; + + for(++o; o < hdrSize.count && 0 != delta; o++) + { + INT i = hdrSize.pOrder[o]; + + INT r = delta / (hdrSize.count - o) + ((delta % (hdrSize.count - o)) ? ((delta >0) ? 1 : -1) : 0); + if (0 == r) + r = delta; + + phdi->cxy = hdrSize.pCXY[i] - r; + INT temp = phdi->cxy; + + CallPrevWndProc(HDM_SETITEMW, i, (LPARAM)phdi); + delta -= r; + + // hdrSize.pCXY[i] = phdi->cxy; + + if (phdi->cxy != temp) + delta += (phdi->cxy- temp); + } + + hdrFlags = flags; + + return 1; +} + +BOOL SkinnedHeader::OnBeginTrack(HWND hwndFrom, NMHEADERW *phdn, LRESULT *pResult) +{ + if (HIF_DEFSIZERULE & hdrFlags) hdrSizeRule = GetDefaultSizeRule(); + + KillTimer(hwnd, TIMER_ENDTRACK_ID); + + hdrSize.headerCXY = 0; + hdrSize.lastCXY = -1; + hdrSize.hwndParent = hwndFrom; + + hdrSize.count = (INT)CallPrevWndProc(HDM_GETITEMCOUNT, 0, 0L); + if (hdrSize.count < 0) hdrSize.count = 0; + + if (hdrSize.count > 0) + { + HDITEMW item; + + if (hdrSize.count > hdrSize.allocated) + { + VOID *data; + data = realloc(hdrSize.pCXY, sizeof(INT)*hdrSize.count*2); + if (data) + { + hdrSize.pCXY = (INT*)data; + hdrSize.pOrder = hdrSize.pCXY + hdrSize.count; + hdrSize.allocated = hdrSize.count; + } + if (!data) hdrSize.count = 0; + } + + if (hdrSize.count) + { + INT i; + if (!CallPrevWndProc(HDM_GETORDERARRAY, hdrSize.count, (LPARAM)hdrSize.pOrder)) + { + for (i = 0; i < hdrSize.count; i++) hdrSize.pOrder[i] = i; + } + + item.mask = HDI_WIDTH; + for (INT o = 0; o < hdrSize.count; o++) + { + i = hdrSize.pOrder[o]; + if (SendMessageW(hwnd, HDM_GETITEMW, i, (LPARAM)&item) && item.lParam) + { + hdrSize.pCXY[i] = item.cxy; + hdrSize.headerCXY += item.cxy; + } + } + } + } + + return FALSE; +} + +BOOL SkinnedHeader::OnEndTrack(HWND hwndFrom, NMHEADERW *phdn) +{ + if (hdrSize.count) + { + BlockRedraw(FALSE, 0); + hdrFlags &= ~(HIF_BLOCKCHANGING | HIF_BLOCKCHANGED); + SetTimer(hwnd, TIMER_ENDTRACK_ID, TIMER_ENDTRACK_DELAY, NULL); + } + return FALSE; +} + +BOOL SkinnedHeader::OnItemChanging(HWND hwndFrom, NMHEADERW *phdn, LRESULT *pResult) +{ + if (HIF_BLOCKCHANGING & hdrFlags) + { + *pResult = FALSE; + return TRUE; + } + + if (0 != hdrSize.count && + 0 == (HIF_REALCXY & hdrFlags)) + { + switch(hdrSizeRule) + { + case SHS_SIZERULE_ADJUSTONE: + case SHS_SIZERULE_PROPORTIONAL: + case SHS_SIZERULE_ADJUSTALL: + BlockRedraw(TRUE, 10); + break; + } + } + return FALSE; +} + +BOOL SkinnedHeader::OnItemChanged(HWND hwndFrom, NMHEADERW *phdn) +{ + UINT result; + + if (HIF_BLOCKCHANGED & hdrFlags) + return TRUE; + + if((HIF_REALCXY & hdrFlags) || !phdn->pitem || 0== (HDI_WIDTH & phdn->pitem->mask)) + return FALSE; + + hdrFlags |= HIF_BLOCKCHANGED; + + switch(hdrSizeRule) + { + case SHS_SIZERULE_ADJUSTONE: result = SizeRuleAdjustOne(phdn->pitem, phdn->iItem, phdn->hdr.code); break; + case SHS_SIZERULE_PROPORTIONAL: result = SizeRuleProportional(phdn->pitem, phdn->iItem, phdn->hdr.code); break; + case SHS_SIZERULE_ADJUSTALL: result = 0; break; + default: result = 0; break; + } + + hdrFlags &= ~HIF_BLOCKCHANGED; + + if (result) + { + if(hdrSize.count) + { + INT i; + HDITEMW item; + item.mask = HDI_WIDTH; + i = hdrSize.pOrder[hdrSize.count - 1]; + if (CallPrevWndProc(HDM_GETITEMW, i, (LPARAM)&item)) + { + long cxy = item.cxy; + hdrFlags |= (HIF_BLOCKCHANGING | HIF_BLOCKCHANGED | HIF_REALCXY); + item.cxy = cxy + 1; + CallPrevWndProc(HDM_SETITEMW, i, (LPARAM)&item); + hdrFlags &= ~(HIF_BLOCKCHANGING | HIF_BLOCKCHANGED); + item.cxy = cxy; + CallPrevWndProc(HDM_SETITEMW, i, (LPARAM)&item); + hdrFlags &= ~HIF_REALCXY; + } + } + + BlockRedraw(FALSE, 0); + + if (NULL != hdrSize.hwndParent) + { + RedrawWindow(hdrSize.hwndParent, NULL, NULL, + RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN/*| RDW_VALIDATE*/); + } + else + RedrawWindow(hwnd, NULL, NULL, + RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN/*| RDW_VALIDATE*/); + + return TRUE; + } + + return FALSE; +} + +BOOL SkinnedHeader::OnCursorNotify(HWND hwndFrom, NMMOUSE *pnm, LRESULT *pResult) +{ + if (0 == ((HHT_ONDIVIDER | HHT_ONDIVOPEN)& pnm->dwHitInfo) && (SWS_USESKINCURSORS & style) && hcurNormal) + { + SetCursor(hcurNormal); + *pResult = TRUE; + return TRUE; + } + return FALSE; +} + +BOOL SkinnedHeader::OnReflectedNotify(INT idCtrl, REFLECTPARAM *rParam) +{ + if (rParam->hwndFrom != GetParent(hwnd)) return FALSE; // controls such as listview forward headers notifications to they parent. + + switch(((NMHDR*)(rParam->lParam))->code) + { + case NM_CUSTOMDRAW: return OnCustomDraw(rParam->hwndFrom, (NMCUSTOMDRAW*)rParam->lParam, &rParam->result); + case HDN_ITEMCHANGINGA: + case HDN_ITEMCHANGINGW: return OnItemChanging(rParam->hwndFrom, (NMHEADERW*)rParam->lParam, &rParam->result); + case HDN_ITEMCHANGEDA: + case HDN_ITEMCHANGEDW: return OnItemChanged(rParam->hwndFrom, (NMHEADERW*)rParam->lParam); + case HDN_BEGINTRACKA: + case HDN_BEGINTRACKW: return OnBeginTrack(rParam->hwndFrom, (NMHEADERW*)rParam->lParam, &rParam->result); + case HDN_ENDTRACKA: + case HDN_ENDTRACKW: return OnEndTrack(rParam->hwndFrom, (NMHEADERW*)rParam->lParam); + case NM_SETCURSOR: return OnCursorNotify(rParam->hwndFrom, (NMMOUSE*)rParam->lParam, &rParam->result); + } + + return FALSE; +} + +void SkinnedHeader::OnPaint(void) +{ + if (HIF_BLOCKREDRAW & hdrFlags) + { + ValidateRgn(hwnd, NULL); + } + else if (SWS_USESKINCOLORS & style) + { + //process the grey area with our color + RECT rc, ri; + int i; + GetClientRect(hwnd, &rc); + i = (INT)CallPrevWndProc(HDM_GETITEMCOUNT, 0, 0L); + if(i > 0) + { + Header_GetItemRect(hwnd, (INT)CallPrevWndProc(HDM_ORDERTOINDEX, (i-1), 0L), &ri); + rc.left = ri.right; + } + + if(rc.left < rc.right && GetUpdateRect(hwnd, &ri, FALSE) && IntersectRect(&rc, &rc, &ri)) + { + UINT flags = DCX_PARENTCLIP | DCX_CACHE | DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | + DCX_INTERSECTUPDATE | DCX_VALIDATE; + + HDC hdc = GetDCEx(hwnd, NULL, flags); + if(hdc) + { + COLORREF rgbBkOld; + rgbBkOld = SetBkColor(hdc, WADlg_getColor(WADLG_LISTHEADER_EMPTY_BGCOLOR)); + ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &rc, L"", 0, 0); + SetBkColor(hdc, rgbBkOld); + ReleaseDC(hwnd, hdc); + ValidateRect(hwnd, &rc); + } + } + } +} + +void SkinnedHeader::OnTimer(UINT_PTR nIDEvent, TIMERPROC lpTimerFunc) +{ + switch (nIDEvent) + { + case TIMER_UNBLOCKREDRAW_ID: + BlockRedraw(FALSE, 0); + return; + case TIMER_ENDTRACK_ID: + KillTimer(hwnd, TIMER_ENDTRACK_ID); + hdrSize.count = 0; + hdrSize.headerCXY = 0; + hdrSize.lastCXY = -1; + return; + } + __super::WindowProc(WM_TIMER, (WPARAM)nIDEvent, (LPARAM)lpTimerFunc); +} + +void SkinnedHeader::SetHeight(INT nHeight) +{ + RECT rw; + GetWindowRect(hwnd, &rw); + + if (nHeight < 0) + { + HDC hdc; + hdc = GetWindowDC(hwnd); + if (hdc) + { + HFONT hfnt; + hfnt = (HFONT)CallPrevWndProc(WM_GETFONT, 0, 0L); + if (!hfnt) hfnt = (HFONT)MlStockObjects_Get(DEFAULT_FONT); + if (hfnt) + { + TEXTMETRICW tm = {0}; + HFONT hfntOld = (HFONT)SelectObject(hdc, hfnt); + + if (GetTextMetricsW(hdc, &tm)) nHeight = tm.tmHeight + 6/*Borders*/; + SelectObject(hdc, hfntOld); + } + ReleaseDC(hwnd, hdc); + } + } + + if (nHeight != (rw.bottom - rw.top)) + { + INT i; + + SetWindowPos(hwnd, NULL, 0, 0, rw.right - rw.left, nHeight, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER); + if (HDS_HIDDEN & GetWindowLongPtrW(hwnd, GWL_STYLE)) return; + + i = (INT)CallPrevWndProc(HDM_GETITEMCOUNT, 0, 0L); + if(i > 0) + { + HDITEMW item; + i = (INT)CallPrevWndProc(HDM_ORDERTOINDEX, (i-1), 0L); + item.mask = HDI_WIDTH; + if (CallPrevWndProc(HDM_GETITEMW, i, (LPARAM)&item)) + { + hdrFlags |= (HIF_BLOCKCHANGING | HIF_BLOCKCHANGED | HIF_REALCXY); + item.cxy++; CallPrevWndProc(HDM_SETITEMW, i, (LPARAM)&item); + hdrFlags &= ~(HIF_BLOCKCHANGING | HIF_BLOCKCHANGED); + item.cxy--; CallPrevWndProc(HDM_SETITEMW, i, (LPARAM)&item); + hdrFlags &= ~HIF_REALCXY; + } + } + } +} + +BOOL SkinnedHeader::OnLayout(HDLAYOUT *pLayout) +{ + BOOL result; + + result = (BOOL)__super::WindowProc(HDM_LAYOUT, 0, (LPARAM)pLayout); + + if (0 == (HDS_HIDDEN & GetWindowLongPtrW(hwnd, GWL_STYLE))) + { + RECT rw; + + GetWindowRect(hwnd, &rw); + OffsetRect(&rw, -rw.left, -rw.top); + + pLayout->pwpos->cy= rw.bottom; + pLayout->prc->top = rw.bottom; + + if (GetClientRect(GetParent(hwnd), &rw)) + pLayout->pwpos->cx = (rw.right - rw.left) - pLayout->pwpos->x; + } + return result; +} + +BOOL SkinnedHeader::OnSetCursor(HWND hwdCursor, UINT hitTest, UINT message) +{ + static HDCURSOR hdrCursor; + + hdrCursor.hwndParent = GetParent(hwnd); + if (hdrCursor.hwndParent) + { + hdrCursor.nm.hdr.code = NM_SETCURSOR; + hdrCursor.nm.hdr.hwndFrom = hwnd; + hdrCursor.nm.hdr.idFrom = GetDlgCtrlID(hwnd); + + hdrCursor.pts = GetMessagePos(); + POINTSTOPOINT(hdrCursor.nm.pt, hdrCursor.pts); + + hdrCursor.hitTest.pt = hdrCursor.nm.pt; + MapWindowPoints(HWND_DESKTOP, hwnd, &hdrCursor.hitTest.pt, 1); + CallPrevWndProc(HDM_HITTEST, 0, (LPARAM)&hdrCursor.hitTest); + + hdrCursor.nm.dwItemSpec = hdrCursor.hitTest.iItem; + hdrCursor.nm.dwHitInfo = hdrCursor.hitTest.flags; + if (SendMessage(hdrCursor.hwndParent, WM_NOTIFY, (WPARAM)hdrCursor.nm.hdr.code, (LPARAM)&hdrCursor.nm)) + return TRUE; + } + return (BOOL)__super::WindowProc(WM_SETCURSOR, (WPARAM)hwdCursor, MAKELPARAM(hitTest, message)); +} + +LRESULT SkinnedHeader::OnSetItem(INT iIndex, HDITEMW *phdItem, BOOL bUnicode) +{ + if (NULL != phdItem && + 0 != (HDI_FORMAT & phdItem->mask)) + { + DWORD newFlags = 0x0000FFFF | (hdrFlags & (0xFFFF0000 & ~HIF_ASCENDING)); + if (0 != ((HDF_SORTDOWN | HDF_SORTUP) & phdItem->fmt) && + iIndex >= 0 && iIndex < 0xFFFF) + { + newFlags = (newFlags & 0xFFFF0000) | (0xFFFF & iIndex); + if (0 != (HDF_SORTUP & phdItem->fmt)) + newFlags |= HIF_ASCENDING; + } + + if ((LOWORD(newFlags) != LOWORD(hdrFlags)) || + ((HIF_ASCENDING & newFlags) != (HIF_ASCENDING & hdrFlags))) + { + hdrFlags = newFlags; + RECT rcItem; + if (NULL != CallPrevWndProc(HDM_GETITEMRECT, (WPARAM)iIndex, (LPARAM)&rcItem)) + { + InvalidateRect(hwnd, &rcItem, FALSE); + } + } + } + + return __super::WindowProc(((bUnicode) ? HDM_SETITEMW : HDM_SETITEMA), (WPARAM)iIndex, (LPARAM)phdItem); +} + +BOOL SkinnedHeader::OnMediaLibraryIPC(INT msg, INT_PTR param, LRESULT *pResult) +{ + switch(msg) + { + case ML_IPC_SKINNEDHEADER_DISPLAYSORT: + hdrFlags = (hdrFlags & 0xFFFF0000) | LOWORD(param); + hdrFlags = (hdrFlags & ~HIF_ASCENDING) | ((HIWORD(param)) ? HIF_ASCENDING : 0); + *pResult = 1; + InvalidateRect(hwnd, NULL, FALSE); + UpdateWindow(hwnd); + return TRUE; + case ML_IPC_SKINNEDHEADER_SETHEIGHT: SetHeight((INT)param); *pResult = TRUE; return TRUE; + case ML_IPC_SKINNEDHEADER_GETSORT: *pResult = MAKELONG(LOWORD(hdrFlags), 0 != (HIF_ASCENDING & hdrFlags)); return TRUE; + case ML_IPC_SKINNEDHEADER_SETCLOUDCOLUMN: + cloudColumn = (INT)param; + InvalidateRect(hwnd, NULL, FALSE); + UpdateWindow(hwnd); + return TRUE; + } + return __super::OnMediaLibraryIPC(msg, param, pResult); +} + +LRESULT SkinnedHeader::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_ERASEBKGND: return 1; + case WM_PAINT: OnPaint(); break; + case WM_TIMER: OnTimer((UINT_PTR)wParam, (TIMERPROC)lParam); return 0; + case WM_SETCURSOR: return OnSetCursor((HWND)wParam, LOWORD(lParam), HIWORD(lParam)); + case WM_CAPTURECHANGED: InvalidateRect(hwnd, NULL, TRUE); break; + case WM_WINDOWPOSCHANGING: if (HIF_BLOCKWNDPOS & hdrFlags) return TRUE; + break; + case REFLECTED_NOTIFY: return OnReflectedNotify((INT)wParam, (REFLECTPARAM*)lParam); + case HDM_LAYOUT: return OnLayout((LPHDLAYOUT)lParam); + case HDM_SETITEMA: + case HDM_SETITEMW: + return OnSetItem((INT)wParam, (HDITEMW*)lParam, (HDM_SETITEMW == uMsg)); + } + return __super::WindowProc(uMsg, wParam, lParam); +}
\ No newline at end of file |