update for HEAD-2003091401
[reactos.git] / subsys / system / explorer / Seashell / SeaShellExt / UITreeCtrl.cpp
1 //*******************************************************************************
2 // COPYRIGHT NOTES
3 // ---------------
4 // You may use this source code, compile or redistribute it as part of your application 
5 // for free. You cannot redistribute it as a part of a software development 
6 // library without the agreement of the author. If the sources are 
7 // distributed along with the application, you should leave the original 
8 // copyright notes in the source code without any changes.
9 // This code can be used WITHOUT ANY WARRANTIES at your own risk.
10 // 
11 // For the latest updates to this code, check this site:
12 // http://www.masmex.com 
13 // after Sept 2000
14 // 
15 // Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
16 //*******************************************************************************
17
18 // URLTreeCtrl.cpp : implementation file
19 //
20
21 #include "stdafx.h"
22 #include "UITreeCtrl.h"
23 #include "UIMessages.h"
24 #include "cbformats.h"
25 #include "UIres.h"
26
27 #ifdef _DEBUG
28 #define new DEBUG_NEW
29 #undef THIS_FILE
30 static char THIS_FILE[] = __FILE__;
31 #endif
32
33 /////////////////////////////////////////////////////////////////////////////
34 // CUITreeCtrl
35 IMPLEMENT_DYNAMIC(CUITreeCtrl,CUIDragDropTree)
36 IMPLEMENT_DYNAMIC(CRefresh,CObject)
37 IMPLEMENT_DYNAMIC(CRefreshCategory,CRefresh)
38
39
40 CUITreeCtrl::CUITreeCtrl(bool bDragDrop) 
41 : CUIDragDropTree(bDragDrop)
42 {
43         m_idxClosed= 0;
44         m_idxOpen = 0; 
45         m_vkeydown = 0;
46         m_IDTimer = 0;
47         m_style = TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS;
48         m_PopupID =     0;
49         m_pPopupWnd = NULL;
50         m_hOrigFont = NULL;
51         m_bMe = false;
52 }
53
54 CUITreeCtrl::~CUITreeCtrl()
55 {
56 }
57
58 void CUITreeCtrl::OnDeleteItemData(DWORD dwData)
59 {
60
61 }
62
63 void CUITreeCtrl::ItemPrePaint(LPNMTVCUSTOMDRAW lptvcd,LRESULT *pResult)
64 {
65         *pResult = CDRF_DODEFAULT;
66         if (lptvcd->nmcd.dwDrawStage & CDDS_ITEM)
67         {
68                 UINT state = GetItemState((HTREEITEM)lptvcd->nmcd.dwItemSpec,TVIS_SELECTED | TVIS_EXPANDED);
69                 if ((state & TVIS_SELECTED))
70                         return;
71                 if ((state & TVIS_SELECTED) && (state & TVIS_EXPANDED))
72                         return;
73         }
74         HTREEITEM hItem = (HTREEITEM)lptvcd->nmcd.dwItemSpec;
75         CUIListCtrlData* pData = GetListCtrlData(hItem);
76         if (pData == NULL)
77                 return;
78         *pResult = CDRF_NOTIFYPOSTPAINT;
79         if (pData->IsFontSet())
80         {
81                 CDC *pDC = CDC::FromHandle(lptvcd->nmcd.hdc);
82                 CFont *pOldFont = pDC->SelectObject((CFont*)pData->GetFont());
83                 m_hOrigFont = (HFONT)pOldFont;
84                 *pResult |= CDRF_NEWFONT;
85         }
86         lptvcd->clrText = pData->GetTextColor();
87         lptvcd->clrTextBk = pData->GetBkColor();
88 }
89
90 void CUITreeCtrl::ItemPostPaint(LPNMTVCUSTOMDRAW lptvcd,LRESULT *pResult)
91 {
92         CDC *pDC = CDC::FromHandle(lptvcd->nmcd.hdc);
93         if (m_hOrigFont)
94         {
95                 pDC->SelectObject(CFont::FromHandle(m_hOrigFont));
96                 m_hOrigFont = NULL;
97         }
98         *pResult = CDRF_DODEFAULT;
99 }
100
101 bool CUITreeCtrl::EndLabelEdit(HTREEITEM hItem,LPCTSTR pszText)
102 {
103         return false;
104 }
105
106 UINT CUITreeCtrl::GetMenuID()
107 {
108         return m_PopupID;
109 }
110
111 CWnd *CUITreeCtrl::GetMenuWnd()
112 {
113         return m_pPopupWnd;
114 }
115
116 void CUITreeCtrl::SetPopupID(UINT nID)
117 {
118         m_PopupID = nID;
119 }
120
121 void CUITreeCtrl::SetPopupWnd(CWnd *pWnd)
122 {
123         m_pPopupWnd = pWnd;
124 }
125
126 bool CUITreeCtrl::DragDrop(CDD_OleDropTargetInfo *pInfo)
127 {
128         if (pInfo->GetDataObject() == NULL)
129         {
130                 HTREEITEM hItem = pInfo->GetTreeItem();
131                 if (pInfo->GetDropEffect() == DROPEFFECT_MOVE)
132                 {
133                         if (TransferItem(GetDragItem(),hItem))
134                         {
135                                 DeleteItem(GetDragItem());
136                         }
137                 }
138                 else
139                 {
140                         AfxMessageBox(_T("Copy not supported!"));
141                 }
142                 return true;
143         }
144         return false;
145 }
146
147 bool CUITreeCtrl::DragEnter(CDD_OleDropTargetInfo *pInfo)
148 {
149         return false;
150 }
151
152 bool CUITreeCtrl::DragLeave(CDD_OleDropTargetInfo *pInfo)
153 {
154         return false;
155 }
156
157 bool CUITreeCtrl::DragOver(CDD_OleDropTargetInfo *pInfo)
158 {
159         // possible non ole drag & drop
160         if (pInfo->GetDataObject() == NULL)
161         {
162                 return true;
163         }
164         // ole drag and drop expects the dropeffect to be set
165         // any valid formats?
166         if (CWDClipboardData::Instance()->IsDataAvailable(pInfo->GetDataObject()))
167         {
168                 FORMATETC FormatEtc;
169                 FormatEtc.cfFormat = CWDClipboardData::Instance()->GetClipboardFormat(CWDClipboardData::e_cfFileGroupDesc);
170                 FormatEtc.ptd = NULL;
171                 FormatEtc.dwAspect = DVASPECT_CONTENT;
172                 FormatEtc.lindex = -1;
173                 FormatEtc.tymed = TYMED_HGLOBAL;
174                 HRESULT hr = pInfo->GetDataObject()->m_lpDataObject->QueryGetData(&FormatEtc);
175                 if ((pInfo->GetKeyboardState() & MK_SHIFT))
176                         pInfo->SetDropEffect(DROPEFFECT_MOVE);
177                 else if (hr == S_OK)
178                 {
179                         pInfo->SetDropEffect(DROPEFFECT_COPY);
180                 }
181                 else
182                         pInfo->SetDropEffect(DROPEFFECT_COPY);
183                 return true;
184         }
185         return false;
186 }
187
188 DROPEFFECT CUITreeCtrl::DoDragDrop(NM_TREEVIEW* pNMTreeView,COleDataSource *pOleDataSource)
189 {
190         // non ole drag and drop only within tree
191         CCF_String ccfText(GetItemText(pNMTreeView->itemNew.hItem));
192         CWDClipboardData::Instance()->SetData(pOleDataSource,&ccfText,CWDClipboardData::e_cfString);
193         return DROPEFFECT_ALL;
194 }
195
196 CRefresh *CUITreeCtrl::CreateRefreshObject(HTREEITEM hItem,LPARAM lParam)
197 {
198         return new CRefresh(hItem,lParam);
199 }
200
201 void CUITreeCtrl::UpdateEvent(LPARAM lHint,CObject *pHint)
202 {
203         GetParent()->SendMessage(WM_APP_UPDATE_ALL_VIEWS,(WPARAM)lHint,(LPARAM)pHint);
204 }
205
206 void CUITreeCtrl::UpdateCurrentSelection()
207 {
208         HTREEITEM hItem = GetSelectedItem();
209         if (hItem)
210         {
211                 SelectionChanged(hItem,GetItemData(hItem));
212         }
213 }
214
215 void CUITreeCtrl::DoubleClick(HTREEITEM hItem)
216 {
217 }
218
219 void CUITreeCtrl::SelectionChanged(HTREEITEM hItem,LPARAM lParam)
220 {
221         CRefresh *pRefresh = CreateRefreshObject(hItem,lParam);
222         if (pRefresh)
223                 UpdateEvent(HINT_TREE_SEL_CHANGED,pRefresh);
224         delete pRefresh;
225 }
226
227 HTREEITEM CUITreeCtrl::AddAnItem(HTREEITEM hParent, LPCTSTR szText, LPARAM lParam, HTREEITEM hInsAfter,int iImage,int iSelImage, int nChildren)
228 {
229         ASSERT_VALID(this);
230
231         TV_ITEM tvI;
232         TV_INSERTSTRUCT tvIns;
233         ZeroMemory(&tvI,sizeof(tvI));
234         ZeroMemory(&tvIns,sizeof(tvIns));
235         tvI.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
236         if (nChildren) // get the plus sign
237         {
238                 tvI.mask |= TVIF_CHILDREN;
239                 tvI.cChildren = nChildren;
240         }
241         tvI.pszText = (LPTSTR)szText;
242         tvI.cchTextMax = lstrlen(szText);
243         if (iImage == 0)
244                 iImage = m_idxClosed;
245         tvI.iImage = iImage;
246         if (iSelImage == 0)
247                 iSelImage = iImage;
248         tvI.iSelectedImage = iSelImage;
249         tvI.lParam = (LPARAM)GetNewListCtrlData(lParam,hParent);
250         tvIns.item = tvI;
251         tvIns.hInsertAfter = hInsAfter;
252         tvIns.hParent = hParent;
253         
254         m_bMe = true;
255         HTREEITEM hNewItem = InsertItem(&tvIns);
256         m_bMe = false;
257         return hNewItem;
258 }
259
260 CUIListCtrlData *CUITreeCtrl::GetNewListCtrlData(DWORD dwData,HTREEITEM hParent)
261 {
262         CUIListCtrlData *pListCtrlData = new CUIListCtrlData;
263         pListCtrlData->SetExtData(dwData); 
264         return pListCtrlData;
265 }
266
267 DWORD CUITreeCtrl::GetItemData(HTREEITEM hItem) const
268 {
269         if (hItem == NULL)
270                 return 0;
271         const CUIListCtrlData* pData = GetListCtrlData(hItem);
272         if (pData)
273                 return pData->GetExtData();
274         return 0;
275 }
276
277 BOOL CUITreeCtrl::SetItemData(HTREEITEM hItem,DWORD dwData,bool bAutoDelete)
278 {
279         ASSERT(hItem);
280         if (hItem == NULL) 
281                 return FALSE;
282         CUIListCtrlData* pData = GetListCtrlData(hItem);
283         if (pData == NULL) 
284                 return FALSE;
285         pData->SetExtData(dwData);
286         pData->SetAutoDelete(bAutoDelete);
287         return TRUE;
288 }
289
290 CUIListCtrlData *CUITreeCtrl::GetListCtrlData(HTREEITEM hItem) const
291 {
292         ((CUITreeCtrl*)this)->m_bMe = true;
293         CUIListCtrlData *pData = (CUIListCtrlData*)CTreeCtrl::GetItemData(hItem);
294         ((CUITreeCtrl*)this)->m_bMe = false;
295         if (pData == NULL)
296                 return NULL;
297         ASSERT(pData->IsKindOf(RUNTIME_CLASS(CUIListCtrlData)));
298         return pData;
299 }
300
301 void CUITreeCtrl::SetTextColor(HTREEITEM hItem,COLORREF TextColor)
302 {
303         CUIListCtrlData *pData = GetListCtrlData(hItem);
304         if (pData)
305                 pData->SetTextColor(TextColor);
306 };
307
308 void CUITreeCtrl::SetBkColor(HTREEITEM hItem,COLORREF BkColor)
309 {
310         CUIListCtrlData *pData = GetListCtrlData(hItem);
311         if (pData)
312                 pData->SetBkColor(BkColor);
313 }
314
315 void CUITreeCtrl::SetDefaultTextColor(HTREEITEM hItem)
316 {
317         CUIListCtrlData *pData = GetListCtrlData(hItem);
318         if (pData)
319                 pData->SetDefaultTextColor();
320 };
321
322 void CUITreeCtrl::SetDefaultBkColor(HTREEITEM hItem)
323 {
324         CUIListCtrlData *pData = GetListCtrlData(hItem);
325         if (pData)
326                 pData->SetDefaultBkColor();
327 }
328
329 void CUITreeCtrl::SetItemFont(HTREEITEM hItem,CFont *pFont)
330 {
331         CUIListCtrlData* pData = GetListCtrlData(hItem);
332         if (pData == NULL)
333                 return;
334         ASSERT(pFont);
335         if (pFont)
336                 pData->SetFont(pFont);
337 }
338
339 void CUITreeCtrl::SetItemBold(HTREEITEM hItem,bool bBold)
340 {
341         CUIListCtrlData* pData = GetListCtrlData(hItem);
342         if (pData == NULL)
343                 return;
344         if (!pData->IsFontSet())
345                 pData->SetFont(GetFont());
346         const CFont *pFont = pData->GetFont();
347         LOGFONT lf;
348         ((CFont*)pFont)->GetLogFont(&lf);
349         lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL; 
350         CFont font;
351         font.CreateFontIndirect(&lf);
352         pData->SetFont(&font);
353         CRect rect;
354         if (GetItemRect(hItem,&rect,FALSE))
355         {
356                 InvalidateRect(rect);
357                 UpdateWindow();
358         }
359 }
360
361 HTREEITEM CUITreeCtrl::GetHitItem(CPoint *pt)
362 {
363         UINT Flag;
364         HTREEITEM hItem;
365         CPoint cpt;
366
367         POINT pt1;
368         GetCursorPos(&pt1);
369         ScreenToClient(&pt1);   
370         cpt.x = pt1.x;
371         cpt.y = pt1.y;
372         hItem = HitTest(cpt, &Flag);
373         if (hItem && ((Flag & TVHT_ONITEMLABEL) || (Flag & TVHT_ONITEMICON)))
374         {
375                 if (pt)
376                         *pt = pt1;
377                 return hItem;
378         }
379         return NULL;
380 }
381
382 void CUITreeCtrl::Refresh()
383 {
384 }
385
386 void CUITreeCtrl::DeleteKey(HTREEITEM hItem)
387 {
388 }
389
390 void CUITreeCtrl::GoBack(HTREEITEM hItem)
391 {
392 }
393
394 void CUITreeCtrl::ShowProperties(HTREEITEM hItem)
395 {
396 }
397
398 void CUITreeCtrl::ShowPopupMenu(HTREEITEM hItem,CPoint point)
399 {
400         UINT MenuID = GetMenuID();
401         if (MenuID == 0) 
402                 return;
403         CWnd *pWndMess = GetMenuWnd();
404         if (pWndMess == NULL)
405                 pWndMess = this;
406         CMenu menu;
407         VERIFY(menu.LoadMenu(MenuID));
408         CMenu* pPopup = menu.GetSubMenu(0);
409         ASSERT(pPopup != NULL);
410         pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, pWndMess);
411 }
412
413 BEGIN_MESSAGE_MAP(CUITreeCtrl, CUIDragDropTree)
414         //{{AFX_MSG_MAP(CUITreeCtrl)
415         ON_NOTIFY_REFLECT_EX(NM_DBLCLK, OnDblclk)
416         ON_NOTIFY_REFLECT_EX(NM_RETURN, OnReturn)
417         ON_NOTIFY_REFLECT_EX(NM_RCLICK, OnRclick)
418         ON_NOTIFY_REFLECT_EX(NM_CUSTOMDRAW, OnCustomDraw)
419         ON_NOTIFY_REFLECT_EX(TVN_ITEMEXPANDED, OnItemExpanded)
420         ON_NOTIFY_REFLECT_EX(TVN_ITEMEXPANDING, OnItemExpanding)
421         ON_NOTIFY_REFLECT_EX(TVN_SELCHANGED, OnSelchanged)
422         ON_NOTIFY_REFLECT_EX(TVN_ENDLABELEDIT, OnEndLabelEdit)
423         ON_NOTIFY_REFLECT_EX(TVN_DELETEITEM, OnDeleteItem)
424         ON_NOTIFY_REFLECT(TVN_KEYDOWN, OnKeydownFolder)
425         ON_WM_MOUSEWHEEL()
426         ON_WM_TIMER()
427         ON_WM_CREATE()
428         //}}AFX_MSG_MAP
429         ON_MESSAGE(WM_APP_ON_PROPERTIES_KEY,OnAppPropertiesKey)
430         ON_MESSAGE(WM_APP_ON_DELETE_KEY,OnAppDeleteKey)
431         ON_MESSAGE(WM_APP_ON_CONTEXT_MENU_KEY,OnAppContextMenuKey)
432         ON_MESSAGE(WM_APP_ON_BACKSPACE_KEY,OnAppBackspaceKey)
433         ON_MESSAGE(WM_APP_ON_EDIT_KEY,OnAppEditKey)
434         ON_MESSAGE(WM_APP_ON_REFRESH_KEY,OnAppRefreshKey)
435
436         ON_MESSAGE(TVM_GETITEM,OnTVMGetItem)
437         ON_MESSAGE(TVM_SETITEM,OnTVMSetItem)
438         ON_MESSAGE(TVM_INSERTITEM,OnTVMInsertItem)
439         ON_MESSAGE(WM_APP_TIMER_SEL_CHANGE,OnTimerSelChange)
440         ON_MESSAGE(WM_APP_OLE_DD_DODRAGDROP, OnDDDoDragDrop)
441         ON_MESSAGE(WM_APP_OLE_DD_DROP, OnDragDrop)
442         ON_MESSAGE(WM_APP_OLE_DD_OVER, OnDragOver)
443         ON_MESSAGE(WM_APP_OLE_DD_ENTER, OnDragEnter)
444         ON_MESSAGE(WM_APP_OLE_DD_LEAVE, OnDragLeave)
445 END_MESSAGE_MAP()
446
447 /////////////////////////////////////////////////////////////////////////////
448 // CUITreeCtrl message handlers
449 BOOL CUITreeCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) 
450 {
451         LPNMTVCUSTOMDRAW lptvcd = (LPNMTVCUSTOMDRAW)pNMHDR;
452         if(lptvcd->nmcd.dwDrawStage == CDDS_PREPAINT)
453         {
454                 *pResult = CDRF_NOTIFYITEMDRAW;
455         }
456         else if(lptvcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
457         {
458                 ItemPrePaint(lptvcd,pResult);
459         }
460         else if(lptvcd->nmcd.dwDrawStage == CDDS_ITEMPOSTPAINT)
461         {
462                 ItemPostPaint(lptvcd,pResult);
463         }
464         return TRUE;
465 }
466
467 BOOL CUITreeCtrl::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) 
468 {
469         // TODO: Add your control notification handler code here
470         CPoint point;
471         HTREEITEM hItem = GetHitItem(&point);
472         if (hItem == NULL) 
473                 return FALSE;
474         ClientToScreen(&point);
475         ShowPopupMenu(hItem,point);
476         *pResult = 0;
477         return TRUE;
478 }
479
480 BOOL CUITreeCtrl::OnDeleteItem(NMHDR* pNMHDR, LRESULT* pResult) 
481 {
482         NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
483         // TODO: Add your control notification handler code here
484         CUIListCtrlData* pData = (CUIListCtrlData*)pNMTreeView->itemOld.lParam;
485         if (!pData->GetAutoDelete())
486                 OnDeleteItemData(pData->GetExtData());
487         delete pData;
488         return TRUE;
489 }
490
491 LRESULT CUITreeCtrl::OnTVMGetItem(WPARAM wParam,LPARAM lParam)
492 {
493         LPTVITEM pitem = (LPTVITEM)lParam;
494         if (m_bMe == false && pitem->mask & TVIF_PARAM)
495         {
496                 CUIListCtrlData* pData = GetListCtrlData(pitem->hItem);
497                 if (pData)
498                 {
499                         pitem->lParam = pData->GetExtData();
500                         pitem->mask &= ~TVIF_PARAM;
501                 }
502         }
503         return Default();
504 }
505
506 LRESULT CUITreeCtrl::OnTVMSetItem(WPARAM wParam,LPARAM lParam)
507 {
508         LPTVITEM pitem = (LPTVITEM)lParam;
509         if (m_bMe == false && pitem->mask & TVIF_PARAM)
510         {
511                 CUIListCtrlData* pData = GetListCtrlData(pitem->hItem);
512                 if (pData)
513                 {
514                         pData->SetExtData(pitem->lParam);
515                         pitem->mask &= ~TVIF_PARAM;
516                 }
517         }
518         return Default();
519 }
520
521 LRESULT CUITreeCtrl::OnTVMInsertItem(WPARAM wParam,LPARAM lParam)
522 {
523         LPTVINSERTSTRUCT lpis = (LPTVINSERTSTRUCT)lParam;
524         if (m_bMe == false && lpis->item.mask & TVIF_PARAM)
525         {
526                 lpis->item.lParam = (LPARAM)GetNewListCtrlData(lpis->item.lParam,lpis->hParent);
527         }
528         return Default();
529 }
530
531 int CUITreeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
532 {
533         if (CUIDragDropTree::OnCreate(lpCreateStruct) == -1)
534                 return -1;
535
536         Init();
537
538         // TODO: Add your specialized creation code here
539         return 0;
540 }
541
542 UINT CUITreeCtrl::GetIconID()
543 {
544         return IDI_FOLDER_CLOSED;
545 }
546
547 UINT CUITreeCtrl::GetOpenIconID()
548 {
549         return 0;
550 }
551
552 bool CUITreeCtrl::Expanding(NM_TREEVIEW *nmtvw)
553 {
554         return false;
555 }
556
557 bool CUITreeCtrl::Collapsing(NM_TREEVIEW *nmtvw)
558 {
559         return true;
560 }
561
562 void CUITreeCtrl::Init()
563 {
564         // Create the image list we will need
565         int nCxSmall = GetSystemMetrics(SM_CXSMICON);
566         int nCySmall = GetSystemMetrics(SM_CYSMICON);
567         m_ImageList.Create(nCxSmall,
568                                                 nCySmall,
569                                                 TRUE,   // list does not include masks
570                                                 2,
571                                                 0 );    // list won't grow
572         UINT nIconID = GetIconID();
573         if (nIconID)
574         {
575                 HINSTANCE hInstIcon = AfxFindResourceHandle(MAKEINTRESOURCE(nIconID),RT_GROUP_ICON);
576                 HICON hIcon = (HICON)LoadImage( hInstIcon, MAKEINTRESOURCE(nIconID), IMAGE_ICON, 
577                         nCxSmall, nCySmall, 0 );
578                 m_idxClosed = m_ImageList.Add(hIcon);
579         }
580         UINT nOpenIconID = GetOpenIconID();
581         if (nOpenIconID)
582         {
583                 HINSTANCE hInstIcon = AfxFindResourceHandle(MAKEINTRESOURCE(nOpenIconID),RT_GROUP_ICON);
584                 HICON hOpenIcon = (HICON)LoadImage( hInstIcon, MAKEINTRESOURCE(nOpenIconID), IMAGE_ICON, 
585                         nCxSmall, nCySmall, 0 );
586                 m_idxOpen = m_ImageList.Add(hOpenIcon);
587         }
588         // Associate the image list with the tree
589         SetImageList(&m_ImageList,TVSIL_NORMAL);
590         m_ImageList.SetBkColor(CLR_NONE);
591         ModifyStyle(0,m_style);
592 }
593
594 BOOL CUITreeCtrl::PreCreateWindow(CREATESTRUCT& cs) 
595 {
596         // TODO: Add your specialized code here and/or call the base class
597         cs.style |= m_style;
598         return CUIDragDropTree::PreCreateWindow(cs);
599 }
600
601 BOOL CUITreeCtrl::OnEndLabelEdit(NMHDR* pNMHDR, LRESULT* pResult) 
602 {
603         LPNMTVDISPINFO pDispInfo = (LPNMTVDISPINFO)pNMHDR;
604         if (pDispInfo->item.pszText)
605                 *pResult = EndLabelEdit(pDispInfo->item.hItem,pDispInfo->item.pszText);
606         return TRUE;
607 }
608
609 BOOL CUITreeCtrl::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) 
610 {
611         // TODO: Add your control notification handler code here
612         HTREEITEM hItem = GetSelectedItem();
613         DoubleClick(hItem);
614         return TRUE;
615 }
616
617 BOOL CUITreeCtrl::OnReturn(NMHDR* pNMHDR, LRESULT* pResult) 
618 {
619         // TODO: Add your control notification handler code here
620         OnDblclk(pNMHDR,pResult);       
621         return TRUE;
622 }
623
624 BOOL CUITreeCtrl::OnItemExpanding(NMHDR* pNMHDR, LRESULT* pResult) 
625 {
626         NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
627         CWaitCursor w;
628         // TODO: Add your control notification handler code here
629         if (pNMTreeView->action == TVE_EXPAND)
630         {
631                 Expanding(pNMTreeView);
632         }
633         else if (pNMTreeView->action == TVE_COLLAPSE)
634         {
635                 Collapsing(pNMTreeView);
636         }
637         return TRUE;
638 }
639
640 BOOL CUITreeCtrl::OnItemExpanded(NMHDR* pNMHDR, LRESULT* pResult) 
641 {
642         NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
643         // TODO: Add your control notification handler code here
644 /*      if (pNMTreeView->action == TVE_EXPAND)
645         {
646                 SetItemImage(pNMTreeView->itemNew.hItem,m_idxClosed,0);
647         }
648         else if (pNMTreeView->action == TVE_COLLAPSE)
649         {
650                 SetItemImage(pNMTreeView->itemNew.hItem,m_idxOpen,0);
651         }*/
652         return TRUE;
653 }
654
655 BOOL CUITreeCtrl::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult) 
656 {
657         //VK_PRIOR 21 page up key  
658         //VK_NEXT 22 page down key  
659         //VK_END 23 end key  
660         //VK_HOME 24 home key  
661         //VK_LEFT 25 left arrow key  
662         //VK_UP 26 up arrow key  
663         //VK_RIGHT 27 right arrow key  
664         //VK_DOWN 28 down arrow key  
665
666         NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
667         // TODO: Add your control notification handler code here
668         if ((pNMTreeView->itemNew.state & TVIS_SELECTED)) 
669         {
670                 if (pNMTreeView->action == TVC_BYMOUSE || pNMTreeView->action == TVC_UNKNOWN)
671                 {
672                         CUIListCtrlData *pData = (CUIListCtrlData*)pNMTreeView->itemNew.lParam;
673                         if (pData)
674                         {
675                                 ASSERT_KINDOF(CUIListCtrlData,pData);
676                                 SelectionChanged(pNMTreeView->itemNew.hItem,pData->GetExtData());
677                         }
678                         else
679                                 SelectionChanged(pNMTreeView->itemNew.hItem,pNMTreeView->itemNew.lParam);
680                 }
681                 else if (pNMTreeView->action == TVC_BYKEYBOARD)
682                 {
683                         CopyMemory(&m_NMTreeView,pNMTreeView,sizeof(NM_TREEVIEW));
684                         if (m_vkeydown && m_IDTimer == 0)
685                         {
686                                 TRACE0("Timer set\n");
687                                 m_IDTimer = SetTimer(2,100,NULL);
688                         }
689                 }
690         }       
691         *pResult = 0;
692         return TRUE;
693 }
694
695 BOOL CUITreeCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
696 {
697         // TODO: Add your message handler code here and/or call default
698         return CUIDragDropTree::OnMouseWheel(nFlags, zDelta, pt);
699 }
700
701 BOOL CUITreeCtrl::PreTranslateMessage(MSG* pMsg) 
702 {
703         // TODO: Add your specialized code here and/or call the base class
704         if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN)
705         {
706                 if (pMsg->wParam == VK_F10 && (GetKeyState(VK_SHIFT) < 0))
707                 {
708                         PostMessage(WM_APP_ON_CONTEXT_MENU_KEY);
709                         return TRUE;
710                 }
711                 else if (pMsg->wParam == VK_BACK)
712                 {
713                         PostMessage(WM_APP_ON_BACKSPACE_KEY);
714                         return TRUE;
715                 }
716                 else if (pMsg->wParam == VK_F2)
717                 {
718                         PostMessage(WM_APP_ON_EDIT_KEY);
719                         return TRUE;
720                 }
721                 else if (pMsg->wParam == VK_F5)
722                 {
723                         PostMessage(WM_APP_ON_REFRESH_KEY);
724                         return TRUE;
725                 }
726                 else if (pMsg->wParam == VK_DELETE)
727                 {
728                         PostMessage(WM_APP_ON_DELETE_KEY);
729                         return TRUE;
730                 }
731                 else if (pMsg->message == WM_SYSKEYDOWN && pMsg->wParam == VK_RETURN)
732                 {
733                         PostMessage(WM_APP_ON_PROPERTIES_KEY);
734                         return TRUE;
735                 }
736         }
737         
738         return CUIDragDropTree::PreTranslateMessage(pMsg);
739 }
740
741 void CUITreeCtrl::OnKeydownFolder(NMHDR* pNMHDR, LRESULT* pResult) 
742 {
743         TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR;
744         // TODO: Add your control notification handler code here
745         m_vkeydown = pTVKeyDown->wVKey;
746         *pResult = 0;
747 }
748
749 LRESULT CUITreeCtrl::OnTimerSelChange(WPARAM wParam,LPARAM lParam)
750 {
751         NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)&m_NMTreeView;
752         CUIListCtrlData *pData = (CUIListCtrlData*)pNMTreeView->itemNew.lParam;
753         if (pData)
754         {
755                 ASSERT_KINDOF(CUIListCtrlData,pData);
756                 SelectionChanged(pNMTreeView->itemNew.hItem,pData->GetExtData());
757         }
758         else
759                 SelectionChanged(pNMTreeView->itemNew.hItem,pNMTreeView->itemNew.lParam);
760         return 1L;
761 }       
762
763 void CUITreeCtrl::OnTimer( UINT nIDEvent )
764 {
765         CUIDragDropTree::OnTimer(nIDEvent);
766         if (nIDEvent == m_IDTimer)
767         {
768                 if (m_vkeydown)
769                 {
770                         SHORT sRet = GetAsyncKeyState(m_vkeydown);
771                         if (sRet >= 0)
772                         {
773                                 KillTimer(m_IDTimer);
774                                 m_IDTimer = 0;
775                                 m_vkeydown = 0;
776                                 PostMessage(WM_APP_TIMER_SEL_CHANGE);
777                         }
778                 }
779         }
780 }
781
782 LRESULT CUITreeCtrl::OnDragDrop(WPARAM wParam,LPARAM lParam)
783 {
784         if (GetDragDrop() == false)
785                 return 1L;
786         // get the info we need
787         CDD_OleDropTargetInfo *pInfo = (CDD_OleDropTargetInfo*)wParam;
788         ASSERT(pInfo);
789         if (pInfo->GetDataObject() != NULL)
790                 return DragDrop(pInfo) ? 1 : 0;
791         else
792                 return 1;
793 }
794
795 // user is currently over the tree view window
796 // return 1 if we are interested in the CB format
797 LRESULT CUITreeCtrl::OnDragOver(WPARAM wParam,LPARAM lParam)
798 {
799         if (GetDragDrop() == false)
800                 return 1L;
801         CDD_OleDropTargetInfo *pInfo = (CDD_OleDropTargetInfo*)wParam;
802         ASSERT(pInfo);
803         if (pInfo->GetDataObject() != NULL)
804                 return DragOver(pInfo) ? 1 : 0;
805         else
806                 return 1;
807 }
808
809 LRESULT CUITreeCtrl::OnDragEnter(WPARAM wParam,LPARAM lParam)
810 {
811         if (GetDragDrop() == false)
812                 return 1L;
813         CDD_OleDropTargetInfo *pInfo = (CDD_OleDropTargetInfo*)wParam;
814         ASSERT(pInfo);
815         if (pInfo->GetDataObject() != NULL)
816                 return DragEnter(pInfo) ? 1 : 0;
817         else
818                 return 1;
819 }
820
821 LRESULT CUITreeCtrl::OnDragLeave(WPARAM wParam,LPARAM lParam)
822 {
823         if (GetDragDrop() == false)
824                 return 1L;
825         CDD_OleDropTargetInfo *pInfo = (CDD_OleDropTargetInfo*)wParam;
826         ASSERT(pInfo);
827         if (pInfo->GetDataObject() != NULL)
828                 return DragLeave(pInfo) ? 1 : 0;
829         else
830                 return 1;
831 }
832
833 // Drag and drop initiated
834 // Return 1 if processed
835 LRESULT CUITreeCtrl::OnDDDoDragDrop(WPARAM wParam,LPARAM lParam)
836 {
837         if (GetDragDrop() == false)
838                 return 1L;
839         NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)wParam;
840         COleDataSource *pOleDataSource = (COleDataSource*)lParam;
841         ASSERT(pOleDataSource);
842         return DoDragDrop(pNMTreeView,pOleDataSource);
843 }
844
845 LRESULT CUITreeCtrl::OnAppPropertiesKey(WPARAM wParam, LPARAM lParam)
846 {
847         ShowProperties(GetSelectedItem());
848         return 1L;
849 }
850
851 LRESULT CUITreeCtrl::OnAppDeleteKey(WPARAM wParam, LPARAM lParam)
852 {
853         DeleteItem(GetSelectedItem());
854         return 1L;
855 }
856
857 LRESULT CUITreeCtrl::OnAppRefreshKey(WPARAM wParam, LPARAM lParam)
858 {
859         Refresh();
860         return 1L;
861 }
862
863 LRESULT CUITreeCtrl::OnAppEditKey(WPARAM wParam, LPARAM lParam)
864 {
865         EditLabel(GetSelectedItem());
866         return 1L;
867 }
868
869 LRESULT CUITreeCtrl::OnAppContextMenuKey(WPARAM wParam, LPARAM lParam)
870 {
871         CRect rc;
872         GetItemRect(GetSelectedItem(),&rc,FALSE);
873         ClientToScreen(&rc);
874         ShowPopupMenu(GetSelectedItem(),rc.CenterPoint());
875         return 1L;
876 }
877
878 LRESULT CUITreeCtrl::OnAppBackspaceKey(WPARAM wParam, LPARAM lParam)
879 {
880         GoBack(GetSelectedItem());
881         return 1L;
882 }