summaryrefslogtreecommitdiff
path: root/plugins/UserInfoEx/classPsTreeItem.cpp
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
commit48540940b6c28bb4378abfeb500ec45a625b37b6 (patch)
tree2ef294c0763e802f91d868bdef4229b6868527de /plugins/UserInfoEx/classPsTreeItem.cpp
parent5c350913f011e119127baeb32a6aedeb4f0d33bc (diff)
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/UserInfoEx/classPsTreeItem.cpp')
-rw-r--r--plugins/UserInfoEx/classPsTreeItem.cpp699
1 files changed, 699 insertions, 0 deletions
diff --git a/plugins/UserInfoEx/classPsTreeItem.cpp b/plugins/UserInfoEx/classPsTreeItem.cpp
new file mode 100644
index 0000000000..7f32b4871a
--- /dev/null
+++ b/plugins/UserInfoEx/classPsTreeItem.cpp
@@ -0,0 +1,699 @@
+/*
+UserinfoEx plugin for Miranda IM
+
+Copyright:
+ฉ 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol
+
+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.
+
+===============================================================================
+
+File name : $HeadURL: https://userinfoex.googlecode.com/svn/trunk/classPsTreeItem.cpp $
+Revision : $Revision: 187 $
+Last change on : $Date: 2010-09-08 16:05:54 +0400 (ะกั€, 08 ัะตะฝ 2010) $
+Last change by : $Author: ing.u.horn $
+
+===============================================================================
+*/
+
+#include "commonheaders.h"
+#include "dlg_propsheet.h"
+#include "m_skin.h"
+
+/**
+ * name: BoldGroupTitlesEnumChildren()
+ * desc: set font of groupboxes to bold
+ *
+ * return: 0
+ **/
+BOOL CALLBACK BoldGroupTitlesEnumChildren(HWND hWnd, LPARAM lParam)
+{
+ TCHAR szClass[64];
+ GetClassName(hWnd, szClass, 64);
+ if (!mir_tcscmp(szClass, _T("Button")) && (GetWindowLongPtr(hWnd, GWL_STYLE) & 0x0F) == BS_GROUPBOX)
+ SendMessage(hWnd, WM_SETFONT, lParam, NULL);
+ return TRUE;
+}
+
+/**
+ * name: CPsTreeItem
+ * class: CPsTreeItem
+ * desc: default constructor
+ * param: pPsh - propertysheet's init structure
+ * odp - optiondialogpage structure with the info about the item to add
+ * return: nothing
+ **/
+CPsTreeItem::CPsTreeItem()
+{
+ _idDlg = NULL;
+ _pTemplate = NULL;
+ _hInst = NULL;
+ _pfnDlgProc = NULL;
+ _hWnd = NULL;
+ _dwFlags = NULL;
+ _hItem = NULL; // handle to the treeview item
+ _iParent = -1; // index to the parent item
+ _iImage = -1; // index of treeview item's image
+ _bState = NULL; // initial state of this treeitem
+ _pszName = NULL; // original name, given by plugin (not customized)
+ _ptszLabel = NULL;
+ _pszProto = NULL;
+ _pszPrefix = NULL;
+ _hContact = NULL;
+}
+
+/**
+ * name: ~CPsTreeItem
+ * class: CPsTreeItem
+ * desc: default destructor
+ * param: none
+ * return: nothing
+ **/
+CPsTreeItem::~CPsTreeItem()
+{
+ if (_hWnd) DestroyWindow(_hWnd);
+ if (_pszName) mir_free(_pszName);
+ if (_ptszLabel) mir_free(_ptszLabel);
+ if (_pszProto) mir_free((LPVOID)_pszProto);
+}
+
+/**
+ * name: PropertyKey
+ * class: CPsTreeItem
+ * desc: merge the treeitem's unique name with a prefix to form a setting string
+ * param: pszProperty - the prefix to add
+ * return: pointer to the setting string
+ **/
+LPCSTR CPsTreeItem::PropertyKey(LPCSTR pszProperty)
+{
+ static CHAR pszSetting[MAXSETTING];
+ mir_snprintf(pszSetting, SIZEOF(pszSetting), "{%s\\%s}_%s", _pszPrefix, _pszName, pszProperty);
+ return pszSetting;
+}
+
+/**
+ * name: GlobalName
+ * class: CPsTreeItem
+ * desc: return item name without prepended protocol name
+ * param: nothing
+ * return: item name without protocol name
+ **/
+LPCSTR CPsTreeItem::GlobalName()
+{
+ LPSTR pgn = NULL;
+
+ if (_dwFlags & PSPF_PROTOPREPENDED)
+ {
+ pgn = mir_strchr(_pszName, '\\');
+ if (pgn && pgn[1]) pgn++;
+ }
+ return (!pgn || !*pgn) ?_pszName : pgn;
+}
+
+/**
+ * name: GlobalPropertyKey
+ * class: CPsTreeItem
+ * desc: merge the treeitem's unique name with a prefix to form a setting string
+ * param: pszProperty - the prefix to add
+ * return: pointer to the setting string
+ **/
+LPCSTR CPsTreeItem::GlobalPropertyKey(LPCSTR pszProperty)
+{
+ static CHAR pszSetting[MAXSETTING];
+ mir_snprintf(pszSetting, SIZEOF(pszSetting), "{Global\\%s}_%s", GlobalName(), pszProperty);
+ return pszSetting;
+}
+
+/**
+ * name: IconKey
+ * class: CPsTreeItem
+ * desc: merge the treeitem's unique name with a prefix to form a setting string
+ * param: pszProperty - the prefix to add
+ * return: pointer to the setting string
+ **/
+LPCSTR CPsTreeItem::IconKey()
+{
+ LPCSTR pszIconName = GlobalName();
+ if (pszIconName)
+ {
+ static CHAR pszSetting[MAXSETTING];
+ mir_snprintf(pszSetting, SIZEOF(pszSetting), MODNAME"_{%s}", pszIconName);
+ return pszSetting;
+ }
+ return NULL;
+}
+
+/**
+ * name: ParentItemName()
+ * class: CPsTreeItem
+ * desc: returns the unique name for the parent item
+ * param: nothing
+ * return: length of group name
+ **/
+LPSTR CPsTreeItem::ParentItemName()
+{
+ DBVARIANT dbv;
+ LPSTR result;
+
+ // try to read the parent item from the database
+ if (!DB::Setting::GetAString(NULL, MODNAME, PropertyKey(SET_ITEM_GROUP), &dbv))
+ {
+ result = dbv.pszVal;
+ }
+ else
+ {
+ const CHAR* p = mir_strrchr(_pszName, '\\');
+
+ if (p)
+ {
+ INT cchGroup = p - _pszName + 1;
+ result = mir_strncpy((LPSTR)mir_alloc(cchGroup), _pszName, cchGroup);
+ }
+ else
+ {
+ result = NULL;
+ }
+ }
+ return result;
+}
+
+/**
+ * name: SetName
+ * class: CPsTreeItem
+ * desc: set the unique name for this item from a given title as it comes with OPTIONDIALOGPAGE
+ * param: ptszTitle - the title which is the base for the unique name
+ * bIsUnicode - if TRUE the title is unicode
+ * return: 0 on success, 1 to 4 indicating the failed operation
+ **/
+INT CPsTreeItem::Name(LPTSTR ptszTitle, const BOOLEAN bIsUnicode)
+{
+ // convert title to utf8
+ _pszName = (bIsUnicode) ? mir_utf8encodeW((LPWSTR)ptszTitle) : mir_utf8encode((LPSTR)ptszTitle);
+ if (_pszName)
+ {
+ // convert disallowed characters
+ for (DWORD i = 0; _pszName[i] != 0; i++)
+ {
+ switch (_pszName[i])
+ {
+ case '{': _pszName[i] = '('; break;
+ case '}': _pszName[i] = ')'; break;
+ }
+ }
+ }
+ return _pszName == NULL;
+}
+
+/**
+ * name: HasName
+ * class: CPsTreeItem
+ * desc: returns true, if current item has the name provided by the parameter
+ * params: pszName - the name to match the item with
+ * return: nothing
+ **/
+BOOLEAN CPsTreeItem::HasName(const LPCSTR pszName) const
+{
+ return !mir_stricmp(_pszName, pszName);
+};
+
+/**
+ * name: Rename
+ * class: CPsTreeItem
+ * desc: Rename label for the treeitem
+ * params: pszLabel - the desired new label
+ * return: nothing
+ **/
+VOID CPsTreeItem::Rename(const LPTSTR pszLabel)
+{
+ if(pszLabel && *pszLabel)
+ {
+ LPTSTR pszDup = mir_tcsdup(pszLabel);
+ if(pszDup)
+ {
+ if(_ptszLabel)
+ {
+ mir_free(_ptszLabel);
+ }
+ _ptszLabel = pszDup;
+ // convert disallowed characters
+ while(*pszDup)
+ {
+ switch(*pszDup)
+ {
+ case '{': *pszDup = '('; break;
+ case '}': *pszDup = ')'; break;
+ }
+ pszDup++;
+ }
+ AddFlags(PSTVF_LABEL_CHANGED);
+ }
+ }
+}
+
+/**
+ * name: ItemLabel
+ * class: CPsTreeItem
+ * desc: returns the label for a given item. The returned value must be freed after use!
+ * param: pszName - uniquely identifiing string for a propertypage encoded with utf8 (e.g.: {group\item})
+ * return: Label in a newly allocated piece of memory
+ **/
+INT CPsTreeItem::ItemLabel(const BOOLEAN bReadDBValue)
+{
+ DBVARIANT dbv;
+
+ // clear existing
+ if (_ptszLabel)
+ {
+ mir_free(_ptszLabel);
+ }
+
+ // try to get custom label from database
+ if (!bReadDBValue || DB::Setting::GetTString(NULL, MODNAME, GlobalPropertyKey(SET_ITEM_LABEL), &dbv) || (_ptszLabel = dbv.ptszVal) == NULL)
+ {
+ // extract the name
+ LPSTR pszName = mir_strrchr(_pszName, '\\');
+ if (pszName && pszName[1])
+ {
+ pszName++;
+ }
+ else
+ {
+ pszName = _pszName;
+ }
+
+ LPTSTR ptszLabel = mir_utf8decodeT(pszName);
+ if (ptszLabel)
+ {
+ _ptszLabel = mir_tcsdup(TranslateTS(ptszLabel));
+ mir_free(ptszLabel);
+ }
+ }
+ // return nonezero if label is invalid
+ return _ptszLabel == NULL;
+}
+
+/**
+ * name: ProtoIcon
+ * class: CPsTreeItem
+ * desc: check if current tree item name is a protocol name and return its icon if so
+ * params: none
+ * return: nothing
+ **/
+HICON CPsTreeItem::ProtoIcon()
+{
+ PROTOACCOUNT **pa;
+ INT ProtoCount, i;
+
+ if (!CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)&ProtoCount, (LPARAM)&pa))
+ {
+ if (_pszName)
+ {
+ for (i = 0; i < ProtoCount; i++)
+ {
+ if (pa[i]->type == PROTOTYPE_PROTOCOL)
+ {
+ TCHAR *ptszName = mir_a2t(_pszName);
+ if (!mir_tcsnicmp(pa[i]->tszAccountName, ptszName, mir_tcslen(pa[i]->tszAccountName)))
+ {
+ HICON hIco;
+ CHAR szIconID[MAX_PATH];
+
+ mir_snprintf(szIconID, SIZEOF(szIconID), "core_status_%s1", pa[i]->szModuleName);
+ hIco = IcoLib_GetIcon(szIconID);
+ if (!hIco)
+ {
+ hIco = (HICON)CallProtoService(pa[i]->szModuleName, PS_LOADICON, PLI_PROTOCOL, NULL);
+ }
+ MIR_FREE (ptszName);
+ return hIco;
+ }
+ MIR_FREE (ptszName);
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
+ * name: Icon
+ * class: CPsTreeItem
+ * desc: load the icon, add to icolib if required and add to imagelist of treeview
+ * params: hIml - treeview's imagelist to add the icon to
+ * odp - pointer to OPTIONSDIALOGPAGE providing the information about the icon to load
+ * hDefaultIcon - default icon to use
+ * return: nothing
+ **/
+INT CPsTreeItem::Icon(HIMAGELIST hIml, OPTIONSDIALOGPAGE *odp, BOOLEAN bInitIconsOnly)
+{
+ HICON hIcon;
+
+ // check parameter
+ if (!_pszName || !odp)
+ return 1;
+
+ // load the icon if no icolib is installed or creating the required settingname failed
+ LPCSTR pszIconName = IconKey();
+
+ // use icolib to handle icons
+ if (!(hIcon = IcoLib_GetIcon(pszIconName)))
+ {
+ SKINICONDESC sid;
+
+ ZeroMemory(&sid, sizeof(sid));
+ sid.cbSize = sizeof(sid);
+ sid.flags = SIDF_ALL_TCHAR;
+ sid.cx = GetSystemMetrics(SM_CXSMICON);
+ sid.cy = GetSystemMetrics(SM_CYSMICON);
+ sid.pszName = (LPSTR)pszIconName;
+ sid.ptszDescription = _ptszLabel;
+ sid.ptszSection = LPGENT(SECT_TREE);
+
+ // the item to insert brings along an icon?
+ if (odp->flags & ODPF_ICON) {
+ // is it uinfoex item?
+ if (odp->hInstance == ghInst) {
+
+ // the pszGroup holds the iconfile for items added by uinfoex
+ sid.ptszDefaultFile = odp->ptszGroup;
+
+ // icon library exists?
+ if (sid.ptszDefaultFile) {
+ sid.iDefaultIndex = (INT_PTR)odp->hIcon;
+ }
+ // no valid icon library
+ else {
+ sid.hDefaultIcon = ImageList_GetIcon(hIml, 0, ILD_NORMAL);;
+ sid.iDefaultIndex = -1;
+ }
+ }
+ // default icon is delivered by the page to add
+ else {
+ sid.hDefaultIcon = (odp->hIcon) ? odp->hIcon : ImageList_GetIcon(hIml, 0, ILD_NORMAL);
+ sid.iDefaultIndex = -1;
+ }
+ }
+ // no icon to add, use default
+ else {
+ sid.iDefaultIndex = -1;
+ sid.hDefaultIcon = ProtoIcon();
+ if (!sid.hDefaultIcon) sid.hDefaultIcon = ImageList_GetIcon(hIml, 0, ILD_NORMAL);
+ }
+ // add file to icolib
+ CallServiceSync(MS_SKIN2_ADDICON, NULL, (LPARAM)&sid);
+
+ if (!bInitIconsOnly)
+ {
+ hIcon = IcoLib_GetIcon(pszIconName);
+ }
+ }
+
+ if (!bInitIconsOnly && hIml) {
+ // set custom icon to image list
+ if (hIcon) return ((_iImage = ImageList_AddIcon(hIml, hIcon)) == -1);
+ _iImage = 0;
+ }
+ else
+ _iImage = -1;
+ return 0;
+}
+
+/**
+ * name: OnAddPage
+ * class: CPsTreeItem
+ * desc: inits the treeitem's attributes
+ * params: pPsh - pointer to the property page's header structure
+ * odp - OPTIONSDIALOGPAGE structure with the information about the page to add
+ * return: 0 on success, 1 on failure
+ **/
+INT CPsTreeItem::Create(CPsHdr* pPsh, OPTIONSDIALOGPAGE *odp)
+{
+ INT err;
+ TCHAR szTitle[ MAXSETTING ];
+
+ // check parameter
+ if (pPsh && pPsh->_dwSize == sizeof(CPsHdr) && odp && PtrIsValid(odp->hInstance))
+ {
+ // instance value
+ _hInst = odp->hInstance;
+ _dwFlags = odp->flags;
+ _initParam = odp->dwInitParam;
+
+ // init page owning contact
+ _hContact = pPsh->_hContact;
+ _pszProto = mir_strdup(pPsh->_pszProto);
+
+ // global settings prefix for current contact (is dialog owning contact's protocol by default)
+ _pszPrefix = (pPsh->_pszPrefix) ? pPsh->_pszPrefix : "Owner";
+
+ if (pPsh->_dwFlags & PSF_PROTOPAGESONLY)
+ {
+ if (_dwFlags & ODPF_USERINFOTAB)
+ {
+ mir_sntprintf(szTitle, SIZEOF(szTitle), _T("%s %d\\%s"), odp->ptszTitle, pPsh->_nSubContact+1, odp->ptszTab);
+ }
+ else
+ {
+ mir_sntprintf(szTitle, SIZEOF(szTitle), _T("%s %d"), odp->ptszTitle, pPsh->_nSubContact+1);
+ }
+ }
+ else
+ {
+ if (_dwFlags & ODPF_USERINFOTAB)
+ {
+ mir_sntprintf(szTitle, SIZEOF(szTitle), _T("%s\\%s"), odp->ptszTitle, odp->ptszTab);
+ }
+ else
+ {
+ mir_tcscpy(szTitle, odp->ptszTitle);
+ }
+ }
+ // set the unique utf8 encoded name for the item
+ if (err = Name(szTitle, (_dwFlags & ODPF_UNICODE) == ODPF_UNICODE))
+ {
+ MsgErr(NULL, LPGENT("Creating unique name for a page failed with %d and error code %d"), err, GetLastError());
+ }
+ // read label from database or create it
+ else if (err = ItemLabel(TRUE))
+ {
+ MsgErr(NULL, LPGENT("Creating the label for a page failed with %d and error code %d"), err, GetLastError());
+ }
+ else
+ {
+ // load icon for the item
+ Icon(pPsh->_hImages, odp, (pPsh->_dwFlags & PSTVF_INITICONS) == PSTVF_INITICONS);
+
+ // the rest is not needed if only icons are loaded
+ if (pPsh->_dwFlags & PSTVF_INITICONS)
+ {
+ return 0;
+ }
+
+ // load custom order
+ if (!(pPsh->_dwFlags & PSTVF_SORTTREE))
+ {
+ _iPosition = (INT)DB::Setting::GetByte(PropertyKey(SET_ITEM_POS), odp->position);
+ if ((_iPosition < 0) && (_iPosition > 0x800000A))
+ _iPosition = 0;
+ }
+ // read visibility state
+ _bState = DB::Setting::GetByte(PropertyKey(SET_ITEM_STATE), DBTVIS_EXPANDED);
+
+ // error for no longer supported dialog template type
+ if (((UINT_PTR)odp->pszTemplate & 0xFFFF0000))
+ {
+ MsgErr(NULL, LPGENT("The dialog template type is no longer supported"));
+ }
+ else
+ {
+ // fetch dialog resource id
+ _idDlg = (INT_PTR)odp->pszTemplate;
+ // dialog procedure
+ _pfnDlgProc = odp->pfnDlgProc;
+
+ // is dummy item?
+ if (!_idDlg && !_pfnDlgProc)
+ return 0;
+
+ if (_idDlg && _pfnDlgProc)
+ {
+ // lock the property pages dialog resource
+ _pTemplate = (DLGTEMPLATE*)LockResource(LoadResource(_hInst, FindResource(_hInst, (LPCTSTR)(UINT_PTR)_idDlg, RT_DIALOG)));
+ if (_pTemplate)
+ {
+ return 0;
+ }
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+/**
+ * name: DBSaveItemState
+ * class: CPsTreeItem
+ * desc: saves the current treeitem to database
+ * param: pszGroup - name of the parent item
+ * iItemPosition - iterated index to remember the order of the tree
+ * iState - expanded|collapsed|invisible
+ * dwFlags - tells what to save
+ * return: handle to new (moved) treeitem if successful or NULL otherwise
+ **/
+WORD CPsTreeItem::DBSaveItemState(LPCSTR pszGroup, INT iItemPosition, UINT iState, DWORD dwFlags)
+{
+ WORD numErrors = 0;
+
+ // save group
+ if ((dwFlags & PSTVF_GROUPS) && (dwFlags & PSTVF_POS_CHANGED)) {
+ numErrors += DB::Setting::WriteUString(PropertyKey(SET_ITEM_GROUP), (LPSTR)pszGroup);
+ }
+ // save label
+ if ((dwFlags & PSTVF_LABEL_CHANGED) && (_dwFlags & PSTVF_LABEL_CHANGED)) {
+ numErrors += DB::Setting::WriteTString(GlobalPropertyKey(SET_ITEM_LABEL), Label());
+ }
+ // save position
+ if ((dwFlags & PSTVF_POS_CHANGED) && !(dwFlags & PSTVF_SORTTREE)) {
+ numErrors += DB::Setting::WriteByte(PropertyKey(SET_ITEM_POS), iItemPosition);
+ }
+ // save state
+ if (dwFlags & PSTVF_STATE_CHANGED) {
+ numErrors += DB::Setting::WriteByte(PropertyKey(SET_ITEM_STATE),
+ _hItem ? ((iState & TVIS_EXPANDED) ? DBTVIS_EXPANDED : DBTVIS_NORMAL) : DBTVIS_INVISIBLE);
+ }
+ RemoveFlags(PSTVF_STATE_CHANGED|PSTVF_LABEL_CHANGED|PSTVF_POS_CHANGED);
+ return numErrors;
+}
+
+/**
+ * name: CreateWnd
+ * class: CPsTreeItem
+ * desc: create the dialog for the propertysheet page
+ * params: pPs - propertysheet's datastructure
+ * hDlg - windowhandle of the propertysheet
+ * return: windowhandle of the dialog if successful
+ **/
+HWND CPsTreeItem::CreateWnd(LPPS pPs)
+{
+ if (pPs && !_hWnd && _pTemplate && _pfnDlgProc)
+ {
+ _hWnd = CreateDialogIndirectParam(_hInst, _pTemplate, pPs->hDlg, _pfnDlgProc, (LPARAM)_hContact);
+ if (_hWnd != NULL)
+ {
+ PSHNOTIFY pshn;
+
+ pshn.hdr.code = PSN_PARAMCHANGED;
+ pshn.hdr.hwndFrom = _hWnd;
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = (LPARAM)_initParam;
+ SendMessage(_hWnd, WM_NOTIFY, 0, (LPARAM)&pshn);
+
+ // force child window (mainly for AIM property page)
+ SetWindowLongPtr(_hWnd, GWL_STYLE, (GetWindowLongPtr(_hWnd, GWL_STYLE) & ~(WS_POPUP|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME)) | WS_CHILD);
+ SetWindowLongPtr(_hWnd, GWL_EXSTYLE, GetWindowLongPtr(_hWnd, GWL_EXSTYLE) & ~(WS_EX_APPWINDOW|WS_EX_STATICEDGE|WS_EX_CLIENTEDGE));
+ SetParent(_hWnd, pPs->hDlg);
+
+ // move dialog into the display area
+ SetWindowPos(_hWnd, HWND_TOP,
+ pPs->rcDisplay.left, pPs->rcDisplay.top,
+ pPs->rcDisplay.right - pPs->rcDisplay.left,
+ pPs->rcDisplay.bottom - pPs->rcDisplay.top, FALSE);
+ // set bold titles
+ if (_dwFlags & ODPF_BOLDGROUPS)
+ {
+ EnumChildWindows(_hWnd, BoldGroupTitlesEnumChildren, (LPARAM)pPs->hBoldFont);
+ }
+
+ // some initial notifications
+ OnInfoChanged();
+ OnPageIconsChanged();
+ return _hWnd;
+ }
+ }
+ return NULL;
+}
+
+/***********************************************************************************************************
+ * public event handlers
+ ***********************************************************************************************************/
+
+/**
+ * name: OnInfoChanged
+ * class: CPsTreeItem
+ * desc: Notifies the propertypage of changed contact information
+ * params: none
+ * return: nothing
+ **/
+VOID CPsTreeItem::OnInfoChanged()
+{
+ if (_hWnd) {
+ PSHNOTIFY pshn;
+
+ pshn.hdr.code = PSN_INFOCHANGED;
+ pshn.hdr.hwndFrom = _hWnd;
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = (LPARAM)_hContact;
+ if (PSP_CHANGED != SendMessage(_hWnd, WM_NOTIFY, 0, (LPARAM)&pshn)) {
+ _dwFlags &= ~PSPF_CHANGED;
+ }
+ }
+}
+
+/**
+ * name: OnPageIconsChanged
+ * class: CPsTreeItem
+ * desc: Notifies the propertypage of changed icons in icolib
+ * params: none
+ * return: nothing
+ **/
+VOID CPsTreeItem::OnPageIconsChanged()
+{
+ if (_hWnd) {
+ PSHNOTIFY pshn;
+
+ pshn.hdr.code = PSN_ICONCHANGED;
+ pshn.hdr.hwndFrom = _hWnd;
+ pshn.hdr.idFrom = 0;
+ pshn.lParam = (LPARAM)_hContact;
+ SendMessage(_hWnd, WM_NOTIFY, 0, (LPARAM)&pshn);
+ }
+}
+
+/**
+ * name: OnIconsChanged
+ * class: CPsTreeItem
+ * desc: Handles reloading icons if changed by icolib
+ * params: none
+ * return: nothing
+ **/
+VOID CPsTreeItem::OnIconsChanged(CPsTree *pTree)
+{
+ HICON hIcon;
+ RECT rc;
+
+ // update tree item icons
+ if (pTree->ImageList() && (hIcon = IcoLib_GetIcon(IconKey())) != NULL) {
+ _iImage = (_iImage > 0)
+ ? ImageList_ReplaceIcon(pTree->ImageList(), _iImage, hIcon)
+ : ImageList_AddIcon(pTree->ImageList(), hIcon);
+
+ if (_hItem && TreeView_GetItemRect(pTree->Window(), _hItem, &rc, 0)) {
+ InvalidateRect(pTree->Window(), &rc, TRUE);
+ }
+ }
+ // update pages icons
+ OnPageIconsChanged();
+}
+