home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / bellhop / cgrptree.cpp < prev    next >
C/C++ Source or Header  |  1997-07-14  |  36KB  |  1,479 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1997 Microsoft Corporation.  All Rights Reserved.
  4.  *
  5.  *  File:       cGrpTree.cpp
  6.  *  Content:    An abstracted Tree control that knows how to handle
  7.  *              DirectPlay system messages and enumerations.
  8.  *
  9.  ***************************************************************************/
  10.  
  11. #include "cgrptree.h"
  12.  
  13. WNDPROC            gwpOrigEditProc;
  14.  
  15. ///////////////////////////////////////////////////////////////////////////////////////
  16. long FAR PASCAL EditCtrlSubProc(HWND hWnd, WORD wMessage,WORD wParam,LONG lParam)
  17. {
  18.  
  19.     switch (wMessage)
  20.      {
  21.  
  22.           case WM_GETDLGCODE:
  23.             return (DLGC_WANTALLKEYS |
  24.                     CallWindowProc( gwpOrigEditProc, hWnd, wMessage,
  25.                                    wParam, lParam));
  26.  
  27.           case WM_CHAR:
  28.           //Process this message to avoid message beeps.
  29.                 if ((wParam == VK_RETURN) || (wParam == VK_TAB))
  30.                     return 0;
  31.             break ;
  32.  
  33.        default:
  34.             break;
  35.  
  36.      } /* end switch */
  37.  
  38.     return (CallWindowProc( gwpOrigEditProc, hWnd, wMessage,
  39.                                    wParam, lParam));
  40.  
  41. }
  42.  
  43. ///////////////////////////////////////////////////////////////////////////////////////
  44. BOOL FAR PASCAL TV_EnumPlayersCallback(    DPID dpId,
  45.                                         DWORD dwPlayerType, 
  46.                                         LPCDPNAME lpName,
  47.                                         DWORD dwFlags, 
  48.                                         LPVOID lpContext)
  49. {
  50.     LPENUMTREESTRUCT lp = (LPENUMTREESTRUCT) lpContext;
  51.  
  52.     if (DPPLAYERTYPE_GROUP == dwPlayerType)
  53.     {
  54.         if (DPENUMGROUPS_SHORTCUT & dwFlags)
  55.         {
  56.             lp->lpTree->AddGroupToGroup( lp->dpidParent, dpId, dwFlags );
  57.         }
  58.         else
  59.         {
  60.             HRESULT    hr;
  61.             ENUMTREESTRUCT    ets;
  62.  
  63.             ets.dpidParent = dpId;
  64.             ets.lpTree = lp->lpTree;
  65.             ets.bRecursive = lp->bRecursive;
  66.  
  67.             if (NULL == lp->dpidParent)
  68.             {
  69.                 lp->lpTree->CreateGroup( dpId, lpName->lpszShortNameA, dwFlags );
  70.             }
  71.             else
  72.             {
  73.                 lp->lpTree->CreateGroupInGroup( lp->dpidParent, dpId, lpName->lpszShortNameA, dwFlags );
  74.             }
  75.  
  76.             if (ets.bRecursive)
  77.             {
  78.                 hr = lp->lpTree->m_lpDP3A->EnumGroupsInGroup(    dpId, NULL, 
  79.                                                             TV_EnumPlayersCallback, 
  80.                                                             &ets, DPENUMPLAYERS_ALL );
  81.  
  82.                 hr = lp->lpTree->m_lpDP3A->EnumGroupPlayers(    dpId, NULL, 
  83.                                                             TV_EnumPlayersCallback, 
  84.                                                             &ets, DPENUMPLAYERS_ALL );
  85.             }
  86.  
  87.         }
  88.     }
  89.     else
  90.     {
  91.         if (lp->dpidParent)
  92.         {
  93.             lp->lpTree->AddPlayerToGroup( lp->dpidParent, dpId, dwFlags );
  94.         }
  95.         else
  96.         {
  97.             lp->lpTree->CreatePlayer( dpId, lpName->lpszShortNameA, dwFlags );
  98.         }
  99.     }
  100.  
  101.     return TRUE;
  102. }
  103.  
  104. ///////////////////////////////////////////////////////////////////////////////////////
  105. int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  106. {
  107.     LPBRANCHSTRUCT    lp1 = (LPBRANCHSTRUCT) lParam1,
  108.                     lp2 = (LPBRANCHSTRUCT) lParam2;
  109.  
  110.     if ( lp1->btType < lp2->btType )
  111.     {
  112.         return -1;
  113.     }
  114.  
  115.     if (lp1->btType > lp2->btType )
  116.     {
  117.         return 1;
  118.     }
  119.  
  120.     //if we got here, they are of the same type
  121.     //so sort alphabetically
  122.  
  123.     LPDPNAME        lpdpn1 = NULL,
  124.                     lpdpn2 = NULL;
  125.     int                iRes = 0;
  126.     HRESULT            hr = DPERR_GENERIC;
  127.     CGroupTree *    lpgt = (CGroupTree *) lParamSort;
  128.  
  129.     if ((lp1->btType == BT_PLAYER ) || (lp1->btType == BT_PLAYER_IN_GROUP ))
  130.     {
  131.         hr = lpgt->GetPlayerName( lp1->dpid, &lpdpn1 );
  132.     }
  133.     else
  134.     {
  135.         hr = lpgt->GetGroupName( lp1->dpid, &lpdpn1 );
  136.     }
  137.  
  138.     if FAILED(hr)
  139.     {
  140.         goto FAILURE;
  141.     }
  142.  
  143.     if ((lp2->btType == BT_PLAYER ) || (lp2->btType == BT_PLAYER_IN_GROUP ))
  144.     {
  145.         hr = lpgt->GetPlayerName( lp2->dpid, &lpdpn2 );
  146.     }
  147.     else
  148.     {
  149.         hr = lpgt->GetGroupName( lp2->dpid, &lpdpn2 );
  150.     }
  151.  
  152.     if FAILED(hr)
  153.     {
  154.         goto FAILURE;
  155.     }
  156.  
  157.  
  158.     iRes = strcmp( lpdpn1->lpszShortNameA, lpdpn2->lpszShortNameA );
  159.  
  160.     if ( 0 == iRes )
  161.     {
  162.         //The groups have the same name.
  163.         if ( lp1->dpid <  lp2->dpid )
  164.         {
  165.             iRes = -1;
  166.         }
  167.         else if ( lp1->dpid >  lp2->dpid )
  168.         {
  169.             iRes = 1;
  170.         }
  171.         else
  172.         {
  173.             iRes = -1;
  174.         }
  175.     }
  176.  
  177. FAILURE:
  178.     if (lpdpn1)
  179.         LocalFree(lpdpn1);
  180.  
  181.     if (lpdpn2)
  182.         LocalFree(lpdpn2);
  183.  
  184.  
  185.     return iRes;
  186. }
  187.  
  188. ///////////////////////////////////////////////////////////////////////////////////////
  189. CGroupTree::CGroupTree()
  190. {
  191.  
  192.     m_hInst = GetModuleHandle( NULL );
  193.     m_hwndTreeView = NULL;
  194.     m_hwndParent = NULL;
  195.     m_lpDP3A = NULL;
  196.     m_fDragging = FALSE;
  197.     m_dpidPlayer = 0;
  198.     m_dpidLastGroup = NULL;
  199.  
  200.     // Prepare popup menus
  201.     m_hMenu = LoadMenu( m_hInst, MAKEINTRESOURCE(IDM_MENU) );
  202.     m_hRootMenu = GetSubMenu( m_hMenu, 0 );
  203.     m_hGroupMenu = GetSubMenu( m_hMenu, 1 );
  204.     m_hPlayerMenu = GetSubMenu( m_hMenu, 2 );
  205.     m_hShortcutMenu = GetSubMenu( m_hMenu, 3 );
  206.     m_hPlayerInGroupMenu= GetSubMenu( m_hMenu, 4 );
  207.  
  208.     // Prepare tree icons
  209.     m_hImageList = ImageList_Create(32, 32, 0, 8, 8);
  210.     ImageList_SetBkColor(m_hImageList, GetSysColor(COLOR_WINDOW));
  211.     m_nGroupImg = ImageList_AddIcon(m_hImageList, LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_CLOSEDDOOR)));
  212.     m_nInGroupImg = ImageList_AddIcon(m_hImageList, LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_OPENDOOR)));
  213.     m_nPlayerImg = ImageList_AddIcon(m_hImageList, LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_PLAYER)));
  214.     m_nShortcutInGroupImg = ImageList_AddIcon(m_hImageList, LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_SHORTCUT)));
  215.     m_nStagingAreaImg = ImageList_AddIcon(m_hImageList, LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_STAGINGAREA)));
  216.     m_nSpectatorImg = ImageList_AddIcon(m_hImageList, LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_SPECTATOR)));
  217.     m_nSessionInProgressImg = ImageList_AddIcon(m_hImageList, LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_SESSIONINPROGRESS)));
  218.  
  219.     ZeroMemory( &m_bsDragging, sizeof( BRANCHSTRUCT ) );
  220.  
  221. }
  222.  
  223. ///////////////////////////////////////////////////////////////////////////////////////
  224. CGroupTree::~CGroupTree()
  225. {
  226.     if (m_hImageList)
  227.     {
  228.         ImageList_Destroy( m_hImageList );
  229.         m_hImageList = NULL;
  230.     }
  231.  
  232.     DestroyMenu( m_hPlayerInGroupMenu );
  233.     DestroyMenu( m_hShortcutMenu );
  234.     DestroyMenu( m_hPlayerMenu );
  235.     DestroyMenu( m_hGroupMenu );
  236.     DestroyMenu( m_hRootMenu );
  237.     DestroyMenu( m_hMenu );
  238. }
  239.  
  240. ///////////////////////////////////////////////////////////////////////////////////////
  241. BOOL CGroupTree::Init( HWND hWnd, LPDIRECTPLAY3A lpDP3A, DPID dpidPlayer )
  242. {
  243.     if ( (hWnd) && (lpDP3A) && (dpidPlayer) )
  244.     {
  245.         m_hwndTreeView = hWnd;
  246.         m_hwndParent = GetParent( m_hwndTreeView );
  247.         m_lpDP3A = lpDP3A;
  248.         m_dpidPlayer = dpidPlayer;
  249.  
  250.         TreeView_SetImageList(hWnd, m_hImageList, TVSIL_NORMAL);
  251.         return TRUE;
  252.     }
  253.     else
  254.         return FALSE;
  255. }
  256.  
  257. ///////////////////////////////////////////////////////////////////////////////////////
  258. HRESULT CGroupTree::GetPlayerName( DPID dpidPlayer, LPDPNAME * lplpn)
  259. {
  260.     HRESULT    hr        = DPERR_GENERIC;
  261.     LPVOID    lpData    = NULL;
  262.     DWORD    dwSize    = 0;
  263.  
  264.     hr = m_lpDP3A->GetPlayerName( dpidPlayer, NULL, &dwSize );
  265.  
  266.     if (DPERR_BUFFERTOOSMALL == hr )
  267.     {
  268.         lpData = LocalAlloc( LPTR, dwSize );
  269.  
  270.         if ( NULL != lpData )
  271.         {
  272.             hr = m_lpDP3A->GetPlayerName( dpidPlayer, lpData, &dwSize );
  273.  
  274.             if (FAILED(hr))
  275.             {
  276.                 LocalFree( lpData );
  277.                 lpData = NULL;
  278.             }
  279.         }
  280.         else
  281.         {
  282.             hr = DPERR_OUTOFMEMORY;
  283.         }
  284.     }
  285.  
  286.     *lplpn = (LPDPNAME) lpData;
  287.  
  288.     return hr;
  289. }
  290.  
  291. ///////////////////////////////////////////////////////////////////////////////////////
  292. HRESULT CGroupTree::GetGroupName( DPID dpidGroup, LPDPNAME * lplpn)
  293. {
  294.     HRESULT    hr        = DPERR_GENERIC;
  295.     LPVOID            lpData = NULL;
  296.  
  297.     DWORD    dwSize    = 0;
  298.  
  299.     hr = m_lpDP3A->GetGroupName( dpidGroup, lpData, &dwSize );
  300.  
  301.     if (DPERR_BUFFERTOOSMALL == hr )
  302.     {
  303.         lpData = LocalAlloc( LPTR,  dwSize );
  304.  
  305.         if ( NULL != lpData )
  306.         {
  307.             hr = m_lpDP3A->GetGroupName( dpidGroup, lpData, &dwSize );
  308.  
  309.             if (FAILED(hr))
  310.             {
  311.                 LocalFree( lpData );
  312.                 lpData = NULL;
  313.             }
  314.         }
  315.         else
  316.         {
  317.             hr = DPERR_OUTOFMEMORY;
  318.         }
  319.     }
  320.  
  321.  
  322.     *lplpn = (LPDPNAME) lpData;
  323.  
  324.     return hr;
  325. }
  326.  
  327.  
  328. ///////////////////////////////////////////////////////////////////////////////////////
  329. HTREEITEM CGroupTree::FindItem( HTREEITEM htiSearchRoot, 
  330.                                 DPID dpidTarget, 
  331.                                 BRANCH_TYPE bt, 
  332.                                 DWORD dwSearch )
  333. {
  334.     TV_ITEM tvi;
  335.     HTREEITEM    hItem,
  336.                 htiSubSearch;
  337.     LPBRANCHSTRUCT lpbs = NULL;
  338.  
  339.     if(TVI_ROOT == htiSearchRoot)
  340.     {
  341.         hItem = TreeView_GetRoot(m_hwndTreeView);
  342.     }
  343.     else
  344.     {
  345.         hItem = TreeView_GetChild( m_hwndTreeView, htiSearchRoot );
  346.     }
  347.  
  348.     while(hItem)
  349.     {
  350.         ZeroMemory( &tvi, sizeof(TV_ITEM));
  351.         
  352.         tvi.mask            = TVIF_PARAM;
  353.         tvi.hItem           = hItem;
  354.  
  355.         TreeView_GetItem(m_hwndTreeView, &tvi);
  356.         lpbs = (LPBRANCHSTRUCT) tvi.lParam;
  357.  
  358.         if ( (lpbs->dpid == dpidTarget) && ( bt == lpbs->btType))
  359.         {
  360.             return tvi.hItem;
  361.         }
  362.  
  363.         if ( (lpbs->btType == BT_GROUP) && (ST_SEARCH_SUBGROUPS & dwSearch) )
  364.         {
  365.             htiSubSearch = FindItem( hItem, dpidTarget, bt, dwSearch );
  366.             if (htiSubSearch)
  367.                 return (htiSubSearch);
  368.         }
  369.  
  370.         hItem = TreeView_GetNextSibling(m_hwndTreeView, hItem);
  371.     }
  372.  
  373.     return NULL;
  374. }
  375.  
  376. ///////////////////////////////////////////////////////////////////////////////////////
  377. HTREEITEM CGroupTree::Insert( HTREEITEM htiParent, DPID dpID, LPSTR lpszShortNameA, BRANCH_TYPE bt, DWORD dwFlags )
  378. {
  379.     LPBRANCHSTRUCT        lpbs    = NULL;
  380.     HTREEITEM            htrItem    = NULL;
  381.  
  382.     if ( lpbs = (LPBRANCHSTRUCT) LocalAlloc( LPTR,  sizeof(BRANCHSTRUCT) ) )
  383.     {
  384.         TV_INSERTSTRUCT        tvi;
  385.         TV_SORTCB            tvscb; 
  386.  
  387.         ZeroMemory(lpbs, sizeof( BRANCHSTRUCT ) );
  388.         ZeroMemory(&tvscb, sizeof(tvscb));
  389.         ZeroMemory(&tvi, sizeof(tvi));
  390.         tvi.hParent                = htiParent;
  391.         tvi.hInsertAfter        = TVI_LAST;
  392.  
  393.         tvi.item.mask            = TVIF_IMAGE | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_TEXT;
  394.         tvi.item.pszText        = lpszShortNameA;
  395.         tvi.item.cchTextMax        = strlen(lpszShortNameA)+1;
  396.  
  397.         switch( bt)
  398.         {
  399.             case BT_PLAYER:
  400.             case BT_PLAYER_IN_GROUP:
  401.                 tvi.item.iImage = (DPPLAYER_SPECTATOR & dwFlags) ?  m_nSpectatorImg: m_nPlayerImg;
  402.                 tvi.item.iSelectedImage    = tvi.item.iImage;
  403.             break;
  404.  
  405.             case BT_GROUP:
  406.                 if (DPGROUP_STAGINGAREA & dwFlags)
  407.                 {
  408.                     HRESULT hr;
  409.                     LPDPLCONNECTION lp = NULL;
  410.                     DWORD            dwSize = 0;
  411.                     BOOL            bSessionInProgress = FALSE;
  412.  
  413.                     // if it is a staging area, check to see if the session is in progress.
  414.                     hr = IDirectPlay3_GetGroupConnectionSettings( m_lpDP3A, 0, dpID, NULL, &dwSize );
  415.                     if (DPERR_BUFFERTOOSMALL == hr )
  416.                     {
  417.                         lp = (LPDPLCONNECTION) GlobalAllocPtr( GHND, dwSize );
  418.  
  419.                         if (lp)
  420.                         {
  421.                             hr = IDirectPlay3_GetGroupConnectionSettings( m_lpDP3A, 0, dpID, lp, &dwSize );
  422.  
  423.                             if (!IsEqualGUID(lp->lpSessionDesc->guidInstance, GUID_NULL))
  424.                             {
  425.                                 // If the server has assigned an instance guid 
  426.                                 // to our connection structure, the session 
  427.                                 // has already started.
  428.  
  429.                                 bSessionInProgress = TRUE;
  430.                             }
  431.                             GlobalFreePtr(lp);
  432.                         }
  433.                     }
  434.  
  435.  
  436.                     tvi.item.iImage = (bSessionInProgress)?m_nSessionInProgressImg:m_nStagingAreaImg;
  437.                     tvi.item.iSelectedImage = tvi.item.iImage;
  438.                 }
  439.                 else
  440.                 {
  441.                     tvi.item.iImage = m_nGroupImg;
  442.                     tvi.item.iSelectedImage = m_nInGroupImg;
  443.                 }
  444.                 break;
  445.  
  446.             case BT_SHORTCUT_IN_GROUP:
  447.                 tvi.item.iImage = m_nShortcutInGroupImg;
  448.                 tvi.item.iSelectedImage    = tvi.item.iImage;
  449.             break;
  450.  
  451.             default:
  452.                 //Invalid BranchType
  453.             break;
  454.         }
  455.         tvi.item.lParam            = (LPARAM) lpbs;
  456.  
  457.         lpbs->dpid        = dpID;
  458.         lpbs->btType    = bt;
  459.         lpbs->dwFlags    = dwFlags;
  460.  
  461.         htrItem = TreeView_InsertItem( m_hwndTreeView, &tvi );
  462.  
  463.         tvscb.hParent = htiParent; 
  464.         tvscb.lpfnCompare = CompareFunc; 
  465.         tvscb.lParam = (LPARAM) this; 
  466.  
  467.         TreeView_SortChildrenCB( m_hwndTreeView, &tvscb, 0 );
  468.  
  469.         if(TVI_ROOT != htiParent)
  470.         {
  471.             TreeView_Expand(m_hwndTreeView, htiParent, TVE_EXPAND);
  472.         }
  473.  
  474.         Redraw();
  475.     }
  476.  
  477.     return htrItem;
  478. }
  479.  
  480.  
  481. ///////////////////////////////////////////////////////////////////////////////////////
  482. HRESULT CGroupTree::CreatePlayer( DPID dpidPlayer, LPSTR lpszShortNameA, DWORD dwFlags )
  483. {
  484.     /*
  485.     // We currently support only one local player. This section of code would create a
  486.     // new player at the root for each create player message received.
  487.  
  488.     LPDPNAME lpn = NULL;
  489.  
  490.     if (NULL == lpszShortNameA)
  491.     {
  492.         GetPlayerName(dpidPlayer, &lpn );
  493.         lpszShortNameA = lpn->lpszShortNameA;
  494.     }
  495.  
  496.     if (lpszShortNameA)
  497.     {
  498.         Insert( TVI_ROOT, dpidPlayer, lpszShortNameA, BT_PLAYER, dwFlags );
  499.     }
  500.  
  501.     if (lpn)
  502.         LocalFree(lpn);
  503.     */
  504.  
  505.     return DP_OK;
  506. }
  507.  
  508. ///////////////////////////////////////////////////////////////////////////////////////
  509. HRESULT CGroupTree::CreateGroup( DPID dpidGroup, LPSTR lpszShortNameA, DWORD dwFlags  )
  510. {
  511.     LPDPNAME lpn = NULL;
  512.  
  513.     if (NULL == lpszShortNameA)
  514.     {
  515.         GetGroupName(dpidGroup, &lpn );
  516.         lpszShortNameA = lpn->lpszShortNameA;
  517.     }
  518.  
  519.     if (lpszShortNameA)
  520.     {
  521.         Insert( TVI_ROOT, dpidGroup, lpszShortNameA, BT_GROUP, dwFlags );
  522.     }
  523.  
  524.     if (lpn)
  525.         LocalFree(lpn);
  526.  
  527.  
  528.     return DP_OK;
  529. }
  530.  
  531. ///////////////////////////////////////////////////////////////////////////////////////
  532. HRESULT CGroupTree::CreateGroupInGroup( DPID dpidParentGroup, DPID dpidChildGroup, LPSTR lpszShortNameA, DWORD dwFlags   )
  533. {
  534.     HTREEITEM hParentItem = NULL;
  535.  
  536.     if ( hParentItem = FindItem( TVI_ROOT, dpidParentGroup, BT_GROUP, ST_SEARCH_SUBGROUPS ) )
  537.     {
  538.         LPDPNAME lpn = NULL;
  539.  
  540.         if (NULL == lpszShortNameA)
  541.         {
  542.             GetGroupName(dpidChildGroup, &lpn );
  543.             lpszShortNameA = lpn->lpszShortNameA;
  544.         }
  545.  
  546.         if (lpszShortNameA)
  547.         {
  548.             Insert( hParentItem, dpidChildGroup, lpszShortNameA, BT_GROUP, dwFlags );
  549.         }
  550.  
  551.         if (lpn)
  552.             LocalFree(lpn);
  553.  
  554.  
  555.     }
  556.  
  557.     return DP_OK;
  558. }
  559.  
  560. ///////////////////////////////////////////////////////////////////////////////////////
  561. HRESULT CGroupTree::AddPlayerToGroup( DPID dpidGroup, DPID dpidPlayer, DWORD dwFlags )
  562. {
  563.     HRESULT    hr = DPERR_GENERIC;
  564.     LPDPNAME lpPlayerName = NULL;
  565.  
  566.     hr = GetPlayerName( dpidPlayer, &lpPlayerName );
  567.  
  568.     if (SUCCEEDED(hr))
  569.     {
  570.         HTREEITEM hParentItem = NULL;
  571.  
  572.         if ( hParentItem = FindItem( TVI_ROOT, dpidGroup, BT_GROUP, ST_SEARCH_SUBGROUPS ) )
  573.         {
  574.             Insert( hParentItem, dpidPlayer, lpPlayerName->lpszShortNameA, BT_PLAYER_IN_GROUP, dwFlags );
  575.         }
  576.     }
  577.  
  578.     if (lpPlayerName)
  579.         LocalFree( lpPlayerName);
  580.  
  581.     return hr;
  582. }
  583.  
  584. ///////////////////////////////////////////////////////////////////////////////////////
  585. HRESULT CGroupTree::AddGroupToGroup( DPID dpidParentGroup, DPID dpidShortcut, DWORD dwFlags )
  586. {
  587.     HRESULT    hr = DPERR_GENERIC;
  588.     LPDPNAME lpGroupName = NULL;
  589.  
  590.     hr = GetGroupName( dpidShortcut, &lpGroupName );
  591.  
  592.     if (SUCCEEDED(hr))
  593.     {
  594.         HTREEITEM hParentItem = NULL;
  595.  
  596.         if ( hParentItem = FindItem( TVI_ROOT, dpidParentGroup, BT_GROUP, ST_SEARCH_SUBGROUPS ) )
  597.         {
  598.             Insert( hParentItem, dpidShortcut, lpGroupName->lpszShortNameA, BT_SHORTCUT_IN_GROUP, dwFlags );
  599.         }
  600.     }
  601.  
  602.     if (lpGroupName)
  603.         LocalFree( lpGroupName);
  604.  
  605.     return hr;
  606. }
  607.  
  608. ///////////////////////////////////////////////////////////////////////////////////////
  609. HRESULT CGroupTree::DestroyPlayer(DPID dpidPlayer)
  610. {
  611.     /*
  612.  
  613.     // We are not currently adding additional players to the tree view. The 
  614.     // Code below would add a player to the root of the tree control. If you
  615.     // want that functionality.
  616.  
  617.     HTREEITEM    htiPlayer = FindItem( TVI_ROOT, dpidPlayer, BT_PLAYER, ST_NO_SUBGROUPS );
  618.  
  619.     if ( htiPlayer )
  620.     {
  621.         TreeView_DeleteItem(m_hwndTreeView, htiPlayer);
  622.         Redraw();
  623.     }
  624.     */
  625.  
  626.     return DP_OK;
  627. }
  628.  
  629. ///////////////////////////////////////////////////////////////////////////////////////
  630. HRESULT CGroupTree::DestroyGroup(DPID dpidGroup)
  631. {
  632.     HTREEITEM    htiGroup = FindItem( TVI_ROOT, dpidGroup, BT_GROUP, ST_SEARCH_SUBGROUPS );
  633.  
  634.     if ( htiGroup )
  635.     {
  636.         TreeView_DeleteItem(m_hwndTreeView, htiGroup);
  637.         Redraw();
  638.     }
  639.  
  640.     return DP_OK;
  641. }
  642.  
  643. ///////////////////////////////////////////////////////////////////////////////////////
  644. HRESULT CGroupTree::DeletePlayerFromGroup( DPID dpidGroup, DPID dpidPlayer )
  645. {
  646.     HRESULT    hr = DPERR_GENERIC;
  647.     HTREEITEM    htiParent = NULL,
  648.                 htiPlayer = NULL;
  649.  
  650.     if ( htiParent = FindItem( TVI_ROOT, dpidGroup, BT_GROUP, ST_SEARCH_SUBGROUPS ) )
  651.     {
  652.         if ( htiPlayer = FindItem( htiParent, dpidPlayer, BT_PLAYER_IN_GROUP, ST_NO_SUBGROUPS ) )
  653.         {
  654.             TreeView_DeleteItem(m_hwndTreeView, htiPlayer);
  655.             hr = DP_OK;
  656.  
  657.             Redraw();
  658.         }
  659.     }
  660.  
  661.     return hr;
  662. }
  663.  
  664. ///////////////////////////////////////////////////////////////////////////////////////
  665. HRESULT CGroupTree::DeleteGroupFromGroup( DPID dpidParentGroup, DPID dpidShortcut )
  666. {
  667.     HRESULT    hr = DPERR_GENERIC;
  668.     HTREEITEM    htiParent = NULL,
  669.                 htiShortcut = NULL;
  670.  
  671.     if ( htiParent = FindItem( TVI_ROOT, dpidParentGroup, BT_GROUP, ST_SEARCH_SUBGROUPS ) )
  672.     {
  673.         if ( htiShortcut = FindItem( htiParent, dpidShortcut, BT_SHORTCUT_IN_GROUP, ST_NO_SUBGROUPS ) )
  674.         {
  675.             TreeView_DeleteItem(m_hwndTreeView, htiShortcut );
  676.             hr = DP_OK;
  677.  
  678.             Redraw();
  679.         }
  680.     }
  681.     return hr;
  682. }
  683.  
  684. ///////////////////////////////////////////////////////////////////////////////////////
  685. HRESULT CGroupTree::SetPlayerName( DPID dpidPlayer, LPSTR lpszShortName )
  686. {
  687.     HRESULT        hr        = DPERR_GENERIC;
  688.  
  689.     hr = RecursiveRename( TVI_ROOT, dpidPlayer, lpszShortName );
  690.  
  691.     return hr; 
  692. }
  693.  
  694. ///////////////////////////////////////////////////////////////////////////////////////
  695. HRESULT CGroupTree::SetGroupName( DPID dpidPlayer, LPSTR lpszShortName )
  696. {
  697.     HRESULT        hr        = DPERR_GENERIC;
  698.  
  699.     hr = RecursiveRename( TVI_ROOT, dpidPlayer, lpszShortName );
  700.  
  701.     return hr; 
  702.  
  703. }
  704.  
  705. ///////////////////////////////////////////////////////////////////////////////////////
  706. HRESULT CGroupTree::RecursiveRename(    HTREEITEM htiSearchRoot, 
  707.                                         DPID dpidTarget, 
  708.                                         LPSTR lpszName )
  709. {
  710.     TV_ITEM tvi;
  711.     HTREEITEM    hItem;
  712.     LPBRANCHSTRUCT lpbs = NULL;
  713.  
  714.     if(TVI_ROOT == htiSearchRoot)
  715.     {
  716.         hItem = TreeView_GetRoot(m_hwndTreeView);
  717.     }
  718.     else
  719.     {
  720.         hItem = TreeView_GetChild( m_hwndTreeView, htiSearchRoot );
  721.     }
  722.  
  723.     while(hItem)
  724.     {
  725.         ZeroMemory( &tvi, sizeof(TV_ITEM));
  726.         
  727.         tvi.mask            = TVIF_PARAM;
  728.         tvi.hItem           = hItem;
  729.  
  730.         TreeView_GetItem(m_hwndTreeView, &tvi);
  731.         lpbs = (LPBRANCHSTRUCT) tvi.lParam;
  732.  
  733.         if (lpbs->dpid == dpidTarget)
  734.         {
  735.             ZeroMemory( &tvi, sizeof(TV_ITEM));
  736.  
  737.             tvi.hItem = hItem;
  738.             tvi.mask = TVIF_TEXT;
  739.             tvi.pszText = lpszName;
  740.             tvi.cchTextMax = strlen(lpszName)+1;
  741.  
  742.             TreeView_SetItem( m_hwndTreeView, &tvi );
  743.         }
  744.  
  745.         if (lpbs->btType == BT_GROUP)
  746.         {
  747.             RecursiveRename( hItem, dpidTarget, lpszName );
  748.         }
  749.  
  750.         hItem = TreeView_GetNextSibling(m_hwndTreeView, hItem);
  751.     }
  752.  
  753.     return DP_OK;
  754.  
  755. }
  756.  
  757.  
  758. ///////////////////////////////////////////////////////////////////////////////////////
  759. HRESULT CGroupTree::Refresh( BOOL bRecursive )
  760. {
  761.     HRESULT            hr = DPERR_GENERIC;
  762.     ENUMTREESTRUCT    ets;
  763.  
  764.     ets.dpidParent = NULL;
  765.     ets.lpTree       = this;
  766.     ets.bRecursive = bRecursive;
  767.  
  768.     TreeView_DeleteAllItems( m_hwndTreeView );
  769.  
  770.     if (m_lpDP3A)
  771.     {
  772.  
  773.         //We don't see other root level players in the lobby world.
  774.  
  775.         //hr = m_lpDP3A->EnumPlayers( NULL, TV_EnumPlayersCallback, &ets, DPENUMPLAYERS_ALL );
  776.  
  777.         //if (SUCCEEDED( hr ))
  778.         //{
  779.             hr = m_lpDP3A->EnumGroups( NULL, TV_EnumPlayersCallback, &ets, DPENUMPLAYERS_ALL );
  780.         //}
  781.     }
  782.  
  783.     return hr;
  784. }
  785.  
  786.  
  787. ///////////////////////////////////////////////////////////////////////////////////////
  788. BOOL CGroupTree::Update(LPVOID lpvMsg)
  789. {
  790.  
  791.     DWORD    dwMsgType        = ((LPDPMSG_GENERIC)lpvMsg)->dwType;
  792.     LPSTR    lpszShortName    = NULL;
  793.     BOOL    bReturn            = TRUE;
  794.  
  795.     // Draws the tree based strictly on system messages.
  796.     // If you place a call to this method in the area where you process
  797.     // your system messages, it should give you a good representation
  798.     // of the DirectPlay group structure as it is created.
  799.  
  800.     switch(dwMsgType)
  801.     {
  802.     case DPSYS_CREATEPLAYERORGROUP:
  803.         {
  804.             LPDPMSG_CREATEPLAYERORGROUP lp = (LPDPMSG_CREATEPLAYERORGROUP)lpvMsg;
  805.  
  806.             lpszShortName = lp->dpnName.lpszShortNameA;
  807.             if (DPPLAYERTYPE_PLAYER == lp->dwPlayerType)
  808.             {
  809.                 CreatePlayer(lp->dpId, lpszShortName, lp->dwFlags );
  810.             }
  811.             else
  812.             {
  813.                 if (NULL == lp->dpIdParent)
  814.                 {
  815.                     CreateGroup(lp->dpId, lpszShortName, lp->dwFlags );
  816.                 }
  817.                 else
  818.                 {
  819.                     CreateGroupInGroup(lp->dpIdParent, lp->dpId, lpszShortName, lp->dwFlags );
  820.                 }
  821.  
  822.             }
  823.         }
  824.         break;
  825.  
  826.         case DPSYS_ADDPLAYERTOGROUP:
  827.         {
  828.             LPDPMSG_ADDPLAYERTOGROUP lp = (LPDPMSG_ADDPLAYERTOGROUP)lpvMsg;
  829.             DWORD    dwFlags;
  830.             HRESULT hr = IDirectPlay3_GetPlayerFlags( m_lpDP3A, lp->dpIdPlayer, &dwFlags );
  831.  
  832.             if (SUCCEEDED(hr))
  833.             {
  834.                 // If I can't get his flags, he must have deleted himself
  835.                 // by the time I got this message.
  836.                 AddPlayerToGroup(lp->dpIdGroup, lp->dpIdPlayer,    dwFlags );
  837.             }
  838.  
  839.         }
  840.         break;
  841.  
  842.         case DPSYS_ADDGROUPTOGROUP:
  843.         {
  844.             LPDPMSG_ADDGROUPTOGROUP lp = (LPDPMSG_ADDGROUPTOGROUP)lpvMsg;
  845.             DWORD    dwFlags;
  846.             HRESULT hr = IDirectPlay3_GetGroupFlags( m_lpDP3A, lp->dpIdGroup, &dwFlags );
  847.  
  848.             if (SUCCEEDED(hr))
  849.             {
  850.                 // If I can't get his flags, he must have deleted himself
  851.                 // by the time I got this message.
  852.                 AddGroupToGroup(lp->dpIdParentGroup, lp->dpIdGroup, dwFlags );
  853.             }
  854.         }
  855.         break;
  856.  
  857.         case DPSYS_DESTROYPLAYERORGROUP:
  858.         {
  859.             LPDPMSG_DESTROYPLAYERORGROUP lp = (LPDPMSG_DESTROYPLAYERORGROUP) lpvMsg;
  860.  
  861.             if ( DPPLAYERTYPE_PLAYER == lp->dwPlayerType )
  862.             {
  863.                 DestroyPlayer( lp->dpId );
  864.             }
  865.             else
  866.             {
  867.                 DestroyGroup( lp->dpId );
  868.             }
  869.    
  870.         }
  871.         break;
  872.  
  873.         case DPSYS_DELETEGROUPFROMGROUP:
  874.         {
  875.             LPDPMSG_DELETEGROUPFROMGROUP lp =(LPDPMSG_DELETEGROUPFROMGROUP)lpvMsg;
  876.  
  877.             DeleteGroupFromGroup( lp->dpIdParentGroup, lp->dpIdGroup );
  878.         }
  879.         break;
  880.  
  881.         case DPSYS_DELETEPLAYERFROMGROUP:
  882.         {
  883.             LPDPMSG_DELETEPLAYERFROMGROUP lp =(LPDPMSG_DELETEPLAYERFROMGROUP)lpvMsg;
  884.  
  885.             DeletePlayerFromGroup( lp->dpIdGroup, lp->dpIdPlayer );
  886.         }
  887.         break;
  888.  
  889.         case DPSYS_SETPLAYERORGROUPDATA:
  890.         //Nothing for right now.
  891.         break;
  892.  
  893.         case DPSYS_SETPLAYERORGROUPNAME:
  894.         {
  895.             LPDPMSG_SETPLAYERORGROUPNAME lp = (LPDPMSG_SETPLAYERORGROUPNAME)lpvMsg;
  896.  
  897.             lpszShortName = lp->dpnName.lpszShortNameA;
  898.             
  899.             if ( DPPLAYERTYPE_PLAYER == lp->dwPlayerType )
  900.             {
  901.                 SetPlayerName(lp->dpId, lpszShortName );
  902.             }
  903.             else
  904.             {
  905.                 SetGroupName(lp->dpId, lpszShortName );
  906.             }
  907.  
  908.         }
  909.         break;
  910.  
  911.         default:
  912.             //Code a new message...
  913.             bReturn = FALSE;
  914.             break;
  915.     }
  916.  
  917.     return bReturn;
  918. }
  919.  
  920. ///////////////////////////////////////////////////////////////////////////////////////
  921. DPID CGroupTree::GetDPIDOfCurrentSelection( LPBRANCHSTRUCT lpbt)
  922. {
  923.  
  924.     HTREEITEM    htItem;
  925.     TV_ITEM    tvi;
  926.  
  927.     ZeroMemory( &tvi, sizeof( TV_ITEM ) );
  928.  
  929.     htItem = TreeView_GetSelection(m_hwndTreeView);
  930.  
  931.     if (htItem)
  932.     {
  933.  
  934.         tvi.mask            = TVIF_PARAM;
  935.         tvi.hItem           = htItem;
  936.  
  937.         TreeView_GetItem(m_hwndTreeView, &tvi);
  938.  
  939.         if (lpbt)
  940.         {
  941.             lpbt->dpid = ((LPBRANCHSTRUCT)(tvi.lParam))->dpid;
  942.             lpbt->btType = ((LPBRANCHSTRUCT)(tvi.lParam))->btType;
  943.         }
  944.  
  945.         return ((LPBRANCHSTRUCT) (tvi.lParam))->dpid;
  946.     }
  947.  
  948.     return 0;
  949.  
  950. }
  951.  
  952. ///////////////////////////////////////////////////////////////////////////////////////
  953. DPID CGroupTree::GetDPIDOfCurrentSelectionParent( LPBRANCHSTRUCT lpbt)
  954. {
  955.  
  956.     HTREEITEM    htChildItem, htItem;
  957.     TV_ITEM    tvi;
  958.  
  959.     ZeroMemory( &tvi, sizeof( TV_ITEM ) );
  960.  
  961.     htChildItem = TreeView_GetSelection(m_hwndTreeView);
  962.  
  963.     htItem = TreeView_GetParent( m_hwndTreeView, htChildItem );
  964.  
  965.     if (htItem)
  966.     {
  967.  
  968.         tvi.mask            = TVIF_PARAM;
  969.         tvi.hItem           = htItem;
  970.  
  971.         TreeView_GetItem(m_hwndTreeView, &tvi);
  972.  
  973.         if (lpbt)
  974.         {
  975.             lpbt->dpid = ((LPBRANCHSTRUCT)(tvi.lParam))->dpid;
  976.             lpbt->btType = ((LPBRANCHSTRUCT)(tvi.lParam))->btType;
  977.         }
  978.  
  979.         return ((LPBRANCHSTRUCT) (tvi.lParam))->dpid;
  980.     }
  981.  
  982.     return 0;
  983.  
  984. }
  985.  
  986. ///////////////////////////////////////////////////////////////////////////////////////
  987. void CGroupTree::OnBeginDrag(NM_TREEVIEW *lpnmtv) 
  988.     HIMAGELIST himl;    // handle of image list 
  989.     LPBRANCHSTRUCT    lp = NULL;
  990.     int level = 0;
  991.     UINT    xIndent = 0;
  992.     HTREEITEM htItem = NULL;
  993.  
  994.      lp = (LPBRANCHSTRUCT)lpnmtv->itemNew.lParam;
  995.     m_bsDragging = *((LPBRANCHSTRUCT)(lpnmtv->itemNew.lParam));
  996.     GetBranchStructOfParent( lpnmtv->itemNew.hItem, &m_bsParentOfDragging );
  997.  
  998.    // Tell the tree-view control to create an image to use 
  999.     // for dragging. 
  1000.     himl = TreeView_CreateDragImage(m_hwndTreeView, lpnmtv->itemNew.hItem); 
  1001.  
  1002.     // Start the drag operation. 
  1003.     RECT rcItem;
  1004.  
  1005.     TreeView_GetItemRect(m_hwndTreeView, lpnmtv->itemNew.hItem, &rcItem, FALSE);
  1006.  
  1007.     htItem = lpnmtv->itemNew.hItem;
  1008.  
  1009.     do
  1010.     {
  1011.         htItem = TreeView_GetParent( m_hwndTreeView, htItem );
  1012.         level++;
  1013.     }
  1014.     while (htItem); 
  1015.  
  1016.     xIndent = TreeView_GetIndent( m_hwndTreeView ) * level;
  1017.  
  1018.     BOOL b = ImageList_BeginDrag(    himl, 0, 
  1019.                                     lpnmtv->ptDrag.x-rcItem.left - xIndent, 
  1020.                                     lpnmtv->ptDrag.y-rcItem.top); 
  1021.   
  1022.     // Hide the mouse cursor, and direct mouse input to the 
  1023.     // parent window. 
  1024.  
  1025.     ShowCursor( FALSE );
  1026.     SetCapture(m_hwndParent); 
  1027.     m_fDragging = TRUE;
  1028.     
  1029.     ImageList_DragEnter( m_hwndTreeView, 
  1030.                         lpnmtv->ptDrag.x-rcItem.left - xIndent, 
  1031.                         lpnmtv->ptDrag.y);
  1032.     return; 
  1033.  
  1034. ///////////////////////////////////////////////////////////////////////////////////////
  1035. void CGroupTree::OnMouseMove( LONG xCur, LONG yCur) 
  1036.     HTREEITEM htiTarget;  // handle of target item 
  1037.     TV_HITTESTINFO tvht;  // hit test information 
  1038.  
  1039.     TV_ITEM    tvi;
  1040.  
  1041.     ZeroMemory(&tvi, sizeof(TV_ITEM ) );
  1042.  
  1043.     if (m_fDragging) 
  1044.     { 
  1045.  
  1046.         // Drag the item to the current position of the mouse cursor. 
  1047.         RECT rcTree, rcParent;
  1048.  
  1049.         GetWindowRect( m_hwndParent, &rcParent );
  1050.         GetWindowRect( m_hwndTreeView, &rcTree );
  1051.         ImageList_DragMove(xCur, yCur); 
  1052.  
  1053.         // Find out if the cursor is on the item. If it is, highlight 
  1054.         // the item as a drop target. 
  1055.         tvht.pt.x = xCur; 
  1056.         tvht.pt.y = yCur; 
  1057.         if ((htiTarget = TreeView_HitTest(m_hwndTreeView, &tvht)) != NULL) 
  1058.         { 
  1059.               ImageList_DragLeave( m_hwndTreeView );
  1060.             TreeView_SelectDropTarget(m_hwndTreeView, htiTarget);
  1061.             ImageList_DragEnter( m_hwndTreeView, xCur, yCur);
  1062.  
  1063.             tvi.mask            = TVIF_PARAM;
  1064.             tvi.hItem           = htiTarget;
  1065.  
  1066.             TreeView_GetItem(m_hwndTreeView, &tvi);
  1067.  
  1068.               memcpy( &m_bsDropTarget, (LPBRANCHSTRUCT)(tvi.lParam), sizeof(BRANCHSTRUCT) );
  1069.  
  1070.         }
  1071.         else
  1072.         {
  1073.             ZeroMemory( &m_bsDropTarget, sizeof(BRANCHSTRUCT) );
  1074.         }
  1075.     } 
  1076.     return; 
  1077.  
  1078. ///////////////////////////////////////////////////////////////////////////////////////
  1079. void CGroupTree::OnLButtonUp(void) 
  1080.     if (m_fDragging) 
  1081.     { 
  1082.         ImageList_EndDrag(); 
  1083.         ReleaseCapture(); 
  1084.         ShowCursor( TRUE );
  1085.         m_fDragging = FALSE;
  1086.           ImageList_DragLeave( m_hwndTreeView );
  1087.     
  1088.         if (m_bsDropTarget.dpid)
  1089.         {
  1090.             switch (m_bsDragging.btType )
  1091.             {
  1092.                 case BT_PLAYER:
  1093.                     m_lpDP3A->AddPlayerToGroup(m_bsDropTarget.dpid, m_bsDragging.dpid ); 
  1094.                     break;
  1095.  
  1096.                 case BT_GROUP:
  1097.                     m_lpDP3A->AddGroupToGroup(m_bsDropTarget.dpid, m_bsDragging.dpid );
  1098.                     break;
  1099.  
  1100.                 case BT_PLAYER_IN_GROUP:
  1101.                     if (m_bsDropTarget.dpid != m_bsParentOfDragging.dpid)
  1102.                     {
  1103.                         m_lpDP3A->AddPlayerToGroup(m_bsDropTarget.dpid, m_bsDragging.dpid );
  1104.                         m_lpDP3A->DeletePlayerFromGroup(m_bsParentOfDragging.dpid, m_bsDragging.dpid ); 
  1105.                     }
  1106.                     break;
  1107.  
  1108.                 case BT_SHORTCUT_IN_GROUP:
  1109.                     if (m_bsDropTarget.dpid != m_bsParentOfDragging.dpid)
  1110.                     {
  1111.                         m_lpDP3A->AddGroupToGroup(m_bsDropTarget.dpid, m_bsDragging.dpid ); 
  1112.                         m_lpDP3A->DeleteGroupFromGroup(m_bsParentOfDragging.dpid, m_bsDragging.dpid ); 
  1113.                     }
  1114.                     break;
  1115.             }
  1116.         }
  1117.  
  1118.         TreeView_SelectDropTarget( m_hwndTreeView, (HTREEITEM) NULL );
  1119.     } 
  1120.     return; 
  1121.  
  1122.  
  1123. ///////////////////////////////////////////////////////////////////////////////////////
  1124. void CGroupTree::Redraw(void) 
  1125. {
  1126.     RECT r;
  1127.     
  1128.     GetWindowRect(m_hwndTreeView, &r );
  1129.     InvalidateRect(m_hwndTreeView, &r, TRUE);
  1130.     UpdateWindow(m_hwndParent);
  1131.  
  1132. }
  1133.  
  1134. ///////////////////////////////////////////////////////////////////////////////////////
  1135. void CGroupTree::OnRButtonDown( LONG xCur, LONG yCur) 
  1136.     HTREEITEM htiTarget;  // handle of target item 
  1137.     TV_HITTESTINFO tvht;  // hit test information 
  1138.     LPBRANCHSTRUCT lpbs = NULL;
  1139.     HMENU hMenu = NULL;
  1140.  
  1141.     TV_ITEM    tvi;
  1142.  
  1143.     ZeroMemory(&tvi, sizeof(TV_ITEM ) );
  1144.     RECT rc;
  1145.  
  1146.     GetWindowRect( m_hwndTreeView, &rc );
  1147.  
  1148.     // Find out if the cursor is on the item. If it is, highlight 
  1149.     // the item as a drop target. 
  1150.     tvht.pt.x = xCur - rc.left; 
  1151.     tvht.pt.y = yCur - rc.top; 
  1152.     if ((htiTarget = TreeView_HitTest(m_hwndTreeView, &tvht)) != NULL) 
  1153.     { 
  1154.         TreeView_SelectItem(m_hwndTreeView, htiTarget);
  1155.  
  1156.         tvi.mask            = TVIF_PARAM;
  1157.         tvi.hItem           = htiTarget;
  1158.  
  1159.         TreeView_GetItem(m_hwndTreeView, &tvi);
  1160.  
  1161.         if (lpbs = (LPBRANCHSTRUCT)tvi.lParam)
  1162.         {
  1163.             m_dpidMenuTarget = lpbs->dpid;
  1164.  
  1165.             switch (lpbs->btType)
  1166.             {
  1167.             case BT_GROUP:
  1168.                 hMenu = m_hGroupMenu;
  1169.                 EnableMenuItem(    hMenu,    ID_GROUP_STARTSESSION,    
  1170.                     (DPGROUP_STAGINGAREA & lpbs->dwFlags)?MF_ENABLED:MF_GRAYED ); 
  1171.                 EnableMenuItem(    hMenu,    ID_GROUP_CONNECTIONSETTINGS,    
  1172.                     (DPGROUP_STAGINGAREA & lpbs->dwFlags)?MF_ENABLED:MF_GRAYED ); 
  1173.                 break;
  1174.  
  1175.             case BT_PLAYER:
  1176.                 hMenu = m_hPlayerMenu;
  1177.                 break;
  1178.  
  1179.             case BT_SHORTCUT_IN_GROUP:
  1180.                 hMenu = m_hShortcutMenu;
  1181.                 break;
  1182.  
  1183.             case BT_PLAYER_IN_GROUP:
  1184.                 hMenu = m_hPlayerInGroupMenu;
  1185.                 break;
  1186.  
  1187.             default:
  1188.                 hMenu = m_hRootMenu;
  1189.                 break;
  1190.             }
  1191.         }
  1192.     }
  1193.     else
  1194.     {
  1195.             hMenu = m_hRootMenu;
  1196.     }
  1197.  
  1198.     TrackPopupMenuEx(    hMenu,    
  1199.                         TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, 
  1200.                         xCur, yCur, m_hwndParent, NULL );    
  1201.  
  1202. ///////////////////////////////////////////////////////////////////////////////////////
  1203. void CGroupTree::OnDblClk( LONG xCur, LONG yCur) 
  1204.     HTREEITEM htiTarget;  // handle of target item 
  1205.     TV_HITTESTINFO tvht;  // hit test information 
  1206.     LPBRANCHSTRUCT lpbs = NULL;
  1207.     HMENU hMenu = NULL;
  1208.  
  1209.     TV_ITEM    tvi;
  1210.  
  1211.     ZeroMemory(&tvi, sizeof(TV_ITEM ) );
  1212.     RECT rc;
  1213.  
  1214.     GetWindowRect( m_hwndTreeView, &rc );
  1215.  
  1216.     // Find out if the cursor is on the item. If it is, highlight 
  1217.     // the item as a drop target. 
  1218.     tvht.pt.x = xCur - rc.left; 
  1219.     tvht.pt.y = yCur - rc.top; 
  1220.     if ((htiTarget = TreeView_HitTest(m_hwndTreeView, &tvht)) != NULL) 
  1221.     { 
  1222.         TreeView_SelectItem(m_hwndTreeView, htiTarget);
  1223.  
  1224.         tvi.mask            = TVIF_PARAM;
  1225.         tvi.hItem           = htiTarget;
  1226.  
  1227.         TreeView_GetItem(m_hwndTreeView, &tvi);
  1228.  
  1229.         if (lpbs = (LPBRANCHSTRUCT)tvi.lParam)
  1230.         {
  1231.             m_dpidMenuTarget = lpbs->dpid;
  1232.  
  1233.             switch (lpbs->btType)
  1234.             {
  1235.             case BT_SHORTCUT_IN_GROUP:
  1236.             case BT_GROUP:
  1237.                 if (m_dpidLastGroup != lpbs->dpid)
  1238.                 {
  1239.                     m_lpDP3A->AddPlayerToGroup(lpbs->dpid, m_dpidPlayer );
  1240.  
  1241.                     m_lpDP3A->DeletePlayerFromGroup(m_dpidLastGroup, m_dpidPlayer ); 
  1242.                     m_dpidLastGroup = lpbs->dpid;
  1243.                 }
  1244.                 break;
  1245.  
  1246.             default:
  1247.                 break;
  1248.             }
  1249.         }
  1250.     }
  1251.  
  1252. ///////////////////////////////////////////////////////////////////////////////////////
  1253. HRESULT CGroupTree::BeginLabelEdit() 
  1254. {
  1255.     // Workaround for Windows tree control/dialog odd behavior
  1256.     // Retrieve the handle of the edit control. 
  1257.     m_hwndEditCtrl = TreeView_GetEditControl( m_hwndTreeView ); 
  1258.  
  1259.     // Subclass the edit control. 
  1260.     gwpOrigEditProc = (WNDPROC) SetWindowLong(m_hwndEditCtrl, GWL_WNDPROC, (LONG) EditCtrlSubProc );
  1261.  
  1262.     return DP_OK;
  1263. }
  1264.  
  1265. ///////////////////////////////////////////////////////////////////////////////////////
  1266. void CGroupTree::EndLabelEdit( TV_DISPINFO FAR * lpTVDisp ) 
  1267. {
  1268.     HRESULT hr;
  1269.  
  1270.     // Subclass the edit control. 
  1271.     SetWindowLong(m_hwndEditCtrl, GWL_WNDPROC, (LONG) gwpOrigEditProc);
  1272.  
  1273.     if (lpTVDisp->item.pszText)
  1274.     {
  1275.         LPBRANCHSTRUCT lpbs = (LPBRANCHSTRUCT) lpTVDisp->item.lParam;
  1276.  
  1277.         hr = CheckAccessRights(lpTVDisp);
  1278.  
  1279.         if (SUCCEEDED(hr))
  1280.         {    
  1281.             DPNAME dpn;
  1282.             dpn.dwSize = sizeof(DPNAME);
  1283.             dpn.lpszShortNameA = lpTVDisp->item.pszText;
  1284.             dpn.lpszLongNameA = lpTVDisp->item.pszText;
  1285.  
  1286.             switch (lpbs->btType)
  1287.             {
  1288.             case  BT_GROUP:
  1289.                 m_lpDP3A->SetGroupName(lpbs->dpid, &dpn, DPSET_REMOTE );
  1290.                 break;
  1291.  
  1292.             case BT_PLAYER_IN_GROUP:
  1293.             case BT_PLAYER:
  1294.                 m_lpDP3A->SetPlayerName(lpbs->dpid, &dpn,  DPSET_REMOTE );
  1295.                 break;
  1296.             }
  1297.         }
  1298.         else
  1299.         {
  1300.             MessageBox( m_hwndParent, "Cannot change the name of remote players or groups", "Error", MB_OK);
  1301.             return;
  1302.         }
  1303.     }
  1304. }
  1305.  
  1306. ///////////////////////////////////////////////////////////////////////////////////////
  1307. DPID CGroupTree::GetBranchStructOfParent( HTREEITEM htChildItem, LPBRANCHSTRUCT lpbt)
  1308. {
  1309.  
  1310.     HTREEITEM    htItem;
  1311.     TV_ITEM    tvi;
  1312.  
  1313.     ZeroMemory( &tvi, sizeof( TV_ITEM ) );
  1314.     ZeroMemory( lpbt, sizeof( BRANCHSTRUCT ) );
  1315.  
  1316.     htItem = TreeView_GetParent( m_hwndTreeView, htChildItem );
  1317.  
  1318.     if (htItem)
  1319.     {
  1320.  
  1321.         tvi.mask            = TVIF_PARAM;
  1322.         tvi.hItem           = htItem;
  1323.  
  1324.         TreeView_GetItem(m_hwndTreeView, &tvi);
  1325.  
  1326.         if (lpbt)
  1327.         {
  1328.             *lpbt = *((LPBRANCHSTRUCT)(tvi.lParam));
  1329.         }
  1330.  
  1331.         return ((LPBRANCHSTRUCT) (tvi.lParam))->dpid;
  1332.     }
  1333.  
  1334.     return 0;
  1335.  
  1336. }
  1337.  
  1338. ///////////////////////////////////////////////////////////////////////////////////////
  1339. BOOL CGroupTree::OnWM_NOTIFY( WPARAM wParam, LPARAM lParam )
  1340. {
  1341.     int idCtrl = (int) wParam;
  1342.     LPNMHDR pnmh = (LPNMHDR)lParam;
  1343.     if (NULL == pnmh)
  1344.         return FALSE;
  1345.       NM_TREEVIEW        *nmtv;
  1346.     TV_ITEM            *    pItemNew = NULL;
  1347.     TV_ITEM            *    pItemOld = NULL;
  1348.     LPBRANCHSTRUCT    lpBranch = NULL;
  1349.     HRESULT hr;
  1350.  
  1351.     switch(pnmh->code)
  1352.     {
  1353.         case NM_RCLICK:
  1354.         {
  1355.             POINT p;
  1356.             GetCursorPos(&p);
  1357.             OnRButtonDown(p.x, p.y );
  1358.         }
  1359.         break;
  1360.  
  1361.         case NM_DBLCLK:
  1362.         {
  1363.             POINT p;
  1364.             GetCursorPos(&p);
  1365.             OnDblClk(p.x, p.y );
  1366.         }
  1367.         break;
  1368.  
  1369.         case TVN_BEGINLABELEDIT:
  1370.             hr = BeginLabelEdit();
  1371.  
  1372.             if (FAILED(hr))
  1373.                 return TRUE;
  1374.         break;
  1375.  
  1376.         case TVN_ENDLABELEDIT:
  1377.             EndLabelEdit((TV_DISPINFO FAR *) lParam);
  1378.         break;
  1379.  
  1380.         case TVN_SELCHANGING:
  1381.         break;
  1382.  
  1383.         case TVN_DELETEITEM:
  1384.             nmtv    = (NM_TREEVIEW *)lParam;
  1385.             pItemOld    = &nmtv->itemOld;
  1386.             LocalFree( (LPVOID) pItemOld->lParam );
  1387.         break;
  1388.  
  1389.         case TVN_BEGINDRAG: 
  1390.             OnBeginDrag((NM_TREEVIEW *) lParam); 
  1391.             break; 
  1392.  
  1393.     }
  1394.  
  1395.     return 0;
  1396. }
  1397.  
  1398. HRESULT    CGroupTree::EditLabel()
  1399. {
  1400.     HRESULT hr; // Initialized by call to CheckAccessRights()
  1401.     HTREEITEM    htItem;
  1402.     TV_ITEM    tvi;
  1403.  
  1404.     ZeroMemory( &tvi, sizeof( TV_ITEM ) );
  1405.  
  1406.     htItem = TreeView_GetSelection(m_hwndTreeView);
  1407.  
  1408.     if (htItem)
  1409.     {
  1410.         HWND hwnd = NULL;
  1411.  
  1412.         hwnd = TreeView_EditLabel( m_hwndTreeView, htItem );
  1413.         hr = (hwnd ? DP_OK : DPERR_ACCESSDENIED); 
  1414.     }
  1415.     else
  1416.     {
  1417.         hr = DPERR_ACCESSDENIED;
  1418.     }
  1419.  
  1420.     return hr;
  1421. }
  1422.  
  1423.  
  1424. HRESULT CGroupTree::CheckAccessRights(TV_DISPINFO FAR * lpTVDisp)
  1425. {
  1426.     HRESULT hr = DPERR_GENERIC;
  1427.     DWORD    dwFlags = 0;
  1428.     BRANCHSTRUCT bsCurSel;
  1429.  
  1430.     if (NULL == lpTVDisp)
  1431.     {
  1432.         GetDPIDOfCurrentSelection( &bsCurSel );
  1433.     }
  1434.     else
  1435.     {    
  1436.         bsCurSel = *((LPBRANCHSTRUCT) lpTVDisp->item.lParam);
  1437.     }
  1438.  
  1439.     switch ( bsCurSel.btType )
  1440.     {
  1441.         case BT_PLAYER:
  1442.         case BT_PLAYER_IN_GROUP:
  1443.             hr = m_lpDP3A->GetPlayerFlags( bsCurSel.dpid, &dwFlags );
  1444.             break;
  1445.  
  1446.         case BT_GROUP:
  1447.             hr = m_lpDP3A->GetGroupFlags( bsCurSel.dpid, &dwFlags );
  1448.             break;
  1449.  
  1450.         default:
  1451.             break;
  1452.     }
  1453.  
  1454.     if (FAILED(hr))
  1455.         return hr;
  1456.  
  1457.     if (dwFlags & DPPLAYER_LOCAL )
  1458.     {
  1459.         hr = DP_OK;
  1460.     }
  1461.     else
  1462.     {
  1463.         hr = DPERR_ACCESSDENIED;
  1464.     }
  1465.  
  1466.     return hr;
  1467. }
  1468.  
  1469.