Создал TreeView с чекбоксами и заполнил его. Хочу по нажатию на чекбокс устанавливать галки в дочерних чекбоксах или если клик был по дочернему - то уставливать родительский (если все смежные установлены). Почти как 3 состояния, только проще. С помощью сабклассинга сделал и на клик мышки и на пробел перехват событий. С пробелом все отлично работает, а клик ведет себя не понятно: не после каждого клика вызывается моя функция анализа галок в WM_LBUTTONUP.
Код | // корректировка чекбоксов для родительских узлов в зависимости от состояния дочерних bool MyFunc_CorrectCheck(HWND hWndTV, HTREEITEM hItem) { HTREEITEM hItemFirst; int iCheckCount, iUnCheckCount;
hItemFirst = hItem; iCheckCount = iUnCheckCount = 0; if(hItem == NULL) return 1; do { if(TreeView_GetChild(hWndTV, hItem) != NULL) MyFunc_CorrectCheck(hWndTV, TreeView_GetChild(hWndTV, hItem)); if(TreeView_GetCheckState(hWndTV, hItem)) iCheckCount++; else iUnCheckCount++; } while((hItem = TreeView_GetNextItem(hWndTV, hItem, TVGN_NEXT)) != NULL); if(iCheckCount && !iUnCheckCount) {TreeView_SetCheckState(hWndTV, TreeView_GetParent(hWndTV, hItemFirst), 1);} else {TreeView_SetCheckState(hWndTV, TreeView_GetParent(hWndTV, hItemFirst), 0);}
return 0; }
// установка чекбоксов у всех элементов относительно узла "hItem": на одном уровне и глубже bool MyFunc_SetCheck(HWND hWndTV, HTREEITEM hItem, bool bState) { if(hItem == NULL) return 1; do { if(TreeView_GetChild(hWndTV, hItem) != NULL) MyFunc_SetCheck(hWndTV, TreeView_GetChild(hWndTV, hItem), bState); TreeView_SetCheckState(hWndTV, hItem, bState); } while((hItem = TreeView_GetNextItem(hWndTV, hItem, TVGN_NEXT)) != NULL);
return 0; }
// LRESULT CALLBACK MyFuncTVProc(HWND hWndTV, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_KEYDOWN: { if(wParam == VK_SPACE) { if(TreeView_GetSelection(hWndTV)) PostMessage(hWndTV, WM_KEYUP, wParam, lParam); } } break;
case WM_KEYUP: { if(wParam == VK_SPACE) { HTREEITEM hItem = TreeView_GetSelection(hWndTV); if(hItem) { if(TreeView_GetChild(hWndTV, hItem) != NULL) MyFunc_SetCheck(hWndTV, TreeView_GetChild(hWndTV, hItem), TreeView_GetCheckState(hWndTV, hItem)?1:0); MyFunc_CorrectCheck(hWndTV, TreeView_GetRoot(hWndTV)); } } } break;
case WM_LBUTTONDOWN: { TVHITTESTINFO hti; hti.pt.x = LOWORD(lParam); hti.pt.y = HIWORD(lParam); if(TreeView_HitTest(hWndTV, &hti) && hti.hItem && (hti.flags & TVHT_ONITEMSTATEICON)) { PostMessage(hWndTV, WM_LBUTTONUP, 0, lParam); TreeView_SelectItem(hWndTV, hti.hItem); } } break; case WM_LBUTTONUP: { TVHITTESTINFO hti; hti.pt.x = LOWORD(lParam); hti.pt.y = HIWORD(lParam); if(TreeView_HitTest(hWndTV, &hti) && hti.hItem && (hti.flags & TVHT_ONITEMSTATEICON)) { if(TreeView_GetChild(hWndTV, hti.hItem) != NULL) MyFunc_SetCheck(hWndTV, TreeView_GetChild(hWndTV, hti.hItem), TreeView_GetCheckState(hWndTV, hti.hItem)?1:0); MyFunc_CorrectCheck(hWndTV, TreeView_GetRoot(hWndTV)); } else TreeView_SelectItem(hWndTV, NULL); } break;
} return CallWindowProc(OldMyFuncTVProc, hWndTV, msg, wParam, lParam); }
|
|