Ejemplo n.º 1
0
CCList::~CCList()
{
	WindowList_Remove(hCLWindowList, hTreeView);
	_ASSERT(GetWindowLongPtr(GetParent(hTreeView), GWLP_WNDPROC) == (LONG_PTR)ParentSubclassProc); // we won't allow anyone to change our WNDPROC. otherwise we're not sure that we're setting the right WNDPROC back
	SetWindowLongPtr(hTreeView, GWLP_WNDPROC, (LONG_PTR)OrigTreeViewProc);
	SetWindowLongPtr(GetParent(hTreeView), GWLP_WNDPROC, (LONG_PTR)OrigParentProc);
	CWndUserData(GetParent(hTreeView)).SetCList(nullptr);
}
Ejemplo n.º 2
0
CMsgTree::~CMsgTree()
{
	_ASSERT(GetWindowLongPtr(GetParent(hTreeView), GWLP_WNDPROC) == (LONG_PTR)ParentSubclassProc); // we won't allow anyone to change our WNDPROC. otherwise we're not sure that we're setting the right WNDPROC back
	SetWindowLongPtr(hTreeView, GWLP_WNDPROC, (GetWindowLongPtr(GetParent(hTreeView), GWLP_WNDPROC) == (LONG_PTR)ParentSubclassProc) ? (LONG_PTR)OrigTreeViewProc : (LONG_PTR)DefDlgProc); // yeah, if that crazy Help plugin substituted MY WndProc again, he won't get his WndProc back.. he-he >:)
	SetWindowLongPtr(GetParent(hTreeView), GWLP_WNDPROC, (LONG_PTR)OrigParentProc);
	CWndUserData(GetParent(hTreeView)).SetMsgTree(NULL);
	WindowList_Remove(hMTWindowList, hTreeView);
	ImageList_Destroy(hImageList);
}
Ejemplo n.º 3
0
CCList::CCList(HWND hTreeView) : 
	hTreeView(hTreeView), 
	ExtraImageList(nullptr)
{
	CWndUserData(GetParent(hTreeView)).SetCList(this);
	OrigTreeViewProc = (WNDPROC)SetWindowLongPtr(hTreeView, GWLP_WNDPROC, (LONG_PTR)ContactListSubclassProc);
	OrigParentProc = (WNDPROC)SetWindowLongPtr(GetParent(hTreeView), GWLP_WNDPROC, (LONG_PTR)ParentSubclassProc);
	TreeView_SetImageList(hTreeView, Clist_GetImageList(), TVSIL_NORMAL);
	WindowList_Add(hCLWindowList, hTreeView, NULL);
	TreeView_SetIndent(hTreeView, 5); // doesn't set it less than the initial value on my system, and i guess it's because of icons... but who knows - maybe it will work somewhere
}
Ejemplo n.º 4
0
CMsgTree::CMsgTree(HWND hTreeView) : MsgTreePage(g_MsgTreePage), hTreeView(hTreeView), hDragItem(NULL), hPrevDropTarget(NULL), UpdateLock(0)
{
	CWndUserData(GetParent(hTreeView)).SetMsgTree(this);
	OrigParentProc = (WNDPROC)SetWindowLongPtr(GetParent(hTreeView), GWLP_WNDPROC, (LONG_PTR)ParentSubclassProc);
	OrigTreeViewProc = (WNDPROC)SetWindowLongPtr(hTreeView, GWLP_WNDPROC, (LONG_PTR)MsgTreeSubclassProc);
	MsgTreePage.SetWnd(GetParent(hTreeView));
	COptItem_TreeCtrl* TreeCtrl = (COptItem_TreeCtrl*)MsgTreePage.Find(IDV_MSGTREE);
	TreeCtrl->SetDlgItemID(GetDlgCtrlID(hTreeView));
	hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 5, 2);
	ImageList_AddIcon(hImageList, LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_NEWMESSAGE)));
	ImageList_AddIcon(hImageList, LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_NEWCATEGORY)));
	ImageList_AddIcon(hImageList, LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_DELETE)));
	MsgTreePage.DBToMemToPage();
	if (!g_MoreOptPage.GetDBValueCopy(IDC_MOREOPTDLG_RECENTMSGSCOUNT)) // show "Recent messages" group only when RECENTMSGSCOUNT is not set to 0.
		TreeView_DeleteItem(hTreeView, TreeCtrl->RootItems[g_Messages_RecentRootID].hItem);

	WindowList_Add(hMTWindowList, hTreeView, NULL);
}
Ejemplo n.º 5
0
LRESULT CALLBACK ParentSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	CCList *dat = CWndUserData(hWnd).GetCList();
	switch (Msg) {
	case WM_NOTIFY:
		{
			LPNMHDR pnmh = (LPNMHDR)lParam;
			if (pnmh->hwndFrom == dat->hTreeView) {
				switch (pnmh->code) {
				case TVN_ITEMEXPANDED: // just set an appropriate group image
					{
						LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam;
						TVITEM tvItem;
						tvItem.hItem = pnmtv->itemNew.hItem;
						tvItem.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
						tvItem.iImage = tvItem.iSelectedImage = (pnmtv->itemNew.state & TVIS_EXPANDED) ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
						TreeView_SetItem(dat->hTreeView, &tvItem);
					}
					break;
				case TVN_SELCHANGED:
					{
						LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam;
						TREEITEMARRAY OldSelection = dat->SelectedItems;
						for (int i = 0; i < dat->SelectedItems.GetSize(); i++) {
							if (dat->SelectedItems[i] != pnmtv->itemNew.hItem) {
								TreeView_SetItemState(dat->hTreeView, dat->SelectedItems[i], 0, TVIS_SELECTED);
							}
						}
						dat->SelectedItems.RemoveAll();
						if (pnmtv->itemNew.hItem) {
							dat->SelectedItems.AddElem(pnmtv->itemNew.hItem);
							dat->SelectGroups(pnmtv->itemNew.hItem, true);
						}
						NMCLIST nm;
						nm.hdr.code = MCLN_SELCHANGED;
						nm.hdr.hwndFrom = dat->hTreeView;
						nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView);
						nm.OldSelection = &OldSelection;
						nm.NewSelection = &dat->SelectedItems;
						SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm);
					}
					break;

				case TVN_DELETEITEM:
					if (dat->Items.GetSize()) { // if Items size = 0, then this TVN_DELETEITEM came after WM_DESTROY, so there is no need to do anything
						LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam;
						TREEITEMARRAY OldSelection = dat->SelectedItems;
						int Index = dat->SelectedItems.Find(pnmtv->itemOld.hItem);
						if (Index != -1)
							dat->SelectedItems.RemoveElem(Index);

						// find an item to pass to SelectGroups()
						HTREEITEM hItem = TreeView_GetNextSibling(dat->hTreeView, pnmtv->itemOld.hItem);
						if (!hItem) {
							hItem = TreeView_GetPrevSibling(dat->hTreeView, pnmtv->itemOld.hItem);
							if (!hItem)
								hItem = TreeView_GetParent(dat->hTreeView, pnmtv->itemOld.hItem);
						}
						if (hItem) // if it wasn't one of the root items
							dat->SelectGroups(hItem, dat->SelectedItems.Find(hItem) != -1);

						NMCLIST nm;
						nm.hdr.code = MCLN_SELCHANGED;
						nm.hdr.hwndFrom = dat->hTreeView;
						nm.hdr.idFrom = GetDlgCtrlID(dat->hTreeView);
						nm.OldSelection = &OldSelection;
						nm.NewSelection = &dat->SelectedItems;
						SendMessage(hWnd, WM_NOTIFY, 0, (LPARAM)&nm);
						dat->Items[pnmtv->itemOld.lParam].hContact = INVALID_CONTACT_ID;
					}
					break;

				case NM_CUSTOMDRAW:
					LPNMTVCUSTOMDRAW lpNMCD = (LPNMTVCUSTOMDRAW)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;
						if (TreeView_GetItemRect(dat->hTreeView, (HTREEITEM)lpNMCD->nmcd.dwItemSpec, &rc, false)) {
							for (int i = 0; i < MAXEXTRAICONS; i++) {
								BYTE nIndex = dat->Items[lpNMCD->nmcd.lItemlParam].ExtraIcons[i];
								if (nIndex != CLC_EXTRAICON_EMPTY) {
									ImageList_DrawEx(dat->ExtraImageList, nIndex, lpNMCD->nmcd.hdc, rc.right - EXTRAICON_XSTEP * (i + 1), rc.top, 0, 0, /*GetSysColor(COLOR_WINDOW)*/CLR_NONE, CLR_NONE, ILD_NORMAL);
								}
							}
						}
						break;
					}
				}
				break;
			}
		}
	}
	return CallWindowProc(dat->OrigParentProc, hWnd, Msg, wParam, lParam);
}
Ejemplo n.º 6
0
LRESULT CALLBACK ContactListSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	TVITEM tvi;
	CCList *dat = CWndUserData(GetParent(hWnd)).GetCList();

	switch (Msg) {
	case INTM_CONTACTDELETED: // wParam = (HANDLE)hContact
		{
			HTREEITEM hItem = dat->FindContact(wParam);
			if (hItem)
				TreeView_DeleteItem(hWnd, hItem);
		}
		break;

	case INTM_ICONCHANGED: // wParam = (HANDLE)hContact, lParam = IconID
		tvi.hItem = dat->FindContact(wParam);
		if (tvi.hItem) {
			tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
			tvi.iImage = tvi.iSelectedImage = lParam;
			TreeView_SetItem(hWnd, &tvi);
			dat->SortContacts();
			InvalidateRect(hWnd, nullptr, false);
		}
		break;

	case INTM_INVALIDATE:
		InvalidateRect(hWnd, nullptr, true);
		break;

	case WM_RBUTTONDOWN:
		SetFocus(hWnd);
		{
			TVHITTESTINFO hitTest;
			hitTest.pt.x = (short)LOWORD(lParam);
			hitTest.pt.y = (short)HIWORD(lParam);
			TreeView_HitTest(hWnd, &hitTest);
			if (hitTest.hItem && hitTest.flags & TVHT_ONITEM)
				TreeView_SelectItem(hWnd, hitTest.hItem);
		}
		return DefWindowProc(hWnd, Msg, wParam, lParam);

	case WM_LBUTTONDOWN:
		{
			POINT pt = { (short)LOWORD(lParam), (short)HIWORD(lParam) };
			DWORD hitFlags;
			HTREEITEM hItem = dat->HitTest(&pt, &hitFlags);
			if (!hItem)
				break;

			if (hitFlags & MCLCHT_ONITEMICON) {
				if (TreeView_GetChild(hWnd, hItem)) { // if it's a group, then toggle its state
					NMTREEVIEW nmtv;
					nmtv.hdr.hwndFrom = hWnd;
					nmtv.hdr.idFrom = GetDlgCtrlID(hWnd);
					nmtv.hdr.code = TVN_ITEMEXPANDING;
					nmtv.action = TVE_TOGGLE;
					nmtv.itemNew.hItem = hItem;
					nmtv.itemNew.mask = TVIF_HANDLE | TVIF_STATE | TVIF_PARAM;
					TreeView_GetItem(hWnd, &nmtv.itemNew);
					nmtv.ptDrag = pt;
					if (SendMessage(GetParent(hWnd), WM_NOTIFY, 0, (LPARAM)&nmtv))
						return 0;

					HTREEITEM hOldSelItem = TreeView_GetSelection(hWnd);
					TreeView_Expand(hWnd, hItem, TVE_TOGGLE);
					HTREEITEM hNewSelItem = TreeView_GetSelection(hWnd);
					if (hNewSelItem != hOldSelItem) {
						TreeView_SetItemState(hWnd, hOldSelItem, (dat->SelectedItems.Find(hOldSelItem) == -1) ? 0 : TVIS_SELECTED, TVIS_SELECTED);
						TreeView_SetItemState(hWnd, hNewSelItem, (dat->SelectedItems.Find(hNewSelItem) == -1) ? 0 : TVIS_SELECTED, TVIS_SELECTED);
					}
					nmtv.hdr.code = TVN_ITEMEXPANDED;
					TreeView_GetItem(hWnd, &nmtv.itemNew);
					SendMessage(GetParent(hWnd), WM_NOTIFY, 0, (LPARAM)&nmtv);
					return 0;
				}
			}
			if (hitFlags & MCLCHT_ONITEM) {
				if (wParam & MK_CONTROL) {
					SetFocus(hWnd);
					TREEITEMARRAY OldSelection = dat->SelectedItems;
					int nIndex = dat->SelectedItems.Find(hItem);
					if (nIndex == -1) {
						TreeView_SetItemState(hWnd, hItem, TVIS_SELECTED, TVIS_SELECTED);
						dat->SelectedItems.AddElem(hItem);
					}
					else {
						TreeView_SetItemState(hWnd, hItem, 0, TVIS_SELECTED);
						dat->SelectedItems.RemoveElem(nIndex);
					}
					dat->SelectGroups(hItem, nIndex == -1);
					NMCLIST nm;
					nm.hdr.code = MCLN_SELCHANGED;
					nm.hdr.hwndFrom = hWnd;
					nm.hdr.idFrom = GetDlgCtrlID(hWnd);
					nm.OldSelection = &OldSelection;
					nm.NewSelection = &dat->SelectedItems;
					SendMessage(GetParent(hWnd), WM_NOTIFY, 0, (LPARAM)&nm);
					return 0;
				}
				// if it was a click on the selected item and there's need to do something in this case, then send SELCHANGED notification by ourselves, as the tree control doesn't do anything
				if (hItem == TreeView_GetSelection(hWnd) && (dat->SelectedItems.GetSize() != 1 || (dat->SelectedItems.GetSize() == 1 && dat->SelectedItems[0] != hItem))) {
					TreeView_SetItemState(hWnd, hItem, TVIS_SELECTED, TVIS_SELECTED);
					NMTREEVIEW nm = {};
					nm.hdr.code = TVN_SELCHANGED;
					nm.hdr.hwndFrom = hWnd;
					nm.hdr.idFrom = GetDlgCtrlID(hWnd);
					nm.itemOld.hItem = TreeView_GetSelection(hWnd);
					nm.itemOld.mask = TVIF_HANDLE | TVIF_STATE | TVIF_PARAM;
					TreeView_GetItem(hWnd, &nm.itemOld);
					nm.itemNew = nm.itemOld;
					SendMessage(GetParent(hWnd), WM_NOTIFY, 0, (LPARAM)&nm);
				}
			}
		}
		break;

	case WM_SETFOCUS:
	case WM_KILLFOCUS:
		for (int i = 0; i < dat->SelectedItems.GetSize(); i++) {
			RECT rc;
			if (TreeView_GetItemRect(hWnd, dat->SelectedItems[i], &rc, false))
				InvalidateRect(hWnd, &rc, false);
		}
		break;

	case WM_SIZE:
	case WM_HSCROLL:
		InvalidateRect(hWnd, nullptr, false);
		break;

	case WM_MEASUREITEM:
		if (!wParam) // if the message was sent by a menu
			return Menu_MeasureItem(lParam);
		break;

	case WM_DRAWITEM:
		if (!wParam) // if the message was sent by a menu
			return Menu_DrawItem(lParam);
		break;

	case WM_CONTEXTMENU:
		{
			POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
			HTREEITEM hItem = nullptr;
			if (pt.x == -1 && pt.y == -1) {
				if (dat->SelectedItems.GetSize() == 1) {
					hItem = dat->SelectedItems[0];
					TreeView_EnsureVisible(hWnd, hItem);
					RECT rc;
					TreeView_GetItemRect(hWnd, hItem, &rc, true);
					pt.x = rc.left;
					pt.y = rc.bottom;
				}
			}
			else {
				DWORD hitFlags;
				ScreenToClient(hWnd, &pt);
				hItem = dat->HitTest(&pt, &hitFlags);
				if (!(hitFlags & MCLCHT_ONITEM))
					hItem = nullptr;
			}
			if (hItem) {
				MCONTACT hContact = dat->GetItemData(hItem).hContact;
				if (IsHContactContact(hContact)) {
					HMENU hMenu = Menu_BuildContactMenu(hContact);
					if (hMenu) {
						ClientToScreen(hWnd, &pt);
						Clist_MenuProcessCommand(TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, 0, hWnd, nullptr), MPCF_CONTACTMENU, hContact);
						DestroyMenu(hMenu);
						return 0;
					}
				}
			}
		}
		break;

	case WM_DESTROY:
		if (dat->ExtraImageList)
			ImageList_Destroy(dat->ExtraImageList);
		dat->SelectedItems.RemoveAll();
		dat->Items.RemoveAll();
		break;
	}
	return CallWindowProc(dat->OrigTreeViewProc, hWnd, Msg, wParam, lParam);
}
Ejemplo n.º 7
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);
}
Ejemplo n.º 8
0
static LRESULT CALLBACK MsgTreeSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	CMsgTree *dat = CWndUserData(GetParent(hWnd)).GetMsgTree();
	switch (Msg) {
	case UM_MSGTREE_UPDATE: // returns TRUE if updated
		{
			bool Modified = dat->MsgTreePage.GetModified();
			TCString WndTitle;
			if (Modified) {
				WndTitle.GetBuffer(256);
				HWND hCurWnd = hWnd;
				do {
					hCurWnd = GetParent(hCurWnd);
				} while (hCurWnd && !GetWindowText(hCurWnd, WndTitle, 256));
				WndTitle.ReleaseBuffer();
			}
			if (!Modified || MessageBox(GetParent(hWnd), TCString(TranslateT("You've made changes to multiple message trees at a time.\r\nDo you want to leave changes in \"")) + WndTitle + TranslateT("\" dialog?\r\nPress Yes to leave changes in this dialog, or No to discard its changes and save changes of the other message tree instead."), WndTitle + _T(" - ") + TranslateT("New Away System"), MB_ICONQUESTION | MB_YESNO) == IDNO) {
				COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl();
				TCString OldTitle, OldMsg, NewTitle, NewMsg;
				int OldOrder = TreeCtrl->IDToOrder(TreeCtrl->GetSelectedItemID(GetParent(hWnd)));
				if (OldOrder != -1) {
					CBaseTreeItem* ItemOld = (OldOrder <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(OldOrder)] : (CBaseTreeItem*)&TreeCtrl->Value[OldOrder];
					OldTitle = ItemOld->Title;
					if (!(ItemOld->Flags & TIF_ROOTITEM))
						OldMsg = ((CTreeItem*)ItemOld)->User_Str1;
				}
				dat->UpdateLock++;
				dat->MsgTreePage.DBToMemToPage();
				dat->UpdateLock--;
				NMMSGTREE nm = { 0 };
				int Order = TreeCtrl->IDToOrder(TreeCtrl->GetSelectedItemID(GetParent(hWnd)));
				if (Order != -1) {
					nm.ItemNew = (Order <= TREECTRL_ROOTORDEROFFS) ? (CBaseTreeItem*)&TreeCtrl->RootItems[ROOT_ORDER_TO_INDEX(Order)] : (CBaseTreeItem*)&TreeCtrl->Value[Order];
					NewTitle = nm.ItemNew->Title;
					if (!(nm.ItemNew->Flags & TIF_ROOTITEM))
						NewMsg = ((CTreeItem*)nm.ItemNew)->User_Str1;
				}
				if (OldTitle.IsEmpty())
					OldTitle = _T(""); // to be sure that NULL will be equal to "" in the latter comparisons
				if (OldMsg.IsEmpty())
					OldMsg = _T("");
				if (NewTitle.IsEmpty())
					NewTitle = _T("");
				if (NewMsg.IsEmpty())
					NewMsg = _T("");

				if (OldTitle != (const TCHAR*)NewTitle || OldMsg != (const TCHAR*)NewMsg) {
					// probably it's better to leave nm.ItemOld = NULL, to prevent accidental rewriting of it with old data from an edit control etc.
					nm.hdr.code = MTN_SELCHANGED;
					nm.hdr.hwndFrom = hWnd;
					nm.hdr.idFrom = GetDlgCtrlID(hWnd);
					SendMessage(GetParent(hWnd), WM_NOTIFY, 0, (LPARAM)&nm);
				}
				return true;
			}
		}
		return false;

	case WM_KEYDOWN:
		switch (wParam) {
		case VK_DELETE:
			dat->DeleteSelectedItem();
			break;
		case VK_INSERT:
			dat->AddMessage();
			break;
		}
		break;

	case WM_RBUTTONDOWN:
		SetFocus(hWnd);
		{
			TVHITTESTINFO hitTest;
			hitTest.pt.x = (short)LOWORD(lParam);
			hitTest.pt.y = (short)HIWORD(lParam);
			TreeView_HitTest(hWnd, &hitTest);
			if (hitTest.hItem && hitTest.flags & TVHT_ONITEM)
				TreeView_SelectItem(hWnd, hitTest.hItem);

			return DefWindowProc(hWnd, Msg, wParam, lParam);
		}
		break;

	case WM_CONTEXTMENU:
		{
			TVHITTESTINFO ht;
			ht.pt.x = GET_X_LPARAM(lParam);
			ht.pt.y = GET_Y_LPARAM(lParam);
			TVITEM tvi = { 0 };
			if (ht.pt.x == -1 && ht.pt.y == -1) { // use selected item 
				if (tvi.hItem = TreeView_GetSelection(hWnd)) {
					TreeView_EnsureVisible(hWnd, tvi.hItem);
					RECT rc;
					TreeView_GetItemRect(hWnd, tvi.hItem, &rc, true);
					ht.pt.x = rc.left;
					ht.pt.y = rc.bottom;
				}
			}
			else {
				ScreenToClient(hWnd, &ht.pt);
				TreeView_HitTest(hWnd, &ht);
				if (ht.hItem && ht.flags & TVHT_ONITEM) {
					tvi.hItem = ht.hItem;
				}
			}
			if (tvi.hItem) {
				COptItem_TreeCtrl *TreeCtrl = dat->GetTreeCtrl();
				tvi.mask = TVIF_HANDLE | TVIF_PARAM;
				TreeView_GetItem(hWnd, &tvi);
				int Order = TreeCtrl->IDToOrder(tvi.lParam);
				if (Order >= 0) {
					HMENU hMenu;
					if (TreeCtrl->Value[Order].Flags & TIF_GROUP)
						hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_MSGTREE_CATEGORYMENU));
					else
						hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_MSGTREE_MESSAGEMENU));

					_ASSERT(hMenu);
					HMENU hPopupMenu = GetSubMenu(hMenu, 0);
					TranslateMenu(hPopupMenu);
					ClientToScreen(hWnd, &ht.pt);
					struct
					{
						int ItemID, IconID;
					}
					MenuItems[] = {
						IDM_MSGTREEMENU_NEWMESSAGE, IMGLIST_NEWMESSAGE,
						IDM_MSGTREEMENU_NEWCATEGORY, IMGLIST_NEWCATEGORY,
						IDM_MSGTREEMENU_DELETE, IMGLIST_DELETE
					};
					MENUITEMINFO mii = { 0 };
					mii.cbSize = sizeof(mii);
					mii.fMask = MIIM_BITMAP | MIIM_DATA | MIIM_STATE | MIIM_CHECKMARKS;
					mii.hbmpItem = HBMMENU_CALLBACK;
					int i;
					for (i = 0; i < _countof(MenuItems); i++) { // set icons
						mii.dwItemData = MenuItems[i].IconID;
						SetMenuItemInfo(hPopupMenu, MenuItems[i].ItemID, false, &mii);
					}
					mii.fMask = MIIM_STATE;
					mii.fState = MFS_CHECKED;
					for (i = 0; i < _countof(SettingsList); i++) // set checkmarks
						if (TreeCtrl->Value[Order].ID == dat->MsgTreePage.GetValue(SettingsList[i].DBSetting))
							SetMenuItemInfo(hPopupMenu, SettingsList[i].MenuItemID, false, &mii);

					int MenuResult = TrackPopupMenu(hPopupMenu, TPM_RIGHTBUTTON | TPM_RETURNCMD, ht.pt.x, ht.pt.y, 0, hWnd, NULL);
					switch (MenuResult) {
					case IDM_MSGTREEMENU_NEWMESSAGE:
						dat->AddMessage();
						break;
					case IDM_MSGTREEMENU_NEWCATEGORY:
						dat->AddCategory();
						break;
					case IDM_MSGTREEMENU_RENAME:
						TreeView_EditLabel(hWnd, tvi.hItem);
						break;
					case IDM_MSGTREEMENU_DELETE:
						dat->DeleteSelectedItem();
						break;
					case IDR_MSGTREEMENU_DEF_ONL:
					case IDR_MSGTREEMENU_DEF_AWAY:
					case IDR_MSGTREEMENU_DEF_NA:
					case IDR_MSGTREEMENU_DEF_OCC:
					case IDR_MSGTREEMENU_DEF_DND:
					case IDR_MSGTREEMENU_DEF_FFC:
					case IDR_MSGTREEMENU_DEF_INV:
					case IDR_MSGTREEMENU_DEF_OTP:
					case IDR_MSGTREEMENU_DEF_OTL:
						for (int i = 0; i < _countof(SettingsList); i++) {
							if (SettingsList[i].MenuItemID == MenuResult) {
								dat->SetDefMsg(SettingsList[i].Status, tvi.lParam);
								break;
							}
						}
					}
					DestroyMenu(hMenu);
					return 0;
				}
			}
		}
		break;

	case WM_MEASUREITEM:
		{
			LPMEASUREITEMSTRUCT lpmi = (LPMEASUREITEMSTRUCT)lParam;
			if (lpmi->CtlType == ODT_MENU) {
				lpmi->itemWidth = max(0, GetSystemMetrics(SM_CXSMICON) - GetSystemMetrics(SM_CXMENUCHECK) + 4);
				lpmi->itemHeight = GetSystemMetrics(SM_CYSMICON) + 2;
				return true;
			}
		}
		break;
	
	case WM_DRAWITEM:
		{
			LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
			if (dis->CtlType == ODT_MENU) {
				ImageList_DrawEx(dat->hImageList, dis->itemData, dis->hDC, 2, (dis->rcItem.bottom + dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2 + 1, 0, 0, GetSysColor(COLOR_WINDOW), CLR_NONE, ILD_NORMAL);
				return true;
			}
		} 
		break;
	}
	return CallWindowProc(dat->OrigTreeViewProc, hWnd, Msg, wParam, lParam);
}