1115 lines
28 KiB
C++
1115 lines
28 KiB
C++
|
#include "main.h"
|
||
|
|
||
|
#include "../gen_ml/ml.h"
|
||
|
#include "../gen_ml/ml_ipc_0313.h"
|
||
|
#include "../Winamp/gen.h"
|
||
|
|
||
|
#define WM_EX_GETREALLIST (WM_USER + 0x01)
|
||
|
#define WM_EX_UNLOCKREDRAW (WM_USER + 0x02)
|
||
|
#define WM_EX_UPDATESCROLLINFO (WM_USER + 0x03)
|
||
|
#define WM_EX_GETCOUNTPERPAGE (WM_USER + 0x04)
|
||
|
|
||
|
#define LVN_EX_SIZECHANGED (LVN_LAST)
|
||
|
|
||
|
#define IWF_NO 0x0000
|
||
|
#define IWF_ALL 0x00FF
|
||
|
#define IWF_CONTAINER 0x0001
|
||
|
#define IWF_LISTVIEW 0x0002
|
||
|
#define IWF_HEADER 0x0004
|
||
|
#define IWF_UPDATENOW 0x1000
|
||
|
|
||
|
BOOL
|
||
|
CopyListColumnToHeaderItem(const LVCOLUMNW *column, HDITEMW *item)
|
||
|
{
|
||
|
if (NULL == column || NULL == item)
|
||
|
return FALSE;
|
||
|
|
||
|
item->mask = 0;
|
||
|
if (0 != (LVCF_FMT & column->mask))
|
||
|
{
|
||
|
item->mask |= HDI_FORMAT;
|
||
|
item->fmt = 0;
|
||
|
|
||
|
switch((LVCFMT_JUSTIFYMASK & column->fmt))
|
||
|
{
|
||
|
case LVCFMT_RIGHT:
|
||
|
item->fmt |= HDF_RIGHT;
|
||
|
break;
|
||
|
case LVCFMT_CENTER:
|
||
|
item->fmt |= HDF_CENTER;
|
||
|
break;
|
||
|
default:
|
||
|
item->fmt |= HDF_LEFT;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (0 != (LVCFMT_IMAGE & column->fmt))
|
||
|
item->fmt |= HDF_IMAGE;
|
||
|
|
||
|
if (0 != (LVCFMT_BITMAP_ON_RIGHT & column->fmt))
|
||
|
item->fmt |= HDF_BITMAP_ON_RIGHT;
|
||
|
}
|
||
|
|
||
|
if (0 != (LVCF_WIDTH & column->mask))
|
||
|
{
|
||
|
item->mask |= HDI_WIDTH;
|
||
|
item->cxy = column->cx;
|
||
|
}
|
||
|
|
||
|
if (0 != (LVCF_TEXT & column->mask))
|
||
|
{
|
||
|
item->mask |= HDI_TEXT;
|
||
|
item->pszText = column->pszText;
|
||
|
item->cchTextMax = column->cchTextMax;
|
||
|
}
|
||
|
|
||
|
if (0 != (LVCF_IMAGE & column->mask))
|
||
|
{
|
||
|
item->mask |= HDI_IMAGE;
|
||
|
item->iImage = column->iImage;
|
||
|
}
|
||
|
|
||
|
if (0 != (LVCF_ORDER & column->mask))
|
||
|
{
|
||
|
item->mask |= HDI_ORDER;
|
||
|
item->iOrder = column->iOrder;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
CopyHeaderItemToListColumn(const HDITEMW *item, LVCOLUMNW *column)
|
||
|
{
|
||
|
if (NULL == column || NULL == item)
|
||
|
return FALSE;
|
||
|
|
||
|
column->mask = 0;
|
||
|
if (0 != (HDI_FORMAT& item->mask))
|
||
|
{
|
||
|
column->mask |= LVCF_FMT ;
|
||
|
column->fmt = 0;
|
||
|
|
||
|
switch((HDF_JUSTIFYMASK & item->fmt))
|
||
|
{
|
||
|
case HDF_RIGHT:
|
||
|
column->fmt |= LVCFMT_RIGHT;
|
||
|
break;
|
||
|
case HDF_CENTER:
|
||
|
column->fmt |= LVCFMT_CENTER;
|
||
|
break;
|
||
|
default:
|
||
|
column->fmt |= LVCFMT_LEFT;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (0 != (HDF_IMAGE & item->fmt))
|
||
|
column->fmt |= LVCFMT_IMAGE;
|
||
|
|
||
|
if (0 != (HDF_BITMAP_ON_RIGHT & item->fmt))
|
||
|
column->fmt |= LVCFMT_BITMAP_ON_RIGHT;
|
||
|
}
|
||
|
|
||
|
if (0 != (HDI_WIDTH & item->mask))
|
||
|
{
|
||
|
column->mask |= LVCF_WIDTH;
|
||
|
column->cx = item->cxy;
|
||
|
}
|
||
|
|
||
|
if (0 != (HDI_TEXT & item->mask))
|
||
|
{
|
||
|
column->mask |= LVCF_TEXT;
|
||
|
column->pszText = item->pszText;
|
||
|
column->cchTextMax = item->cchTextMax;
|
||
|
}
|
||
|
|
||
|
if (0 != (HDI_IMAGE & item->mask))
|
||
|
{
|
||
|
column->mask |= LVCF_IMAGE;
|
||
|
column->iImage = item->iImage;
|
||
|
}
|
||
|
|
||
|
if (0 != (HDI_ORDER & item->mask))
|
||
|
{
|
||
|
column->mask |= LVCF_ORDER;
|
||
|
column->iOrder = item->iOrder;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static BOOL UpdateScrollInfo(HWND hwnd, UINT fMask, BOOL bRedraw)
|
||
|
{
|
||
|
HWND hwndList;
|
||
|
SCROLLINFO si;
|
||
|
BOOL bUpdateBars(FALSE);
|
||
|
|
||
|
hwndList = GetDlgItem(hwnd,2);
|
||
|
|
||
|
si.cbSize= sizeof(SCROLLINFO);
|
||
|
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
|
||
|
|
||
|
if (!hwndList || !GetScrollInfo(hwnd, SB_VERT, &si))
|
||
|
return FALSE;
|
||
|
|
||
|
if (SIF_RANGE & fMask)
|
||
|
{
|
||
|
RECT rc, rv;
|
||
|
|
||
|
UINT nPage;
|
||
|
INT nMax;
|
||
|
BOOL bScrollVisible;
|
||
|
HDLAYOUT headerLayout;
|
||
|
WINDOWPOS headerPos;
|
||
|
|
||
|
HWND hwndHeader = GetDlgItem(hwnd, 3);
|
||
|
if (!hwndHeader)
|
||
|
return FALSE;
|
||
|
|
||
|
GetClientRect(hwnd, &rc);
|
||
|
ListView_GetViewRect(hwndList,&rv);
|
||
|
|
||
|
headerLayout.prc = &rc;
|
||
|
headerLayout.pwpos = &headerPos;
|
||
|
|
||
|
SendMessageW(hwndHeader, HDM_LAYOUT, 0, (LPARAM)&headerLayout);
|
||
|
|
||
|
bScrollVisible = (si.nMax > 0 && si.nPage > 0 && (INT)si.nPage < si.nMax);
|
||
|
|
||
|
nMax = rv.bottom - rv.top;
|
||
|
nPage = (rc.bottom - rc.top);
|
||
|
|
||
|
if (si.nMax != nMax || si.nPage != nPage)
|
||
|
{
|
||
|
si.nMin = 0;
|
||
|
si.nMax = nMax;
|
||
|
si.nPage = nPage;
|
||
|
SetScrollInfo(hwnd, SB_VERT, &si, FALSE);
|
||
|
bUpdateBars = TRUE;
|
||
|
if (bScrollVisible != (si.nMax > 0 && si.nPage > 0 && (INT)si.nPage < si.nMax))
|
||
|
{
|
||
|
MLSkinnedScrollWnd_UpdateBars(hwnd, bRedraw);
|
||
|
GetClientRect(hwnd, &rc);
|
||
|
|
||
|
headerLayout.prc = &rc;
|
||
|
headerLayout.pwpos = &headerPos;
|
||
|
|
||
|
SendMessageW(hwndHeader, HDM_LAYOUT, 0, (LPARAM)&headerLayout);
|
||
|
|
||
|
headerPos.flags |= SWP_NOREDRAW;
|
||
|
SetWindowPos(hwndHeader, headerPos.hwndInsertAfter, headerPos.x, headerPos.y,
|
||
|
headerPos.cx, headerPos.cy, headerPos.flags);
|
||
|
|
||
|
SetWindowPos(hwndList, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
|
||
|
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
|
||
|
|
||
|
if (FALSE != bRedraw)
|
||
|
RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
|
||
|
|
||
|
bUpdateBars = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (SIF_POS & fMask)
|
||
|
{
|
||
|
POINT p;
|
||
|
if (FALSE != SendMessageW(hwndList, LVM_GETORIGIN, (WPARAM)0, (LPARAM)&p))
|
||
|
{
|
||
|
if (p.y < si.nMin)
|
||
|
p.y = si.nMin;
|
||
|
|
||
|
if (p.y > (si.nMax - (int)si.nPage))
|
||
|
p.y = si.nMax - si.nPage;
|
||
|
|
||
|
if (p.y != si.nPos)
|
||
|
{
|
||
|
si.nPos = p.y;
|
||
|
si.fMask = SIF_POS;
|
||
|
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
|
||
|
bUpdateBars = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (bUpdateBars)
|
||
|
MLSkinnedScrollWnd_UpdateBars(hwnd, bRedraw);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
UpdateFontMetrics(HWND hwnd, BOOL redraw)
|
||
|
{
|
||
|
HWND controlWindow;
|
||
|
RECT headerRect;
|
||
|
unsigned int windowStyle;
|
||
|
|
||
|
|
||
|
windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
|
||
|
if(0 != (WS_VISIBLE & windowStyle))
|
||
|
SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);
|
||
|
|
||
|
|
||
|
controlWindow = GetDlgItem(hwnd, 3);
|
||
|
if (NULL != controlWindow)
|
||
|
{
|
||
|
MLSkinnedHeader_SetHeight(controlWindow, -1);
|
||
|
if (FALSE == GetWindowRect(controlWindow, &headerRect))
|
||
|
SetRectEmpty(&headerRect);
|
||
|
}
|
||
|
else
|
||
|
SetRectEmpty(&headerRect);
|
||
|
|
||
|
|
||
|
controlWindow = GetDlgItem(hwnd, 2);
|
||
|
if (NULL != controlWindow)
|
||
|
{
|
||
|
|
||
|
RECT rect;
|
||
|
if (FALSE != GetClientRect(hwnd, &rect))
|
||
|
{
|
||
|
SetWindowPos(controlWindow, NULL,
|
||
|
rect.left, rect.top + headerRect.bottom - headerRect.top,
|
||
|
rect.right - rect.left, (rect.bottom - rect.top) - (headerRect.bottom - headerRect.top),
|
||
|
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOCOPYBITS);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
if (0 != (WS_VISIBLE & windowStyle))
|
||
|
{
|
||
|
windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
|
||
|
if (0 == (WS_VISIBLE & windowStyle))
|
||
|
{
|
||
|
windowStyle |= WS_VISIBLE;
|
||
|
SetWindowLongPtrW(hwnd, GWL_STYLE, windowStyle);
|
||
|
}
|
||
|
|
||
|
if (FALSE != redraw)
|
||
|
RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static HHOOK hook = NULL;
|
||
|
static HWND hwndToMonitor = NULL;
|
||
|
|
||
|
typedef struct UpdateSelection
|
||
|
{
|
||
|
BOOL active;
|
||
|
int iFrom;
|
||
|
int iTo;
|
||
|
}UpdateSelection;
|
||
|
|
||
|
|
||
|
typedef struct ListViewData
|
||
|
{
|
||
|
WNDPROC prevWindowProc;
|
||
|
UpdateSelection updateSelection;
|
||
|
} ListViewData;
|
||
|
|
||
|
#define LVCWP_NORMAL 0
|
||
|
#define LVCWP_UPDATESCROLLINFO (1 << 0)
|
||
|
|
||
|
static LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
MSG *pMsg = (MSG*)lParam;
|
||
|
if (pMsg->hwnd == hwndToMonitor)
|
||
|
{
|
||
|
switch(pMsg->message)
|
||
|
{
|
||
|
case WM_LBUTTONUP:
|
||
|
case WM_RBUTTONUP:
|
||
|
{
|
||
|
LRESULT result = CallNextHookEx(hook, nCode, wParam, lParam);
|
||
|
UnhookWindowsHookEx(hook);
|
||
|
hwndToMonitor = NULL;
|
||
|
hook = NULL;
|
||
|
return result;
|
||
|
}
|
||
|
case WM_MOUSEMOVE:
|
||
|
if ((MK_LBUTTON | MK_RBUTTON) & pMsg->wParam)
|
||
|
{
|
||
|
RECT rw;
|
||
|
POINTS pts(MAKEPOINTS(pMsg->lParam));
|
||
|
POINT pt;
|
||
|
POINTSTOPOINT(pt, pts);
|
||
|
MapWindowPoints(pMsg->hwnd, HWND_DESKTOP, &pt, 1);
|
||
|
GetWindowRect(pMsg->hwnd, &rw);
|
||
|
if (pt.y < rw.top || pt.y > rw.bottom)
|
||
|
{
|
||
|
HWND hwndParent = GetParent(pMsg->hwnd);
|
||
|
if (hwndParent)
|
||
|
{
|
||
|
SCROLLINFO si;
|
||
|
si.cbSize = sizeof(SCROLLINFO);
|
||
|
si.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
|
||
|
if (GetScrollInfo(hwndParent, SB_VERT, &si))
|
||
|
{
|
||
|
if ((si.nPos > si.nMin && pt.y < rw.top) || (si.nPos < (si.nMax - (INT)si.nPage) && pt.y > rw.bottom))
|
||
|
{
|
||
|
SendMessageW(hwndParent, WM_SETREDRAW, FALSE, 0L);
|
||
|
LRESULT result = CallNextHookEx(hook, nCode, wParam, lParam);
|
||
|
PostMessageW(hwndParent, WM_EX_UPDATESCROLLINFO, SIF_POS, FALSE);
|
||
|
PostMessageW(hwndParent, WM_EX_UNLOCKREDRAW, IWF_CONTAINER | IWF_LISTVIEW | IWF_UPDATENOW, 0L);
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
SleepEx(1, TRUE);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return CallNextHookEx(hook, nCode, wParam, lParam);
|
||
|
}
|
||
|
static void
|
||
|
ListView_ScheduleSelectionUpdate(HWND hwnd, int iFrom, int iTo)
|
||
|
{
|
||
|
ListViewData *listView;
|
||
|
listView = (ListViewData*)(LONG_PTR)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
|
||
|
if (NULL == listView)
|
||
|
return;
|
||
|
|
||
|
listView->updateSelection.iFrom = iFrom;
|
||
|
listView->updateSelection.iTo = iTo;
|
||
|
listView->updateSelection.active = TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
ListView_UpdateSelection(HWND hwnd, int iFrom, int iTo)
|
||
|
{
|
||
|
HWND parentWindow;
|
||
|
LVITEM item;
|
||
|
int start, stop, i, lim;
|
||
|
|
||
|
start = (int)SendMessageW(hwnd, LVM_GETSELECTIONMARK, 0, 0L);
|
||
|
stop = (int)SendMessageW(hwnd, LVM_GETNEXTITEM, iFrom - 1, LVNI_FOCUSED);
|
||
|
if (stop < start)
|
||
|
{
|
||
|
int tmp = start;
|
||
|
start = stop;
|
||
|
stop = tmp;
|
||
|
}
|
||
|
|
||
|
item.state = 0;
|
||
|
item.stateMask = LVIS_SELECTED;
|
||
|
|
||
|
if (start != iFrom)
|
||
|
{
|
||
|
if (start < iFrom)
|
||
|
{
|
||
|
i = start;
|
||
|
lim = iFrom;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
i = iFrom;
|
||
|
lim = start;
|
||
|
}
|
||
|
|
||
|
i--;
|
||
|
for(;;)
|
||
|
{
|
||
|
i = (int)SendMessageW(hwnd, LVM_GETNEXTITEM, (WPARAM)i,
|
||
|
(LPARAM)(LVNI_ALL | LVNI_SELECTED));
|
||
|
if (-1 == i || i >= lim)
|
||
|
break;
|
||
|
|
||
|
SendMessageW(hwnd, LVM_SETITEMSTATE, i, (LPARAM)&item);
|
||
|
}
|
||
|
}
|
||
|
if (stop < iTo)
|
||
|
{
|
||
|
i = stop + 1;
|
||
|
lim = iTo;
|
||
|
|
||
|
i--;
|
||
|
for(;;)
|
||
|
{
|
||
|
i = (int)SendMessageW(hwnd, LVM_GETNEXTITEM, (WPARAM)i,
|
||
|
(LPARAM)(LVNI_ALL | LVNI_SELECTED));
|
||
|
if (-1 == i || i > lim)
|
||
|
break;
|
||
|
|
||
|
SendMessageW(hwnd, LVM_SETITEMSTATE, i, (LPARAM)&item);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
parentWindow = GetAncestor(hwnd, GA_PARENT);
|
||
|
if (NULL != parentWindow)
|
||
|
{
|
||
|
HWND notifyWindow;
|
||
|
|
||
|
SendMessageW(parentWindow, WM_SETREDRAW, TRUE, 0L);
|
||
|
RedrawWindow(parentWindow, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
|
||
|
|
||
|
notifyWindow = GetAncestor(parentWindow, GA_PARENT);
|
||
|
if (NULL != notifyWindow)
|
||
|
{
|
||
|
NMLVODSTATECHANGE stateChange;
|
||
|
stateChange.hdr.idFrom = GetWindowLongPtrW(parentWindow, GWLP_ID);
|
||
|
stateChange.hdr.hwndFrom = parentWindow;
|
||
|
stateChange.hdr.code = LVN_ODSTATECHANGED;
|
||
|
stateChange.iFrom = start;
|
||
|
stateChange.iTo = stop;
|
||
|
stateChange.uNewState = LVIS_SELECTED;
|
||
|
stateChange.uOldState = 0;
|
||
|
SendMessageW(notifyWindow, WM_NOTIFY, stateChange.hdr.idFrom, (LPARAM)&stateChange);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
static LRESULT
|
||
|
ListView_CallWindowProc(ListViewData *listView, HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam,
|
||
|
unsigned int flags)
|
||
|
{
|
||
|
LRESULT result;
|
||
|
|
||
|
result = CallWindowProcW(listView->prevWindowProc, hwnd, uMsg, wParam, lParam);
|
||
|
|
||
|
if (FALSE != listView->updateSelection.active)
|
||
|
{
|
||
|
listView->updateSelection.active = FALSE;
|
||
|
ListView_UpdateSelection(hwnd, listView->updateSelection.iFrom, listView->updateSelection.iTo);
|
||
|
}
|
||
|
|
||
|
if (0 != (LVCWP_UPDATESCROLLINFO & flags))
|
||
|
{
|
||
|
HWND hwndParent;
|
||
|
hwndParent = GetAncestor(hwnd, GA_PARENT);
|
||
|
if (NULL != hwndParent)
|
||
|
UpdateScrollInfo(hwndParent, SIF_POS, TRUE);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static LRESULT WINAPI
|
||
|
ListView_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
ListViewData *listView;
|
||
|
listView = (ListViewData*)(LONG_PTR)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
|
||
|
|
||
|
if (NULL == listView ||
|
||
|
NULL == listView->prevWindowProc)
|
||
|
{
|
||
|
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
switch(uMsg)
|
||
|
{
|
||
|
case WM_DESTROY:
|
||
|
SetWindowLongPtrW(hwnd, GWLP_USERDATA, NULL);
|
||
|
CallWindowProcW(listView->prevWindowProc, hwnd, uMsg, wParam, lParam);
|
||
|
free(listView);
|
||
|
return 0;
|
||
|
case WM_KEYDOWN:
|
||
|
switch(wParam)
|
||
|
{
|
||
|
case VK_PRIOR:
|
||
|
case VK_UP:
|
||
|
case VK_HOME:
|
||
|
case VK_NEXT:
|
||
|
case VK_END:
|
||
|
case VK_DOWN:
|
||
|
case VK_LEFT:
|
||
|
case VK_RIGHT:
|
||
|
return ListView_CallWindowProc(listView, hwnd, uMsg, wParam, lParam, LVCWP_UPDATESCROLLINFO);
|
||
|
}
|
||
|
break;
|
||
|
case WM_TIMER:
|
||
|
if (43 == wParam)
|
||
|
return ListView_CallWindowProc(listView, hwnd, uMsg, wParam, lParam, LVCWP_UPDATESCROLLINFO);
|
||
|
break;
|
||
|
case WM_HSCROLL:
|
||
|
case WM_VSCROLL:
|
||
|
case WM_MOUSEWHEEL:
|
||
|
case LVM_ENSUREVISIBLE:
|
||
|
return ListView_CallWindowProc(listView, hwnd, uMsg, wParam, lParam, LVCWP_UPDATESCROLLINFO);
|
||
|
case WM_LBUTTONDOWN:
|
||
|
case WM_RBUTTONDOWN:
|
||
|
{
|
||
|
LVHITTESTINFO ht;
|
||
|
ht.pt.x = GET_X_LPARAM(lParam);
|
||
|
ht.pt.y = GET_Y_LPARAM(lParam);
|
||
|
if (-1 == SendMessageW(hwnd, LVM_HITTEST, 0, (LPARAM)&ht) || 0 == (LVHT_ONITEM & ht.flags))
|
||
|
{
|
||
|
hwndToMonitor = hwnd;
|
||
|
hook = SetWindowsHookEx(WH_MSGFILTER, HookProc, NULL, GetCurrentThreadId());
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ListView_CallWindowProc(listView, hwnd, uMsg, wParam, lParam, LVCWP_NORMAL);
|
||
|
}
|
||
|
|
||
|
|
||
|
static LRESULT
|
||
|
HeaderIconList_OnCreate(HWND hwnd, CREATESTRUCT *createStruct)
|
||
|
{
|
||
|
HWND hwndList, hwndHeader;
|
||
|
MLSKINWINDOW m;
|
||
|
RECT rc;
|
||
|
DWORD style;
|
||
|
|
||
|
m.skinType = SKINNEDWND_TYPE_SCROLLWND;
|
||
|
m.style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS;
|
||
|
m.hwndToSkin = hwnd;
|
||
|
MLSkinWindow(g_hwnd, &m);
|
||
|
|
||
|
SetScrollRange(hwnd, SB_VERT, 0, 0, FALSE);
|
||
|
MLSkinnedScrollWnd_UpdateBars(hwnd, FALSE);
|
||
|
|
||
|
GetClientRect(hwnd, &rc);
|
||
|
|
||
|
style = WS_CLIPSIBLINGS | WS_CHILD | WS_VISIBLE | HDS_BUTTONS | HDS_FULLDRAG;
|
||
|
hwndHeader = CreateWindowExW(WS_EX_NOPARENTNOTIFY, WC_HEADERW, L"", style, 0, 0, rc.right - rc.left, 20, hwnd, (HMENU)3,0,0);
|
||
|
if (NULL != hwndHeader)
|
||
|
{
|
||
|
m.hwndToSkin = hwndHeader;
|
||
|
m.skinType = SKINNEDWND_TYPE_HEADER;
|
||
|
m.style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS;
|
||
|
MLSkinWindow(g_hwnd, &m);
|
||
|
}
|
||
|
|
||
|
style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CHILD | WS_TABSTOP | WS_VISIBLE |
|
||
|
LVS_ICON | LVS_SHOWSELALWAYS | LVS_OWNERDATA | LVS_NOLABELWRAP;
|
||
|
|
||
|
hwndList = CreateWindowExW(WS_EX_NOPARENTNOTIFY, WC_LISTVIEWW,L"",style,0, 20, rc.right - rc.left, rc.bottom - rc.top - 20, hwnd,(HMENU)2,0,0);
|
||
|
if (NULL != hwndList)
|
||
|
{
|
||
|
ListViewData *listView;
|
||
|
listView = (ListViewData*)calloc(1, sizeof(ListViewData));
|
||
|
if (NULL != listView)
|
||
|
{
|
||
|
listView->prevWindowProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwndList, GWLP_WNDPROC, (LONGX86)(LONG_PTR)ListView_WindowProc);
|
||
|
SetWindowLongPtrW(hwndList,GWLP_USERDATA, (LONGX86)(LONG_PTR)listView);
|
||
|
}
|
||
|
|
||
|
SendMessageW(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_INFOTIP, LVS_EX_INFOTIP);
|
||
|
|
||
|
if (NULL != hwndHeader)
|
||
|
SetWindowPos(hwndHeader, hwndList, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||
|
|
||
|
m.skinType = SKINNEDWND_TYPE_LISTVIEW;
|
||
|
m.hwndToSkin = hwndList;
|
||
|
m.style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWLVS_FULLROWSELECT | SWLVS_DOUBLEBUFFER;
|
||
|
MLSkinWindow(g_hwnd, &m);
|
||
|
MLSkinnedScrollWnd_SetMode(hwndList, SCROLLMODE_STANDARD);
|
||
|
MLSkinnedScrollWnd_ShowHorzBar(hwndList, FALSE);
|
||
|
MLSkinnedScrollWnd_ShowVertBar(hwndList, FALSE);
|
||
|
}
|
||
|
|
||
|
UpdateFontMetrics(hwnd, FALSE);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
HeaderIconList_OnDestroy(HWND hwnd)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// TODO need to finish off the butting up to edge handling
|
||
|
static void
|
||
|
HeaderIconList_OnWindowPosChanged(HWND hwnd, WINDOWPOS *windowPos)
|
||
|
{
|
||
|
RECT rc;
|
||
|
HWND hwndHeader, hwndList;
|
||
|
hwndHeader = GetDlgItem(hwnd, 3);
|
||
|
hwndList = GetDlgItem(hwnd, 2);
|
||
|
BOOL bRedraw;
|
||
|
|
||
|
bRedraw = (0 == (SWP_NOREDRAW & windowPos->flags));
|
||
|
|
||
|
if ((SWP_NOSIZE | SWP_NOMOVE) == ((SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED) & windowPos->flags))
|
||
|
return;
|
||
|
|
||
|
hwndHeader = GetDlgItem(hwnd, 3);
|
||
|
hwndList = GetDlgItem(hwnd, 2);
|
||
|
if (hwndHeader && hwndList)
|
||
|
{
|
||
|
HDLAYOUT headerLayout;
|
||
|
WINDOWPOS headerPos;
|
||
|
|
||
|
GetClientRect(hwnd, &rc);
|
||
|
|
||
|
/*SCROLLINFO si;
|
||
|
si.cbSize= sizeof(SCROLLINFO);
|
||
|
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
|
||
|
BOOL got = GetScrollInfo(hwnd, SB_VERT, &si);
|
||
|
BOOL bScrollVisible = (si.nMax > 0 && si.nPage > 0 && (INT)si.nPage <= si.nMax);*/
|
||
|
|
||
|
headerLayout.prc = &rc;
|
||
|
headerLayout.pwpos = &headerPos;
|
||
|
|
||
|
if (FALSE != SendMessageW(hwndHeader, HDM_LAYOUT, 0, (LPARAM)&headerLayout))
|
||
|
{
|
||
|
headerPos.flags |= ((SWP_NOREDRAW | SWP_NOCOPYBITS) & windowPos->flags);
|
||
|
SetWindowPos(hwndHeader, headerPos.hwndInsertAfter, headerPos.x, headerPos.y,
|
||
|
headerPos.cx, headerPos.cy, headerPos.flags);
|
||
|
}
|
||
|
|
||
|
SetWindowPos(hwndList, NULL, rc.left, rc.top, rc.right - rc.left/* + (bScrollVisible ? 16 : 0)*/, rc.bottom - rc.top,
|
||
|
SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
|
||
|
|
||
|
UpdateScrollInfo(hwnd, SIF_RANGE | SIF_POS, bRedraw);
|
||
|
}
|
||
|
|
||
|
NMHDR hdr;
|
||
|
hdr.code = LVN_EX_SIZECHANGED;
|
||
|
hdr.hwndFrom = hwnd;
|
||
|
hdr.idFrom = GetWindowLongPtrW(hwnd,GWLP_ID);
|
||
|
SendMessageW(GetParent(hwnd), WM_NOTIFY, hdr.idFrom, (LPARAM)&hdr);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
HeaderIconList_OnVertScroll(HWND hwnd, INT actionLayout, INT trackPosition, HWND scrollBar)
|
||
|
{
|
||
|
SCROLLINFO si={sizeof(si),SIF_TRACKPOS | SIF_POS | SIF_RANGE | SIF_PAGE,0};
|
||
|
if (GetScrollInfo(hwnd,SB_VERT,&si))
|
||
|
{
|
||
|
int pos(0), itemHeight;
|
||
|
BOOL bRedraw(TRUE);
|
||
|
HWND hwndList;
|
||
|
|
||
|
hwndList = GetDlgItem(hwnd, 2);
|
||
|
if (!hwndList)
|
||
|
return;
|
||
|
|
||
|
itemHeight = HIWORD(SendMessageW(hwndList, LVM_GETITEMSPACING, 0, 0L));
|
||
|
|
||
|
if (si.nPos > (si.nMax - (INT)si.nPage))
|
||
|
si.nPos = si.nMax - si.nPage;
|
||
|
|
||
|
switch(actionLayout)
|
||
|
{
|
||
|
case SB_TOP: pos = si.nMin; break;
|
||
|
case SB_BOTTOM: pos = si.nMax; break;
|
||
|
case SB_LINEDOWN: pos = si.nPos + itemHeight/2; break;
|
||
|
case SB_LINEUP: pos = si.nPos - itemHeight/2; break;
|
||
|
case SB_PAGEDOWN: pos = si.nPos + si.nPage - (((INT)si.nPage > itemHeight && 0 == ((INT)si.nPage%itemHeight)) ? itemHeight : 0);break;
|
||
|
case SB_PAGEUP: pos = si.nPos - si.nPage - (((INT)si.nPage > itemHeight && 0 == ((INT)si.nPage%itemHeight)) ? itemHeight : 0);break;
|
||
|
case SB_THUMBPOSITION:
|
||
|
case SB_THUMBTRACK:
|
||
|
{
|
||
|
POINT pt;
|
||
|
if (!SendMessageW(hwndList, LVM_GETORIGIN, 0, (LPARAM)&pt))
|
||
|
return;
|
||
|
si.nPos = pt.y;
|
||
|
pos = si.nTrackPos;
|
||
|
bRedraw = FALSE;
|
||
|
}
|
||
|
break;
|
||
|
case SB_ENDSCROLL: MLSkinnedScrollWnd_UpdateBars(hwnd, TRUE); return;
|
||
|
default: pos = si.nPos;
|
||
|
}
|
||
|
|
||
|
if (pos < si.nMin) pos = si.nMin;
|
||
|
if (pos > (si.nMax - (INT)si.nPage)) pos = si.nMax - si.nPage;
|
||
|
if (pos != si.nPos)
|
||
|
{
|
||
|
BOOL br;
|
||
|
if (!bRedraw)
|
||
|
{
|
||
|
UpdateWindow(GetDlgItem(hwnd, 3));
|
||
|
UpdateWindow(hwnd);
|
||
|
SendMessageW(hwnd, WM_SETREDRAW, FALSE, 0L);
|
||
|
}
|
||
|
br = (BOOL)SendMessageW(hwndList, LVM_SCROLL, 0, pos - si.nPos);
|
||
|
if (!bRedraw) SendMessageW(hwnd, WM_SETREDRAW, TRUE, 0L);
|
||
|
if (br)
|
||
|
{
|
||
|
si.fMask = SIF_POS;
|
||
|
si.nPos = pos;
|
||
|
SetScrollInfo(hwnd, SB_VERT, &si, FALSE);
|
||
|
|
||
|
if (!bRedraw)
|
||
|
InvalidateRect(hwndList, NULL, TRUE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
HeaderIconList_OnSetFont(HWND hwnd, HFONT font, BOOL redraw)
|
||
|
{
|
||
|
if (0 == (SWS_USESKINFONT & MLSkinnedWnd_GetStyle(hwnd)))
|
||
|
{
|
||
|
HWND controlWindow;
|
||
|
|
||
|
controlWindow = GetDlgItem(hwnd,3);
|
||
|
if (NULL != controlWindow)
|
||
|
SendMessageW(controlWindow, WM_SETFONT, (WPARAM)font, MAKELPARAM(0, 0L));
|
||
|
|
||
|
controlWindow = GetDlgItem(hwnd,2);
|
||
|
if (NULL != controlWindow)
|
||
|
SendMessageW(controlWindow, WM_SETFONT, (WPARAM)font, MAKELPARAM(0, 0L));
|
||
|
|
||
|
UpdateFontMetrics(hwnd, redraw);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static LRESULT
|
||
|
HeaderIconList_OnGetFont(HWND hwnd)
|
||
|
{
|
||
|
HWND listWindow;
|
||
|
|
||
|
listWindow = GetDlgItem(hwnd, 2);
|
||
|
if (NULL != listWindow)
|
||
|
return SendMessageW(listWindow, WM_GETFONT, 0, 0L);
|
||
|
|
||
|
return DefWindowProcW(hwnd, WM_GETFONT, 0, 0L);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
HeaderIconList_OnSetRedraw(HWND hwnd, BOOL enableRedraw)
|
||
|
{
|
||
|
HWND childWindow;
|
||
|
|
||
|
DefWindowProcW(hwnd, WM_SETREDRAW, enableRedraw, 0L);
|
||
|
|
||
|
childWindow = GetDlgItem(hwnd, 3);
|
||
|
if (NULL != childWindow)
|
||
|
{
|
||
|
SendMessage(childWindow, WM_SETREDRAW, enableRedraw, 0L);
|
||
|
if (FALSE != enableRedraw)
|
||
|
InvalidateRect(childWindow, NULL, TRUE);
|
||
|
}
|
||
|
|
||
|
childWindow = GetDlgItem(hwnd, 2);
|
||
|
if (NULL != childWindow)
|
||
|
{
|
||
|
SendMessage(childWindow, WM_SETREDRAW, enableRedraw, 0L);
|
||
|
if (FALSE != enableRedraw)
|
||
|
InvalidateRect(childWindow, NULL, TRUE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
HeaderIconList_OnSkinUpdated(HWND hwnd, BOOL notifyChildren, BOOL redraw)
|
||
|
{
|
||
|
UpdateFontMetrics(hwnd, redraw);
|
||
|
}
|
||
|
|
||
|
static LRESULT
|
||
|
HeaderIconList_OnDisplaySort(HWND hwnd, int sortIndex, BOOL ascendingOrder)
|
||
|
{
|
||
|
HWND headerWindow;
|
||
|
|
||
|
headerWindow = GetDlgItem(hwnd, 3);
|
||
|
if (NULL == headerWindow)
|
||
|
return 0;
|
||
|
|
||
|
return SENDMLIPC(headerWindow, ML_IPC_SKINNEDHEADER_DISPLAYSORT, MAKEWPARAM(sortIndex, ascendingOrder));
|
||
|
}
|
||
|
|
||
|
static LRESULT
|
||
|
HeaderIconList_OnGetSort(HWND hwnd)
|
||
|
{
|
||
|
HWND headerWindow;
|
||
|
|
||
|
headerWindow = GetDlgItem(hwnd, 3);
|
||
|
if (NULL == headerWindow)
|
||
|
return 0;
|
||
|
|
||
|
return SENDMLIPC(headerWindow, ML_IPC_SKINNEDHEADER_GETSORT, 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
static LRESULT
|
||
|
HeaderIconList_OnMediaLibraryIPC(HWND hwnd, INT msg, INT_PTR param)
|
||
|
{
|
||
|
switch(msg)
|
||
|
{
|
||
|
case ML_IPC_SKINNEDWND_SKINUPDATED: HeaderIconList_OnSkinUpdated(hwnd, LOWORD(param), HIWORD(param)); break;
|
||
|
case ML_IPC_SKINNEDLISTVIEW_DISPLAYSORT: return HeaderIconList_OnDisplaySort(hwnd, LOWORD(param), HIWORD(param));
|
||
|
case ML_IPC_SKINNEDLISTVIEW_GETSORT: return HeaderIconList_OnGetSort(hwnd);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static LRESULT CALLBACK HeaderIconList(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||
|
switch(uMsg)
|
||
|
{
|
||
|
case WM_CREATE: return HeaderIconList_OnCreate(hwnd, (CREATESTRUCT*)lParam);
|
||
|
case WM_DESTROY: HeaderIconList_OnDestroy(hwnd); return 0;
|
||
|
case WM_WINDOWPOSCHANGED: HeaderIconList_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); return 0;
|
||
|
case WM_VSCROLL: HeaderIconList_OnVertScroll(hwnd, LOWORD(wParam), (short)HIWORD(wParam), (HWND)lParam); return 0;
|
||
|
case WM_ERASEBKGND: return 1;
|
||
|
case WM_SETFONT: HeaderIconList_OnSetFont(hwnd, (HFONT)wParam, LOWORD(lParam)); return 0;
|
||
|
case WM_GETFONT: return HeaderIconList_OnGetFont(hwnd);
|
||
|
case WM_SETREDRAW: HeaderIconList_OnSetRedraw(hwnd, (BOOL)wParam); return 0;
|
||
|
case WM_TIMER:
|
||
|
if (43 == wParam)
|
||
|
{
|
||
|
KillTimer(hwnd, 43);
|
||
|
PostMessageW(hwnd, WM_EX_UPDATESCROLLINFO, SIF_POS, FALSE);
|
||
|
PostMessageW(hwnd, WM_EX_UNLOCKREDRAW, IWF_CONTAINER | IWF_LISTVIEW | IWF_UPDATENOW, 0L);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_EX_UPDATESCROLLINFO:
|
||
|
return UpdateScrollInfo(hwnd, (UINT)wParam, (BOOL)lParam);
|
||
|
|
||
|
case WM_EX_UNLOCKREDRAW:
|
||
|
|
||
|
SendMessageW(hwnd, WM_SETREDRAW, TRUE, 0L);
|
||
|
if (IWF_CONTAINER & wParam) { InvalidateRect(hwnd, NULL, FALSE); if (IWF_UPDATENOW & wParam) UpdateWindow(hwnd); }
|
||
|
if (IWF_LISTVIEW & wParam)
|
||
|
{
|
||
|
HWND hwndList = GetDlgItem(hwnd, 2);
|
||
|
if(hwndList) { InvalidateRect(hwndList, NULL, TRUE); if (IWF_UPDATENOW & wParam) UpdateWindow(hwndList); }
|
||
|
}
|
||
|
if (IWF_HEADER & wParam)
|
||
|
{
|
||
|
HWND hwndHeader = GetDlgItem(hwnd, 3);
|
||
|
if(hwndHeader) { InvalidateRect(hwndHeader, NULL, TRUE); if (IWF_UPDATENOW & wParam) UpdateWindow(hwndHeader); }
|
||
|
}
|
||
|
break;
|
||
|
case LVM_GETHEADER:
|
||
|
return (LRESULT)GetDlgItem(hwnd,3);
|
||
|
case LVM_DELETECOLUMN:
|
||
|
{
|
||
|
HWND headerWindow;
|
||
|
headerWindow = GetDlgItem(hwnd,3);
|
||
|
if (NULL != headerWindow)
|
||
|
return SendMessageW(headerWindow, HDM_DELETEITEM, wParam, 0L);
|
||
|
}
|
||
|
return FALSE;
|
||
|
case LVM_GETCOLUMNWIDTH:
|
||
|
{
|
||
|
HWND headerWindow;
|
||
|
headerWindow = GetDlgItem(hwnd,3);
|
||
|
if (NULL != headerWindow)
|
||
|
{
|
||
|
HDITEMW headerItem;
|
||
|
headerItem.mask = HDI_WIDTH;
|
||
|
if (FALSE != SendMessageW(headerWindow, HDM_GETITEM, wParam, (LPARAM)&headerItem))
|
||
|
return headerItem.cxy;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
case LVM_INSERTCOLUMNA:
|
||
|
case LVM_INSERTCOLUMNW:
|
||
|
{
|
||
|
LVCOLUMNW *listColumn = (LVCOLUMNW*)lParam;
|
||
|
HDITEMW headerItem;
|
||
|
HWND headerWindow;
|
||
|
headerWindow = GetDlgItem(hwnd,3);
|
||
|
if (NULL == headerWindow)
|
||
|
return -1;
|
||
|
|
||
|
if (FALSE == CopyListColumnToHeaderItem(listColumn, &headerItem))
|
||
|
return -1;
|
||
|
|
||
|
if (0 == (HDI_FORMAT & headerItem.mask))
|
||
|
{
|
||
|
headerItem.mask |= HDI_FORMAT;
|
||
|
headerItem.fmt = HDF_LEFT;
|
||
|
}
|
||
|
|
||
|
return SendMessageW(headerWindow,
|
||
|
(LVM_INSERTCOLUMNW == uMsg) ? HDM_INSERTITEMW : HDM_INSERTITEMA,
|
||
|
wParam, (LPARAM)&headerItem);
|
||
|
}
|
||
|
break;
|
||
|
case LVM_SETITEMCOUNT:
|
||
|
{
|
||
|
HWND hwndList = GetDlgItem(hwnd, 2);
|
||
|
if (hwndList)
|
||
|
{
|
||
|
LRESULT lr = ListView_WindowProc(hwndList, uMsg, wParam, lParam);
|
||
|
UpdateScrollInfo(hwnd, SIF_RANGE | SIF_POS, TRUE);
|
||
|
return lr;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case LVM_GETCOLUMNW:
|
||
|
case LVM_GETCOLUMNA:
|
||
|
{
|
||
|
LVCOLUMNW *l = (LVCOLUMNW *)lParam;
|
||
|
HDITEMW h;
|
||
|
HWND headerWindow;
|
||
|
|
||
|
headerWindow = GetDlgItem(hwnd, 3);
|
||
|
if (NULL == headerWindow)
|
||
|
return FALSE;
|
||
|
|
||
|
if (FALSE == CopyListColumnToHeaderItem(l, &h))
|
||
|
return FALSE;
|
||
|
|
||
|
if(!SendMessageW(headerWindow,
|
||
|
(LVM_GETCOLUMNW == uMsg) ? HDM_GETITEMW : HDM_GETITEMA,
|
||
|
wParam,
|
||
|
(LPARAM)&h))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (FALSE == CopyHeaderItemToListColumn(&h, l))
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
|
||
|
case LVM_SETCOLUMNW:
|
||
|
case LVM_SETCOLUMNA:
|
||
|
{
|
||
|
LVCOLUMNW *l = (LVCOLUMNW *)lParam;
|
||
|
HDITEMW h;
|
||
|
HWND headerWindow;
|
||
|
|
||
|
headerWindow = GetDlgItem(hwnd, 3);
|
||
|
if (NULL == headerWindow)
|
||
|
return FALSE;
|
||
|
|
||
|
if (FALSE == CopyListColumnToHeaderItem(l, &h))
|
||
|
return FALSE;
|
||
|
|
||
|
if(!SendMessageW(headerWindow,
|
||
|
(LVM_SETCOLUMNW == uMsg) ? HDM_SETITEMW : HDM_SETITEMA,
|
||
|
wParam, (LPARAM)&h))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (FALSE == CopyHeaderItemToListColumn(&h, l))
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
case LVM_SETCOLUMNWIDTH:
|
||
|
{
|
||
|
HWND headerWindow;
|
||
|
HDITEMW headerItem;
|
||
|
|
||
|
headerWindow = GetDlgItem(hwnd, 3);
|
||
|
if (NULL == headerWindow)
|
||
|
return FALSE;
|
||
|
|
||
|
if (LVSCW_AUTOSIZE == lParam)
|
||
|
return FALSE;
|
||
|
|
||
|
if (LVSCW_AUTOSIZE_USEHEADER == lParam)
|
||
|
return FALSE;
|
||
|
|
||
|
headerItem.mask = HDI_WIDTH;
|
||
|
headerItem.cxy = (int)lParam;
|
||
|
|
||
|
return SendMessageW(headerWindow, HDM_SETITEMW, (WPARAM)wParam, (LPARAM)&headerItem);
|
||
|
}
|
||
|
break;
|
||
|
case WM_NOTIFY:
|
||
|
{
|
||
|
BOOL bPost(FALSE);
|
||
|
LPNMHDR l=(LPNMHDR)lParam;
|
||
|
if(l->idFrom == 2)
|
||
|
{
|
||
|
switch(l->code)
|
||
|
{
|
||
|
case LVN_ODFINDITEMA:
|
||
|
case LVN_ODFINDITEMW:
|
||
|
bPost = TRUE;
|
||
|
break;
|
||
|
case LVN_ODSTATECHANGED:
|
||
|
{
|
||
|
NMLVODSTATECHANGE *stateChange;
|
||
|
stateChange = (NMLVODSTATECHANGE*)lParam;
|
||
|
|
||
|
if (0 != (LVIS_SELECTED & (stateChange->uNewState ^ stateChange->uOldState)))
|
||
|
{
|
||
|
|
||
|
SendMessageW(hwnd, WM_SETREDRAW, FALSE, 0L);
|
||
|
ListView_ScheduleSelectionUpdate(l->hwndFrom, stateChange->iFrom,stateChange->iTo);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
l->idFrom = GetWindowLong(hwnd,GWL_ID);
|
||
|
l->hwndFrom = hwnd;
|
||
|
LRESULT lr = SendMessageW(GetParent(hwnd),uMsg,l->idFrom,lParam);
|
||
|
if (bPost)
|
||
|
{
|
||
|
UpdateWindow(GetDlgItem(hwnd, 3));
|
||
|
SendMessageW(hwnd, WM_SETREDRAW, FALSE, 0L);
|
||
|
PostMessageW(hwnd, WM_EX_UPDATESCROLLINFO, SIF_POS, TRUE);
|
||
|
PostMessageW(hwnd, WM_EX_UNLOCKREDRAW, IWF_CONTAINER | IWF_LISTVIEW, 0L);
|
||
|
}
|
||
|
return lr;
|
||
|
}
|
||
|
else if(l->idFrom == 3) {
|
||
|
switch(l->code) {
|
||
|
case HDN_ITEMCLICKA:
|
||
|
case HDN_ITEMCLICKW:
|
||
|
{
|
||
|
NMHEADER *nm = (NMHEADER*)lParam;
|
||
|
HWND hwndParent;
|
||
|
hwndParent = GetParent(hwnd);
|
||
|
if (hwndParent)
|
||
|
{
|
||
|
wParam = GetWindowLongPtrW(hwnd,GWLP_ID);
|
||
|
if(nm->iButton == 0) { // left click
|
||
|
NMLISTVIEW p = {{hwnd, wParam, LVN_COLUMNCLICK},-1,nm->iItem,0};
|
||
|
return SendMessageW(hwndParent,WM_NOTIFY,wParam,(LPARAM)&p);
|
||
|
} else if(nm->iButton == 1) { // right click
|
||
|
NMHDR p = {nm->hdr.hwndFrom,wParam,NM_RCLICK};
|
||
|
return SendMessageW(hwndParent,WM_NOTIFY,wParam,(LPARAM)&p);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
return SendMessageW(GetParent(hwnd),uMsg, wParam,lParam);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case WM_EX_GETREALLIST:
|
||
|
return (LRESULT)GetDlgItem(hwnd, 2);
|
||
|
case WM_EX_GETCOUNTPERPAGE:
|
||
|
{
|
||
|
HWND hwndList;
|
||
|
RECT rc;
|
||
|
hwndList = GetDlgItem(hwnd, 2);
|
||
|
if (hwndList)
|
||
|
{
|
||
|
GetClientRect(hwndList, &rc);
|
||
|
OffsetRect(&rc, -rc.left, -rc.top);
|
||
|
DWORD spacing = (DWORD)SendMessageW(hwndList, LVM_GETITEMSPACING, 0, 0L);
|
||
|
if (LOWORD(spacing) && HIWORD(spacing))
|
||
|
{
|
||
|
return (rc.right/LOWORD(spacing)) * (rc.bottom /HIWORD(spacing) + ((rc.bottom%HIWORD(spacing)) ? 1 : 0));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
|
||
|
case WM_ML_IPC:
|
||
|
return HeaderIconList_OnMediaLibraryIPC(hwnd, (INT)lParam, (INT_PTR)wParam);
|
||
|
|
||
|
default:
|
||
|
if(uMsg >= LVM_FIRST && uMsg < LVM_FIRST + 0x100)
|
||
|
{
|
||
|
HWND hwndList = GetDlgItem(hwnd,2);
|
||
|
if (hwndList) return ListView_WindowProc(hwndList, uMsg, wParam, lParam);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
return DefWindowProcW(hwnd,uMsg,wParam,lParam);
|
||
|
}
|
||
|
|
||
|
|
||
|
void InitHeaderIconList() {
|
||
|
WNDCLASSW wc = {0, };
|
||
|
|
||
|
if (GetClassInfoW(plugin.hDllInstance, L"HeaderIconList", &wc)) return;
|
||
|
wc.style = CS_DBLCLKS;
|
||
|
wc.lpfnWndProc = HeaderIconList;
|
||
|
wc.hInstance = plugin.hDllInstance;
|
||
|
wc.lpszClassName = L"HeaderIconList";
|
||
|
RegisterClassW(&wc);
|
||
|
}
|