123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- #include "./folderbrowser.h"
- #include "./folderbrowser_internal.h"
- #include "../nu/CGlobalAtom.h"
- static CGlobalAtom NAVMGR_FBLISTBOXW(L"FBLISTBOX");
- extern size_t FolderBrowser_GetListBoxColumn(HWND hwndList);
- static LRESULT CALLBACK FBListBox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- typedef struct _FBMULTISELECT
- {
- HWND hOwner;
- INT nStart;
- INT nTrack;
- POINTS ptStart;
- } FBMULTISELECT;
- static HWND g_hDragSource = NULL;
- static FBMULTISELECT g_MultiSelect = {NULL, };
- BOOL FolderBrowser_CustomizeListBox(HWND hwndListbox)
- {
- LONG_PTR oldProc = GetWindowLongPtrW(hwndListbox, GWLP_WNDPROC);
- if (!oldProc || !SetPropW(hwndListbox, NAVMGR_FBLISTBOXW, (HANDLE)oldProc)) return FALSE;
- SetWindowLongPtrW(hwndListbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)FBListBox_WindowProc);
- return TRUE;
- }
- static void ResetMultiSelect(FBMULTISELECT *pms)
- {
- pms->hOwner = NULL;
- pms->nTrack = -1;
- pms->nStart = -1;
- pms->ptStart.x = -1;
- pms->ptStart.y = -1;
- }
- static void EnsureFocused(HWND hwnd)
- {
- HWND hFocus = GetFocus();
- if (hwnd != hFocus)
- {
- SetFocus(hwnd);
- HWND hParent = GetParent(hwnd);
- if (NULL != hParent)
- SendMessageW(hParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), LBN_SETFOCUS), (LPARAM)hwnd);
- }
- }
- static void EmulateSelectionChanged(HWND hwnd, INT caretIndex, INT ctrlId)
- {
- HWND hParent = GetParent(hwnd);
- SendMessageW(hwnd, LB_SETCARETINDEX, (WPARAM)caretIndex, TRUE);
- if (NULL != hParent)
- SendMessageW(hParent, WM_COMMAND, MAKEWPARAM(ctrlId, LBN_SELCHANGE), (LPARAM)hwnd);
- }
- static BOOL FBListBox_OnLButtonDown(HWND hwnd, UINT uFlags, POINTS pts)
- {
- g_hDragSource = NULL;
- ResetMultiSelect(&g_MultiSelect);
- INT count = (INT)SendMessageW(hwnd, LB_GETCOUNT, 0, 0L);
- if (count > 0)
- {
- DWORD item = (DWORD)SendMessageW(hwnd, LB_ITEMFROMPOINT, 0, *((LPARAM*)&pts));
- if (HIWORD(item))
- {
- if (0 == (MK_SHIFT & uFlags))
- {
- EnsureFocused(hwnd);
- SendMessageW(hwnd, LB_SETSEL, FALSE, (LPARAM)-1);
- EmulateSelectionChanged(hwnd, (INT)SendMessageW(hwnd, LB_GETCARETINDEX, 0, 0L), GetDlgCtrlID(hwnd));
- }
- g_MultiSelect.hOwner = hwnd;
- g_MultiSelect.nStart = LOWORD(item);
- g_MultiSelect.nTrack = item;
- g_MultiSelect.ptStart = pts;
- SetCapture(hwnd);
- return TRUE;
- }
- item = LOWORD(item);
- INT sel = (INT)SendMessageW(hwnd, LB_GETSEL, item, 0L);
- if (sel > 0)
- {
- EnsureFocused(hwnd);
- g_hDragSource = hwnd;
- return TRUE;
- }
- RECT rc;
- if (SendMessageW(hwnd, LB_GETITEMRECT, (WPARAM)item, (LPARAM)&rc))
- {
- MEASUREITEMSTRUCT mis;
- ZeroMemory(&mis, sizeof(MEASUREITEMSTRUCT));
- mis.CtlID = GetDlgCtrlID(hwnd);
- mis.CtlType = ODT_LISTBOX;
- mis.itemID = item;
- mis.itemData = (DWORD)SendMessageW(hwnd, LB_GETITEMDATA, (WPARAM)item, 0L);
- if (SendMessageW(GetParent(hwnd), WM_MEASUREITEM, mis.CtlID, (LPARAM)&mis))
- {
- rc.right = rc.left + mis.itemWidth;
- POINT pt;
- POINTSTOPOINT(pt, pts);
- if (PtInRect(&rc, pt))
- {
- EnsureFocused(hwnd);
- if (0 == ((MK_CONTROL | MK_SHIFT) & uFlags)) SendMessageW(hwnd, LB_SETSEL, FALSE, (LPARAM)-1);
- if (MK_SHIFT & uFlags)
- {
- INT anchor = (INT)SendMessageW(hwnd, LB_GETANCHORINDEX, 0, 0L);
- INT start = (anchor < (INT)item) ? anchor : item;
- INT stop = (start == anchor) ? item : anchor;
- SendMessageW(hwnd, LB_SETSEL, FALSE, (LPARAM)-1);
- SendMessageW(hwnd, LB_SELITEMRANGEEX, (WPARAM)start, (LPARAM)stop);
- SendMessageW(hwnd, LB_SETANCHORINDEX, (WPARAM)anchor, 0L);
- }
- else
- {
- SendMessageW(hwnd, LB_SETSEL, (0 == (MK_CONTROL & uFlags) || 0 == sel), (LPARAM)item);
- }
- EmulateSelectionChanged(hwnd, item, mis.CtlID);
- return TRUE;
- }
- }
- }
- }
- else
- {
- EnsureFocused(hwnd);
- return TRUE;
- }
- return FALSE;
- }
- static BOOL FBListBox_OnLButtonUp(HWND hwnd, UINT uFlags, POINTS pts)
- {
- ResetMultiSelect(&g_MultiSelect);
- if (hwnd == GetCapture())
- ReleaseCapture();
- INT count = (INT)SendMessageW(hwnd, LB_GETCOUNT, 0, 0L);
- if (count > 0)
- {
- DWORD item = (DWORD)SendMessageW(hwnd, LB_ITEMFROMPOINT, 0, *((LPARAM*)&pts));
- if (HIWORD(item)) return FALSE;
- item = LOWORD(item);
- INT sel = (INT)SendMessageW(hwnd, LB_GETSEL, item, 0L);
- if (sel > 0 && hwnd == g_hDragSource)
- {
- if ((INT)SendMessageW(hwnd, LB_GETSELCOUNT, item, 0L) > 0)
- {
- SendMessageW(hwnd, LB_SETSEL, FALSE, (LPARAM)-1);
- SendMessageW(hwnd, LB_SETSEL, TRUE, (LPARAM)item);
- EmulateSelectionChanged(hwnd, item, GetDlgCtrlID(hwnd));
- }
- }
- }
- g_hDragSource = NULL;
- return FALSE;
- }
- static BOOL FBListBox_OnMouseMove(HWND hwnd, UINT uFlags, POINTS pts)
- {
- if (g_hDragSource == hwnd) return TRUE;
- if (g_MultiSelect.hOwner == hwnd)
- {
- RECT rc;
- if (GetClientRect(hwnd, &rc))
- pts.x = (SHORT)(rc.left + (rc.right - rc.left)/2);
- DWORD item = (DWORD)SendMessageW(hwnd, LB_ITEMFROMPOINT, 0, *((LPARAM*)&pts));
- BOOL bNotify = FALSE;
-
- if (item != g_MultiSelect.nTrack)
- {
- INT nCurrent = LOWORD(item);
- INT nTrack = LOWORD(g_MultiSelect.nTrack);
- if (abs(nCurrent - g_MultiSelect.nStart) < abs(nTrack - g_MultiSelect.nStart))
- {
- INT first = (nTrack < g_MultiSelect.nStart) ? g_MultiSelect.nStart : nTrack;
- INT last = (first == nTrack) ? g_MultiSelect.nStart : nTrack;
- LRESULT r = SendMessageW(hwnd, LB_SELITEMRANGEEX, (WPARAM)first, (LPARAM)last);
- if (!bNotify) bNotify = (LB_ERR != r);
- }
- if (nCurrent != g_MultiSelect.nStart)
- {
- INT first = (nCurrent > g_MultiSelect.nStart) ? g_MultiSelect.nStart : nCurrent;
- INT last = (first == nCurrent) ? g_MultiSelect.nStart : nCurrent;
- LRESULT r = SendMessageW(hwnd, LB_SELITEMRANGEEX, (WPARAM)first, (LPARAM)last);
- if (!bNotify) bNotify = (LB_ERR != r);
- }
- else if (0 == HIWORD(item))
- {
- LRESULT r = SendMessageW(hwnd, LB_SETSEL, TRUE, (LPARAM)nCurrent);
- if (!bNotify) bNotify = (LB_ERR != r);
- }
- g_MultiSelect.nTrack = (INT)item;
- }
- else if (0 != HIWORD(g_MultiSelect.nTrack) && 0 != HIWORD(item) &&
- LOWORD(item) == g_MultiSelect.nStart &&
- (INT)SendMessageW(hwnd, LB_GETSEL, (WPARAM)g_MultiSelect.nStart, 0L) > 0)
- {
- BOOL bReset = TRUE;
- if (1 == (INT)SendMessageW(hwnd, LB_GETCOUNT, 0, 0L))
- {
- RECT ri;
- if (LB_ERR != SendMessageW(hwnd, LB_GETITEMRECT, (WPARAM)g_MultiSelect.nStart, (LPARAM)&ri))
- {
- LONG t = (pts.y < g_MultiSelect.ptStart.y) ? pts.y : g_MultiSelect.ptStart.y;
- LONG b = (t != pts.y) ? pts.y : g_MultiSelect.ptStart.y;
- bReset = !(t < ri.bottom && b > ri.top);
- }
- }
- if (bReset)
- {
- LRESULT r = SendMessageW(hwnd, LB_SETSEL, FALSE, (LPARAM)g_MultiSelect.nStart);
- if (!bNotify) bNotify = (LB_ERR != r);
- }
- }
- if (bNotify)
- {
- HWND hParent = GetParent(hwnd);
- if (NULL != hParent)
- SendMessageW(hParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), LBN_SELCHANGE), (LPARAM)hwnd);
- }
- }
- return FALSE;
- }
- static BOOL FBListBox_OnMouseWheel(HWND hwnd, UINT vkCode, INT delta, POINTS pts)
- {
- if (MK_CONTROL == vkCode)
- {
- PostMessageW(GetParent(hwnd), WM_MOUSEWHEEL, MAKEWPARAM(vkCode, delta), MAKELPARAM(pts.x, pts.y));
- return TRUE;
- }
- return FALSE;
- }
- static BOOL FBListBox_OnKeyDown(HWND hwnd, UINT vkCode, UINT flags)
- {
- UINT uiState = 0;
- switch(vkCode)
- {
- case VK_CONTROL:
- case VK_SHIFT:
- return FALSE;
- case VK_MENU:
- uiState = (UINT)SendMessageW(hwnd, WM_QUERYUISTATE, 0, 0L);
- if (UISF_HIDEACCEL & uiState)
- SendMessageW(hwnd, WM_CHANGEUISTATE, MAKELONG(UIS_CLEAR, UISF_HIDEACCEL), 0L);
- return FALSE;
- }
- uiState = (UINT)SendMessageW(hwnd, WM_QUERYUISTATE, 0, 0L);
- if (UISF_HIDEFOCUS & uiState)
- {
- SendMessageW(hwnd, WM_CHANGEUISTATE, MAKELONG(UIS_CLEAR, UISF_HIDEFOCUS), 0L);
- }
- if (0 != (0x80000000 & GetAsyncKeyState(VK_CONTROL)))
- {
- switch(vkCode)
- {
- case VK_UP:
- case VK_DOWN:
- case VK_PRIOR:
- case VK_NEXT:
- case VK_END:
- case VK_HOME:
- {
- INT count = (INT)SendMessageW(hwnd, LB_GETCOUNT, 0, 0L);
- INT caret = (INT)SendMessageW(hwnd, LB_GETCARETINDEX, 0, 0L);
- INT caretNew = caret;
- INT page = 0;
- if (count > 0)
- {
- RECT rc;
- INT h = (INT)SendMessageW(hwnd, LB_GETITEMHEIGHT, 0, 0L);
- if (h != -1 && GetClientRect(hwnd, &rc))
- {
- page = (rc.bottom - rc.top)/(h) - 1;
- if (page < 1) page = 1;
- }
- }
- switch(vkCode)
- {
- case VK_UP: caretNew = caret - 1; break;
- case VK_DOWN: caretNew = caret + 1; break;
- case VK_PRIOR: caretNew = caret - page; break;
- case VK_NEXT: caretNew = caret + page; break;
- case VK_END: caretNew = count - 1; break;
- case VK_HOME: caretNew = 0; break;
- }
- if (caretNew < 0) caretNew = 0;
- if (caretNew >= count) caretNew = count - 1;
- if (caret != caretNew && -1 != caretNew)
- SendMessageW(hwnd, LB_SETCARETINDEX, (WPARAM)caretNew, FALSE);
- }
- return TRUE;
- case VK_SPACE:
- {
- INT caret = (INT)SendMessageW(hwnd, LB_GETCARETINDEX, 0, 0L);
- if (-1 != caret)
- {
- INT selected = (INT)SendMessageW(hwnd, LB_GETSEL, caret, 0L);
- SendMessageW(hwnd, LB_SETSEL, (0 == selected), (LPARAM)caret);
- HWND hParent = GetParent(hwnd);
- if (NULL != hParent)
- SendMessageW(hParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), LBN_SELCHANGE), (LPARAM)hwnd);
- }
- }
- return TRUE;
- }
- }
- return FALSE;
- }
- static BOOL FBListBox_OnNcHitTest(HWND hwnd, POINTS pts, LRESULT *pResult)
- {
- if (SIZER_OVERLAP_LEFT > 0 || SIZER_OVERLAP_RIGHT > 0)
- {
- RECT rw;
- if (GetWindowRect(hwnd, &rw))
- {
- if ((SIZER_OVERLAP_RIGHT > 0 && pts.x >= rw.left && pts.x <= (rw.left + SIZER_OVERLAP_RIGHT)) ||
- (SIZER_OVERLAP_LEFT > 0 && pts.x <= rw.right && pts.x >= (rw.right - SIZER_OVERLAP_LEFT)))
- {
- *pResult = HTTRANSPARENT;
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- static LRESULT CALLBACK FBListBox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- WNDPROC fnOriginalProc = (WNDPROC)GetPropW(hwnd, NAVMGR_FBLISTBOXW);
- if (!fnOriginalProc) return DefWindowProcW(hwnd, uMsg, wParam, lParam);
- switch(uMsg)
- {
- case WM_NCDESTROY:
- SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)fnOriginalProc);
- RemovePropW(hwnd, NAVMGR_FBLISTBOXW);
- return CallWindowProcW(fnOriginalProc, hwnd, uMsg, wParam, lParam);
- case WM_LBUTTONDOWN:
- if (FBListBox_OnLButtonDown(hwnd, (UINT)wParam, MAKEPOINTS(lParam))) return 0;
- break;
- case WM_LBUTTONUP:
- if (FBListBox_OnLButtonUp(hwnd, (UINT)wParam, MAKEPOINTS(lParam))) return 0;
- break;
- case WM_MOUSEWHEEL:
- if (FBListBox_OnMouseWheel(hwnd, GET_KEYSTATE_WPARAM(wParam), GET_WHEEL_DELTA_WPARAM(wParam), MAKEPOINTS(lParam))) return 0;
- break;
- case WM_MOUSEMOVE:
- if (FBListBox_OnMouseMove(hwnd, (UINT)wParam, MAKEPOINTS(lParam))) return 0;
- break;
- case WM_KEYDOWN:
- if (FBListBox_OnKeyDown(hwnd, (UINT)wParam, (UINT)lParam)) return 0;
- break;
- case WM_UPDATEUISTATE:
- InvalidateRect(hwnd, NULL, FALSE);
- break;
- case WM_NCHITTEST:
- {
- LRESULT lResult;
- if (FBListBox_OnNcHitTest(hwnd, MAKEPOINTS(lParam), &lResult))
- return lResult;
- }
- break;
- }
- return CallWindowProcW(fnOriginalProc, hwnd, uMsg, wParam, lParam);
- }
|