/* New Away System - plugin for Miranda IM Copyright (c) 2005-2007 Chervov Dmitry This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // Miranda's built-in CListControl is very slow and it has too limited functionality... 8( So I had to use my own control instead. #pragma once typedef TMyArray TREEITEMARRAY; typedef TREEITEMARRAY* PTREEITEMARRAY; #define CLC_EXTRAICON_EMPTY 0xFF #define CLC_ROOT TVI_ROOT #define MAXEXTRAICONS 16 class CCLItemData // internal CCList's class { public: CCLItemData(HANDLE hContact = INVALID_HANDLE_VALUE): hContact(hContact) {FillMemory(ExtraIcons, sizeof(ExtraIcons), CLC_EXTRAICON_EMPTY);}; BYTE ExtraIcons[MAXEXTRAICONS]; HANDLE hContact; LPARAM lParam; }; typedef TMyArray TREEITEMDATAARRAY; typedef TREEITEMDATAARRAY* PTREEITEMDATAARRAY; class CCList { public: CCList(HWND hTreeView); ~CCList(); HTREEITEM AddContact(HANDLE hContact); HTREEITEM AddGroup(TCString GroupName); HTREEITEM AddInfo(TCString Title, HTREEITEM hParent, HTREEITEM hInsertAfter, LPARAM lParam = NULL, HICON hIcon = NULL); void SetInfoIcon(HTREEITEM hItem, HICON hIcon); int GetExtraImage(HTREEITEM hItem, int iColumn); // returns iImage, or CLC_EXTRAICON_EMPTY void SetExtraImage(HTREEITEM hItem, int iColumn, int iImage); // set iImage to CLC_EXTRAICON_EMPTY to reset image void SetExtraImageList(HIMAGELIST hImgList); int GetItemType(HTREEITEM hItem); // returns a MCLCIT_ (see below) HTREEITEM GetNextItem(DWORD Flags, HTREEITEM hItem); void SortContacts(); HANDLE GethContact(HTREEITEM hItem); // returns hContact, hGroup or hInfo HTREEITEM HitTest(LPPOINT pt, PDWORD hitFlags); // pt is relative to control; returns hItem or NULL void EnsureVisible(HTREEITEM hItem) {TreeView_EnsureVisible(hTreeView, hItem); InvalidateRect(hTreeView, NULL, false);} // sometimes horizontal scrollbar position changes too, so we must redraw extra icons - that's why here is InvalidateRect. TODO: try to find a way to invalidate it on _every_ horizontal scrollbar position change, instead of just here - unfortunately the scrollbar doesn't notify the tree control of its position change through WM_HSCROLL in some cases int SelectItem(HTREEITEM hItem) {return TreeView_SelectItem(hTreeView, hItem);} void SetItemParam(HTREEITEM hItem, LPARAM lParam) {GetItemData(hItem).lParam = lParam;} LPARAM GetItemParam(HTREEITEM hItem) {return GetItemData(hItem).lParam;} PTREEITEMARRAY GetSelection() {return &SelectedItems;} void SetRedraw(bool bRedraw) {SendMessage(hTreeView, WM_SETREDRAW, bRedraw, 0);} friend LRESULT CALLBACK ParentSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); friend LRESULT CALLBACK ContactListSubclassProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); friend int CALLBACK CompareItemsCallback(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); private: int Array_SetItemState(HTREEITEM hItem, bool bSelected); CCLItemData& GetItemData(HTREEITEM hItem); HTREEITEM TreeView_GetLastChild(HWND hTreeView, HTREEITEM hItem); HTREEITEM FindContact(HANDLE hContact); // returns NULL if not found void SelectGroups(HTREEITEM hCurItem, bool bSelected); DWORD GetItemTypeAsCLGNFlag(HTREEITEM hItem); // returns MCLGN_CONTACT, MCLGN_GROUP or MCLGN_INFO HWND hTreeView; WNDPROC OrigTreeViewProc; WNDPROC OrigParentProc; TREEITEMDATAARRAY Items; // array that stores info for every tree item; array items are left even if corresponding tree item was deleted, so treeitem's lParam can be used as an index of an item in this array. TREEITEMARRAY SelectedItems; // contains HTREEITEMs of all selected items HIMAGELIST ExtraImageList; }; // HitTest constants #define MCLCHT_ABOVE 0x0001 // above the client area #define MCLCHT_BELOW 0x0002 // below the client area #define MCLCHT_TOLEFT 0x0004 // to the left of the client area #define MCLCHT_TORIGHT 0x0008 // to the right of the client area #define MCLCHT_NOWHERE 0x0010 // in the client area, but below the last item #define MCLCHT_ONITEMINDENT 0x0020 // to the left of an item icon #define MCLCHT_ONITEMICON 0x0040 #define MCLCHT_ONITEMLABEL 0x0080 #define MCLCHT_ONITEMRIGHT 0x0100 // in the area to the right of an item #define MCLCHT_ONITEMEXTRA 0x0200 // on an extra icon, HIBYTE(HIWORD(hitFlags)) says which #define MCLCHT_ONITEM (MCLCHT_ONITEMICON | MCLCHT_ONITEMLABEL) // item types #define MCLCIT_GROUP 0 #define MCLCIT_CONTACT 1 #define MCLCIT_INFO 3 // GetNextItem constants #define MCLGN_ROOT 0 #define MCLGN_LAST 1 #define MCLGN_CHILD 2 #define MCLGN_LASTCHILD 3 #define MCLGN_PARENT 4 #define MCLGN_NEXT 5 #define MCLGN_PREV 6 // flags for use with MCLGN_NEXT and MCLGN_PREV: #define MCLGN_CONTACT 0x20 // you need to specify at least one of these three! otherwise GetNextItem will not find anything #define MCLGN_GROUP 0x40 #define MCLGN_INFO 0x80 #define MCLGN_ANY (MCLGN_CONTACT | MCLGN_GROUP | MCLGN_INFO) #define MCLGN_MULTILEVEL 0x100 // walk through items of different levels too (ex.: MCLGN_NEXT | MCLGN_MULTILEVEL) #define MCLGN_NOTCHILD (0x200 | MCLGN_MULTILEVEL) // when this flag is set, child items of specified hItem are ignored. for example, MCLGN_NEXT | MCLGN_CONTACT | MCLGN_NOTCHILD retrieves next contact that is not a child of hItem. // GetNextItem(MCLGN_PREV | MCLGN_ALL | MCLGN_NOTCHILD, CLM_GETNEXTITEM(MCLGN_NEXT | MCLGN_ALL | MCLGN_NOTCHILD, hItem) === hItem // notifications typedef struct { NMHDR hdr; PTREEITEMARRAY OldSelection, NewSelection; } NMCLIST; typedef NMCLIST* PNMCLIST; #define MCLN_FIRST (0U - 100U) #define MCLN_SELCHANGED (MCLN_FIRST - 20) // lParam = &NMCLIST; OldSelection and NewSelection contain selection info void LoadCListModule();