Пример #1
0
CBaseTreeItem* CMsgTree::GetNextItem(int Flags, CBaseTreeItem* Item) // Item is 'int ID' if MTGN_BYID flag is set; returns CBaseTreeItem* or NULL
{
	COptItem_TreeCtrl *TreeCtrl = GetTreeCtrl();
	CBaseTreeItem* TreeItem = Item;
	if (Flags & MTGN_BYID) {
		int Order = TreeCtrl->IDToOrder((int)Item);
		_ASSERT(Order != -1);
		TreeItem = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
	}

	int TVFlag = 0;
	switch (Flags & ~MTGN_BYID) {
		case MTGN_ROOT: TVFlag = TVGN_ROOT; break;
		case MTGN_CHILD: TVFlag = TVGN_CHILD; break;
		case MTGN_PARENT: TVFlag = TVGN_PARENT; break;
		case MTGN_NEXT: TVFlag = TVGN_NEXT; break;
		case MTGN_PREV: TVFlag = TVGN_PREVIOUS; break;
		default: _ASSERT(0);
	}
	int Order = TreeCtrl->hItemToOrder(TreeView_GetNextItem(hTreeView, TreeItem ? TreeItem->hItem : NULL, TVFlag));
	if (Order == -1)
		return NULL;

	return (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
}
Пример #2
0
static LRESULT CALLBACK ParentSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	CMsgTree *dat = CWndUserData(hWnd).GetMsgTree();
	switch (Msg) {
	case WM_NOTIFY:
		if (((LPNMHDR)lParam)->hwndFrom == dat->hTreeView) {
			switch (((LPNMHDR)lParam)->code) {
			case TVN_BEGINDRAG:
				{
					LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam;
					NMMSGTREE nm = { 0 };
					COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl();
					int Order = TreeCtrl->hItemToOrder(pnmtv->itemNew.hItem);
					_ASSERT(Order != -1);
					if (Order != -1) {
						nm.ItemOld = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
						nm.hdr.code = MTN_BEGINDRAG;
						nm.hdr.hwndFrom = dat->hTreeView;
						nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView);
						if (!SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm)) {
							SetCapture(hWnd);
							dat->hPrevDropTarget = dat->hDragItem = pnmtv->itemNew.hItem;
							SetFocus(dat->hTreeView);
							TreeView_SelectItem(dat->hTreeView, dat->hDragItem);
						}
					}
				}
				break;

			case TVN_SELCHANGED:
				if (dat->UpdateLock)
					return 0;
				else {
					LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam;
					NMMSGTREE nm = { 0 };
					COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl();
					if (pnmtv->itemOld.hItem) {
						int Order = TreeCtrl->IDToOrder(pnmtv->itemOld.lParam);
						if (Order != -1) {
							nm.ItemOld = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
						}
					}
					if (pnmtv->itemNew.hItem) {
						int Order = TreeCtrl->IDToOrder(pnmtv->itemNew.lParam);
						if (Order != -1) {
							nm.ItemNew = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
						}
					}
					nm.hdr.code = MTN_SELCHANGED;
					nm.hdr.hwndFrom = dat->hTreeView;
					nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView);
					SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm);
				}
				break;

			case TVN_BEGINLABELEDIT:
				if (dat->GetTreeCtrl()->IDToOrder(((LPNMTVDISPINFO)lParam)->item.lParam) < 0)
					return true; // cancel editing

				g_OrigEditProc = (WNDPROC)SetWindowLongPtr(TreeView_GetEditControl(dat->hTreeView), GWLP_WNDPROC, (LONG_PTR)EditSubclassProc);
				break;

			case TVN_ENDLABELEDIT:
				{
					LPNMTVDISPINFO ptvdi = (LPNMTVDISPINFO)lParam;
					if (ptvdi->item.pszText) {
						COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl();
						int Order = TreeCtrl->IDToOrder(ptvdi->item.lParam);
						if (Order >= 0) {
							TreeCtrl->Value[Order].Title = ptvdi->item.pszText;
							TreeCtrl->SetModified(true);
							NMMSGTREE nm = { 0 };
							nm.ItemNew = &TreeCtrl->Value[Order];
							nm.hdr.code = MTN_ITEMRENAMED;
							nm.hdr.hwndFrom = dat->hTreeView;
							nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView);
							SendMessage(GetParent(dat->hTreeView), WM_NOTIFY, 0, (LPARAM)&nm);
							return true; // commit new text
						}
					}
				}
				break;

			case NM_CLICK:
			case NM_RCLICK:
				{
					TVHITTESTINFO hitTest;
					hitTest.pt.x = (short)LOWORD(GetMessagePos());
					hitTest.pt.y = (short)HIWORD(GetMessagePos());
					ScreenToClient(dat->hTreeView, &hitTest.pt);
					TreeView_HitTest(dat->hTreeView, &hitTest);
					if (hitTest.hItem) {
						if (TreeView_GetSelection(dat->hTreeView) == hitTest.hItem) // make sure TVN_SELCHANGED notification is sent always, even if previous selected item was the same as new
							TreeView_SelectItem(dat->hTreeView, NULL);
						TreeView_SelectItem(dat->hTreeView, hitTest.hItem);
					}
				}
				break;

			case NM_CUSTOMDRAW:
				NMTVCUSTOMDRAW *lpNMCD = (NMTVCUSTOMDRAW*)lParam;
				switch (lpNMCD->nmcd.dwDrawStage) {
				case CDDS_PREPAINT: // the control is about to start painting
					return CDRF_NOTIFYITEMDRAW; // instruct the control to return information when it draws items
				case CDDS_ITEMPREPAINT:
					return CDRF_NOTIFYPOSTPAINT;
				case CDDS_ITEMPOSTPAINT:
					RECT rc;
					TreeView_GetItemRect(lpNMCD->nmcd.hdr.hwndFrom, (HTREEITEM)lpNMCD->nmcd.dwItemSpec, &rc, true);
					int iSize = GetSystemMetrics(SM_CXSMICON);
					int x = rc.left - iSize - 5;
					for (int i = 0; i < _countof(SettingsList); i++) {
						if (lpNMCD->nmcd.lItemlParam == dat->MsgTreePage.GetValue(SettingsList[i].DBSetting)) {
							DrawIconEx(lpNMCD->nmcd.hdc, x, rc.top, Skin_LoadProtoIcon(NULL, SettingsList[i].Status), iSize, iSize, 0, GetSysColorBrush(COLOR_WINDOW), DI_NORMAL);
							x -= iSize + 1;
						}
					}
				}
			}
		}
		break;

	case WM_MOUSEMOVE:
		if (dat->hDragItem) {
			TVHITTESTINFO hti;
			hti.pt.x = (short)LOWORD(lParam);
			hti.pt.y = (short)HIWORD(lParam);
			ClientToScreen(hWnd, &hti.pt);
			ScreenToClient(dat->hTreeView, &hti.pt);
			TreeView_HitTest(dat->hTreeView, &hti);
			if (hti.hItem) {
				TreeView_SelectDropTarget(dat->hTreeView, hti.hItem);
				SetTimer(hWnd, MSGTREE_TIMER_ID, MSGTREE_DRAGANDDROP_GROUPEXPANDTIME, NULL);
			}
			else {
				if (hti.flags & TVHT_ABOVE)
					SendMessage(dat->hTreeView, WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0);
				if (hti.flags & TVHT_BELOW)
					SendMessage(dat->hTreeView, WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0);

				TreeView_SelectDropTarget(dat->hTreeView, NULL);
				KillTimer(hWnd, MSGTREE_TIMER_ID);
			}
		}
		break;

	case WM_LBUTTONUP:
		if (dat->hDragItem) {
			TreeView_SelectDropTarget(dat->hTreeView, NULL);
			KillTimer(hWnd, MSGTREE_TIMER_ID);
			ReleaseCapture();
			TVHITTESTINFO hti;
			hti.pt.x = (short)LOWORD(lParam);
			hti.pt.y = (short)HIWORD(lParam);
			ClientToScreen(hWnd, &hti.pt);
			ScreenToClient(dat->hTreeView, &hti.pt);
			TreeView_HitTest(dat->hTreeView, &hti);
			if (hti.hItem && dat->hDragItem != hti.hItem) {
				NMMSGTREE nm = { 0 };
				COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl();
				int OrderOld = TreeCtrl->hItemToOrder(dat->hDragItem);
				int OrderNew = TreeCtrl->hItemToOrder(hti.hItem);
				_ASSERT(OrderOld != -1 && OrderNew != -1);
				nm.ItemOld = (OrderOld <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(OrderOld)] : (CBaseTreeItem*)&TreeCtrl->Value[OrderOld];
				nm.ItemNew = (OrderNew <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(OrderNew)] : (CBaseTreeItem*)&TreeCtrl->Value[OrderNew];
				nm.hdr.code = MTN_ENDDRAG;
				nm.hdr.hwndFrom = dat->hTreeView;
				nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView);
				if (!SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm)) {
					dat->UpdateLock++;
					dat->GetTreeCtrl()->MoveItem(hWnd, dat->hDragItem, hti.hItem);
					dat->UpdateLock--;
				}
			}
			dat->hDragItem = NULL;
		}
		break;

	case WM_TIMER:
		if (wParam == MSGTREE_TIMER_ID) {
			KillTimer(hWnd, MSGTREE_TIMER_ID);
			TVHITTESTINFO hti;
			hti.pt.x = (short)LOWORD(GetMessagePos());
			hti.pt.y = (short)HIWORD(GetMessagePos());
			ScreenToClient(dat->hTreeView, &hti.pt);
			TreeView_HitTest(dat->hTreeView, &hti);
			if (hti.hItem && dat->hDragItem != hti.hItem && TreeView_GetChild(dat->hTreeView, hti.hItem)) // target is a group and is not the same item that we're dragging
				TreeView_Expand(dat->hTreeView, hti.hItem, TVE_EXPAND);
		}
	}
	return CallWindowProc(dat->OrigParentProc, hWnd, Msg, wParam, lParam);
}