#include #include #include "common.h" #include "listview.h" #include "layout.h" extern HFONT g_hfNormal; static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ListView::ListView(const HWND hWndParent, const HMENU hMenu, const DWORD dwStyle) { m_hWndParent = hWndParent; m_bHeader = !(dwStyle & LVS_NOCOLUMNHEADER); hWnd = require(CreateWindowEx( WS_EX_CLIENTEDGE, WC_LISTVIEW, L"", dwStyle|WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP|LVS_REPORT|LVS_SHOWSELALWAYS, 0, 0, 0, 0, m_hWndParent, hMenu, GetModuleHandle(NULL), this)); if (require(SetProp(hWnd, L"this", (HANDLE)this))) m_proc0 = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)::WndProc); ListView_SetExtendedListViewStyle(hWnd, LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER); SendMessage(hWnd, WM_SETFONT, (WPARAM)g_hfNormal, MAKELPARAM(FALSE, 0)); } /* Retrieve next matching list view item. */ bool ListView::FindNextItem(LVITEM* const lvi, const LPARAM lParam) { if ((lvi->iItem = ListView_GetNextItem(hWnd, lvi->iItem, lParam)) == -1) return false; return ListView_GetItem(hWnd, lvi); } /* Naively calculate height of list view. */ int ListView::Height(int bHeader) { if (bHeader == -1) bHeader = m_bHeader; const int cItem = ListView_GetItemCount(hWnd); return cItem? Dpi(bHeader? 27: 4)+cItem*Dpi(19): 0; } void ListView::ResizeColumns(int) {} void ListView::UpdateTheme(const BOOL bThemeActive) { const wchar_t* theme; WORD action; extern BOOL (*SetWindowTheme)(HWND, LPCWSTR, LPCWSTR); if (!SetWindowTheme) return; if (bThemeActive) { theme = L"Explorer"; action = UIS_SET; } else { theme = NULL; action = UIS_CLEAR; } /* Use modern "Explorer" theme. */ SetWindowTheme(hWnd, theme, NULL); /* Hide focus rectangles. */ SendMessage(hWnd, WM_UPDATEUISTATE, MAKEWPARAM(action, UISF_HIDEFOCUS), 0); } LRESULT CALLBACK ListView::WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam) { extern Dragger g_dragDlv; switch (uMsg) { case WM_NOTIFY: switch (((NMHDR*)lParam)->code) { case HDN_ENDTRACK: UpdateLayout(); return TRUE; } break; case WM_LBUTTONDOWN: case WM_NCLBUTTONDOWN: if (g_dragDlv.HandleDown()) return 0; break; } return CallWindowProc(m_proc0, hWnd, uMsg, wParam, lParam); } LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam) { ListView* const lv = (ListView*)GetProp(hWnd, L"this"); if (uMsg == WM_DESTROY) RemoveProp(hWnd, L"this"); return lv? lv->WndProc(hWnd, uMsg, wParam, lParam): FALSE; }