home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / ADDON.PAK / PRJWIN.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  21.9 KB  |  787 lines

  1. /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2.  
  3.   prjwin.cpp
  4.   Created: 11/28/95
  5.   Copyright (c) 1995, Borland International
  6.   $Revision:   1.16  $
  7.  
  8. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
  9. #ifndef __AOEXPCH_H
  10.   #include "aoexpch.h"
  11. #endif
  12. #pragma hdrstop
  13.  
  14. #include <ideaddon\iproj.h>
  15. #include <ideaddon\iide.h>
  16. #include "tests.hrc"
  17. #include "prjview.h"
  18. #include "prjwin.h"
  19.  
  20. #define NUM_BITMAPS 3
  21. #define ID_TREEVIEW 1
  22. #define BITMAP_WIDTH   18
  23. #define BITMAP_HEIGHT 16
  24.  
  25. #define USE_QI 1
  26.  
  27. extern void CreateDetailView(ProjectNode* nodes, int nNodes);
  28.  
  29. /******************************************************************************
  30. * This file implements the addon project window. It has the following features:
  31. *
  32. *  Edit           Open the selected node into the text editor. It does not check
  33. *                  for file type.
  34. *
  35. *  New View       Create a new project window that has the same top node.
  36. *
  37. *  View from here Make the current selected node the top node in the addon
  38. *                  project view.
  39. *
  40. *  Refresh         Refresh the addon project view content. The addon project view
  41. *                  can not detect node change beside delete and add in the project.
  42. *
  43. *  Delete Node     Delete the selected node from the project
  44. *
  45. *  Add Node...     Add a node to the project.
  46. *
  47. *  Make           Make the selected node.
  48. *
  49. *  Build           Build the selected node.
  50. *
  51. *  Translate       Translate the selected node.
  52. *
  53. ******************************************************************************/
  54. class DependentCollector : public IProjectClient {
  55. public:
  56.   DependentCollector();
  57.   ~DependentCollector();
  58.  
  59.   //IUnknown members
  60.   STDMETHODIMP QueryInterface (THIS_ REFIID, LPVOID FAR *);
  61.   STDMETHODIMP_(ULONG) AddRef (THIS) { return m_RefCount++; }
  62.   STDMETHODIMP_(ULONG) Release (THIS)
  63.       {return --m_RefCount == 0 ? (delete this, 0) : m_RefCount; }
  64.  
  65.   //.... IProjectClient methods ....
  66.    virtual void OpenNotify( IPolyString * projectName );
  67.    virtual void CloseNotify();
  68.    virtual void NodeDeleteNotify( ProjectNode node );
  69.    virtual void NodeAddNotify( ProjectNode node );
  70.    virtual void NodeCopyNotify( ProjectNode, ProjectNode, BOOL ) {}
  71.    virtual void NodeMoveNotify( ProjectNode, ProjectNode ) {}
  72.    virtual void NodeChangeNotify( ProjectNode ) {}
  73.    virtual void DependencyQueryResponder( ProjectNode node, 
  74.                                           IPolyString * outputName );
  75.    virtual BOOL HandleAddNodeUI() { return FALSE; }
  76.  
  77.  
  78.    int  GetDependents(ProjectNode node, ProjectNode* nodes, int nNodes);
  79. protected:
  80.   // private variables
  81.   ULONG          m_RefCount;
  82.   IProjectServer* d_projectServer;
  83.  
  84.   ProjectNode*    d_nodes;
  85.   int            d_nNodes;
  86.   int            d_iNext;
  87. };
  88.  
  89. DependentCollector::DependentCollector() {
  90.   m_RefCount = 1;
  91.   d_projectServer = GET_INTERFACE( IProjectServer );
  92. };
  93.  
  94. DependentCollector::~DependentCollector() {
  95.   d_projectServer->Release();
  96. };
  97.  
  98.  
  99. STDMETHODIMP
  100. DependentCollector::QueryInterface (REFIID riid, LPVOID FAR* ppobj)
  101. {
  102.   if ((riid == IID_IUnknown)/* || (riid == IID_PUBLIC_)*/)
  103.   {
  104.     *ppobj = (LPVOID)this;
  105.     AddRef();
  106.    return NOERROR;
  107.   }
  108.  
  109.   *ppobj = NULL;
  110.   return ResultFromScode(E_NOINTERFACE);
  111. }
  112.  
  113. //
  114. // IProjectClient methods
  115. //
  116. void DependentCollector::OpenNotify( IPolyString * projectName ) {
  117.   projectName->Release();
  118. }
  119. //.............................................................................
  120. void DependentCollector::CloseNotify() {
  121. }
  122.  
  123. void DependentCollector::NodeDeleteNotify( ProjectNode ) {
  124. }
  125. //.............................................................................
  126. void DependentCollector::NodeAddNotify( ProjectNode ) {
  127. }
  128. //.............................................................................
  129. void DependentCollector::DependencyQueryResponder( ProjectNode node,
  130.                           IPolyString * outputName) {
  131.   outputName->Release();
  132.   if (d_iNext >= d_nNodes)
  133.    return;
  134.  
  135.   d_nodes[d_iNext] = node;
  136.   ++d_iNext;
  137. }
  138.  
  139. int DependentCollector::GetDependents(ProjectNode node, ProjectNode* nodes, int nNodes) {
  140.   d_nodes = nodes;
  141.   d_nNodes = nNodes;
  142.   d_iNext = 0;
  143.   d_projectServer->QueryDependencies(node, this);
  144.   return d_iNext;
  145. };
  146.  
  147. /******************************************************************************
  148. *
  149. * TreeController
  150. *
  151. ******************************************************************************/
  152.  
  153. TreeController::TreeController() {
  154.   d_projectServer = GET_INTERFACE(IProjectServer);
  155.   d_topNode = 0;
  156.  
  157. }
  158.  
  159. TreeController::~TreeController() {
  160.   d_projectServer->Release();
  161. }
  162.  
  163. HWND TreeController::InitWindow(HWND hwndParent) {
  164.  
  165.  
  166.   // Ensure that the common control DLL is loaded.
  167.   InitCommonControls();
  168.  
  169.   // get the size and position of the parent window
  170.   RECT rcl;          // rectangle for setting the size of the window
  171.   GetClientRect(hwndParent, &rcl);
  172.   HINSTANCE hInst = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE);
  173.  
  174.   // create the tree view window
  175.   d_hwnd = CreateWindowEx(  WS_EX_CLIENTEDGE,
  176.                             WC_TREEVIEW,                // tree view class
  177.                             TEXT(""),                  // no default text
  178.                             WS_VISIBLE | WS_CHILD
  179.                             | WS_BORDER | TVS_HASLINES
  180.                             | TVS_HASBUTTONS | TVS_LINESATROOT,
  181.                             0, 0,
  182.                             rcl.right - rcl.left, rcl.bottom - rcl.top - 15,
  183.                             hwndParent,
  184.                             (HMENU) ID_TREEVIEW,
  185.                             hInst,
  186.                             NULL );
  187.  
  188.   if (d_hwnd == NULL ) {
  189.     MessageBox (NULL, TEXT("Tree View not created!"), NULL, MB_OK );
  190.     return NULL;
  191.   }
  192.  
  193.   HIMAGELIST hIml;    // handle to the image list
  194.   // initialize the tree view window
  195.   // First, create the image list we will need
  196.   hIml = ImageList_Create( BITMAP_WIDTH,  // width
  197.                         BITMAP_HEIGHT,                      // height
  198.                         0,                                  // flags
  199.                         NUM_BITMAPS,                        // number of bitmaps
  200.                         0 );                                // amount to grow
  201.  
  202.   HBITMAP hBmp;      // handle to a bitmap
  203.   // load the bitmaps and add them to the image lists
  204.   hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_CLOSED_FOLDER));
  205.   d_idxCloseFolder = ImageList_Add(hIml,        // handle to the imagelist
  206.                            hBmp,        // handle to the bitmap
  207.                            NULL);      // handle of the bitmap mask
  208.  
  209.   hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_OPEN_FOLDER));
  210.   d_idxOpenFolder = ImageList_Add(hIml, hBmp, NULL);
  211.  
  212.   hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_FILE));
  213.   d_idxFile = ImageList_Add(hIml, hBmp, NULL);
  214.  
  215.   // Associate the image list with the tree
  216.   TreeView_SetImageList(d_hwnd, hIml, TVSIL_NORMAL);
  217.  
  218.   return d_hwnd;
  219. }
  220.  
  221. void TreeController::GetItem(HTREEITEM  ti, TV_ITEM& item, unsigned mask) {
  222.   item.hItem = ti;
  223.   item.mask = mask;
  224.  
  225.   TreeView_GetItem(d_hwnd, &item);
  226. }
  227.  
  228. void TreeController::SetImage(HTREEITEM ti, unsigned idxImage) {
  229.   TV_ITEM item;
  230.   GetItem(ti, item, TVIF_IMAGE | TVIF_SELECTEDIMAGE);
  231.   item.iImage       = idxImage;
  232.   item.iSelectedImage= idxImage;
  233.   TreeView_SetItem(d_hwnd, &item);
  234. };
  235.  
  236. void TreeController::SetTopNode(ProjectNode topNode) {
  237.   d_topNode = topNode;
  238. };
  239.  
  240. //
  241. // initialize the treeview by adding project nodes
  242. //
  243. BOOL TreeController::AddTreeViewItems() {
  244.  
  245.   //
  246.   // by default, display from project's top node
  247.   //
  248.   if (!d_topNode)
  249.     d_topNode = d_projectServer->QueryTopNode();
  250.  
  251.   ProjectNode topNode = d_topNode;
  252.  
  253.   TreeView_DeleteAllItems(d_hwnd);
  254.  
  255.   IProjectNodeInfo* pni = d_projectServer->QueryNodeInfo( topNode );
  256.  
  257.   IPolyString* name = pni->GetInputLocation();
  258.   if (name) {
  259.     HTREEITEM hTRoot = AddOneItem((HTREEITEM)NULL
  260.                                  , name->GetCstr()
  261.                                  , (HTREEITEM)TVI_ROOT
  262.                                  , d_idxCloseFolder
  263.                                  , (LPARAM)topNode);
  264.     name->Release();
  265.     AddBranch(hTRoot, topNode);
  266.   }
  267.   return TRUE;
  268. }
  269.  
  270. //
  271. // get corresponding ProjectNode of a TREEITEM
  272. //
  273. ProjectNode TreeController::GetNodeFromItem(HTREEITEM ti) {
  274.   TV_ITEM item;
  275.  
  276.   GetItem(ti, item, TVIF_PARAM);
  277.   return (ProjectNode)item.lParam;
  278. }
  279.  
  280. HTREEITEM TreeController::FindItem(HTREEITEM hitem, ProjectNode node) {
  281.  
  282.   ProjectNode iNode = GetNodeFromItem(hitem);
  283.   if (node == iNode)
  284.     return hitem;
  285.  
  286.   hitem = TreeView_GetChild(d_hwnd, hitem);
  287.  
  288.   while (hitem) {
  289.     HTREEITEM itemFound = FindItem(hitem, node);
  290.     if (itemFound)
  291.       return itemFound;
  292.     hitem = TreeView_GetNextSibling(d_hwnd, hitem);
  293.   }
  294.   return 0;
  295. };
  296.  
  297. HTREEITEM TreeController::GetItemFromNode(ProjectNode node) {
  298.  
  299.   HTREEITEM root = TreeView_GetRoot(d_hwnd);
  300.   return FindItem(root, node);
  301. }
  302. //
  303. // add project nodes to the treeview
  304. //
  305. unsigned TreeController::AddBranch(HTREEITEM tiParent, ProjectNode node) {
  306.   IProjectNodeInfo* pni = d_projectServer->QueryNodeInfo( node );
  307.  
  308.   ProjectNode childNode = pni->GetFirstChild();
  309.   HTREEITEM tiPrevChild = TVI_FIRST;
  310.   unsigned counter = 0;
  311.  
  312.   //
  313.   // add all children of tiParent
  314.   //
  315.   while (childNode) {
  316.  
  317.     IProjectNodeInfo* childNodeInfo = d_projectServer->QueryNodeInfo( childNode );
  318.     IPolyString* name = childNodeInfo->GetInputLocation();
  319.     tiPrevChild = AddOneItem(tiParent, name->GetCstr(), tiPrevChild, d_idxFile, childNode);
  320.     name->Release();
  321.     //
  322.     // increment child counter
  323.     //
  324.     ++counter;
  325.     //
  326.     // add children for the child that is just added
  327.     //
  328.     counter += AddBranch(tiPrevChild, childNode);
  329.     //
  330.     // get sibling
  331.     //
  332.     childNode = childNodeInfo->GetNextSibling();
  333.     childNodeInfo->Release();
  334.   };
  335.   pni->Release();
  336.   //
  337.   // If tiParent has children, change parent's image to close folder
  338.   //
  339.   if (counter) {
  340.     SetImage(tiParent, d_idxCloseFolder);
  341.   }
  342.   return counter;
  343. }
  344.  
  345. //
  346. // change image when user expand/collapse a tree item
  347. //
  348. void TreeController::OnExpanded(LPNM_TREEVIEW lpNMTreeView) {
  349.   TV_ITEM      tviNew, tviChange, tviCurrent;
  350.  
  351.   tviNew = lpNMTreeView->itemNew;
  352.  
  353.   //
  354.   // get current assigned image
  355.   // 
  356.   tviCurrent.hItem = tviNew.hItem;
  357.   tviCurrent.mask = TVIF_IMAGE;
  358.   TreeView_GetItem (d_hwnd, &tviCurrent);
  359.  
  360.   //
  361.   // toggle image
  362.   //  if action == expand and image == close folder
  363.   //    image = open folder
  364.   //
  365.   tviChange.hItem = tviNew.hItem;
  366.   tviChange.mask  = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  367.   if ((lpNMTreeView->action == TVE_EXPAND) &&
  368.       (tviCurrent.iImage == d_idxCloseFolder))  {       
  369.     tviChange.iImage        = d_idxOpenFolder;
  370.     tviChange.iSelectedImage= d_idxOpenFolder;
  371.   } else {        
  372.     tviChange.iImage        = d_idxCloseFolder;
  373.     tviChange.iSelectedImage= d_idxCloseFolder;
  374.   }
  375.   TreeView_SetItem(d_hwnd, &tviChange);
  376. }
  377.  
  378. void TreeController::AddNode(ProjectNode node) {
  379.   IProjectNodeInfo* nodeInfo =  d_projectServer->QueryNodeInfo(node);
  380.   if (nodeInfo) {
  381.     ProjectNode parentNode = nodeInfo->GetParent();
  382.     IPolyString* name = nodeInfo->GetInputLocation();
  383.  
  384.     HTREEITEM tiParent = GetItemFromNode(parentNode);
  385.     AddOneItem(tiParent, name->GetCstr(), TVI_FIRST, d_idxFile, node);
  386.  
  387.     TV_ITEM item;
  388.     item.hItem = tiParent;
  389.     item.mask = TVIF_IMAGE;
  390.  
  391.     if ( TreeView_GetItem(d_hwnd, &item) ) {
  392.       
  393.       //
  394.       // if it is a file, make it a folder
  395.       //
  396.       if ( item.iImage == d_idxFile )
  397.         SetImage(tiParent, d_idxCloseFolder);
  398.  
  399.       nodeInfo->Release();
  400.       name->Release();
  401.     }
  402.   }
  403. };
  404.  
  405. void TreeController::DeleteTreeItem(ProjectNode node) {
  406.   HTREEITEM hitem = GetItemFromNode(node);
  407.   if (hitem)
  408.     TreeView_DeleteItem(d_hwnd, hitem);
  409. };
  410.  
  411. void TreeController::RemoveNodeFromProject(ProjectNode node) {
  412.  
  413.   d_projectServer->NodeRemove(node);
  414. }
  415.  
  416. void TreeController::AddNodeToProject(ProjectNode node, char* name) {
  417.    d_projectServer->NodeAdd(node, MakePolyString(name));
  418. }
  419.  
  420. /****************************************************************************
  421. * TreeModel
  422. *
  423. ****************************************************************************/
  424.  
  425. TreeModel::TreeModel(HWND hwnd) {
  426.  
  427.   d_makeServer  = GET_INTERFACE(IMakeServer);
  428.   d_toolServer  = GET_INTERFACE(IToolServer);
  429.   d_hwnd = hwnd;
  430.   d_tc = 0;
  431.   d_selectedItem = 0;
  432.   d_client = 0;
  433. }
  434.  
  435. TreeModel::~TreeModel() {
  436.   d_makeServer->Release();
  437.   d_toolServer->Release();
  438.   if ( d_client ) {
  439.     d_client->Stop();
  440.     d_client->Release();
  441.   }
  442. };
  443.  
  444.  
  445. void TreeModel::SetProjectViewClient(IProjectViewClient* client) {
  446.   d_client = client;
  447. };
  448.  
  449.         
  450. void TreeModel::SetSelected(HTREEITEM item) {
  451.   d_selectedItem = item;
  452. }
  453.  
  454. ProjectNode TreeModel::GetSelectedNode() {
  455.   return d_tc->GetNodeFromItem(d_selectedItem);
  456. };
  457.  
  458. BOOL TreeModel::GetNewNodeName(char* buf, int bufSize) {
  459.   
  460.   OPENFILENAME ofn;      /* common dialog box structure  */
  461.  
  462.   memset(&ofn, 0, sizeof(ofn));
  463.   char szFilter[260] = "Files(*.*)\0*.*\0\0";    /* filter string                */
  464.   
  465.   /* Set the members of the OPENFILENAME structure. */
  466.  
  467.   ofn.lStructSize = sizeof(OPENFILENAME);
  468.   ofn.hwndOwner = d_hwnd;
  469.   ofn.lpstrFilter = szFilter;
  470.   ofn.nFilterIndex = 1;
  471.   ofn.lpstrFile = buf;
  472.   ofn.nMaxFile = bufSize;
  473.   ofn.lpstrTitle = "AddOn - add node";
  474.   ofn.Flags = OFN_EXPLORER;
  475.  
  476.   /* Display the Open dialog box. */
  477.  
  478.   return GetOpenFileName(&ofn);
  479.  
  480. }
  481.  
  482. void TreeModel::OnCommand(WORD wID, WORD /*wNotifyCode*/) {
  483.   switch (wID) {
  484.     case IDM_MAKE:
  485.     {
  486.       ProjectNode nodes[1];
  487.       nodes[0] = GetSelectedNode();
  488.       d_makeServer->MakeNodes(MM_Make, nodes, 1);
  489.     }
  490.     break;
  491.     case IDM_BUILD:
  492.     {
  493.       ProjectNode nodes[1];
  494.       nodes[0] = GetSelectedNode();
  495.       d_makeServer->MakeNodes(MM_Build, nodes, 1);
  496.     }
  497.     break;
  498.     case IDM_TRANSLATE:
  499.     {
  500.       ProjectNode nodes[1];
  501.       nodes[0] = GetSelectedNode();
  502.       d_makeServer->MakeNodes(MM_Translate, nodes, 1);
  503.     }
  504.     break;
  505.     case IDM_VIEW:
  506.     {
  507.       ToolObj toolObj = d_toolServer->ToolFind( ::MakePolyString ( "EditText" ) );
  508.       d_toolServer->ToolInvoke(toolObj, GetSelectedNode());
  509.     }
  510.     break;
  511.     case IDM_REFRESH:
  512.     {
  513.       d_tc->AddTreeViewItems();
  514.     }
  515.     break;
  516.     case IDM_CREATENEWVIEW:
  517.     {
  518.       CreateNewProjectView(d_tc->GetTopNode());
  519.     }
  520.     break;
  521.     case IDM_VIEWFROMHERE:
  522.     {
  523.       d_tc->SetTopNode(GetSelectedNode());
  524.       d_tc->AddTreeViewItems();
  525.     }
  526.     break;
  527.     case IDM_DELETENODE:
  528.     {
  529.       d_tc->RemoveNodeFromProject(GetSelectedNode());
  530.     }
  531.     break;
  532.     case IDM_ADDNODE:
  533.     {
  534.     char buf[MAX_PATH] = "";
  535.       if (GetNewNodeName(buf, sizeof(buf))) {
  536.       d_tc->AddNodeToProject(GetSelectedNode(), buf);
  537.     }
  538.    }
  539.    break;
  540.    case IDM_VIEWDEP:
  541.    {
  542.     ProjectNode nodes[100]; // only do up to 100 nodes
  543.     int nNodes = DependentCollector().GetDependents(GetSelectedNode()
  544.                                    , nodes
  545.                                    , sizeof(nodes)/sizeof(nodes[0]));
  546.     CreateDetailView(nodes, nNodes);
  547.    }
  548.     break;
  549.   };
  550. };
  551.  
  552. void TreeModel::Resize(int w, int h) {
  553.   MoveWindow(d_tc->d_hwnd, 0, 0, w, h, TRUE);
  554. }
  555.  
  556. void TreeModel::OnNodeDeleted(ProjectNode node) {
  557.   d_tc->DeleteTreeItem(node);
  558. };
  559.  
  560. void TreeModel::OnNodeAdd(ProjectNode node) {
  561.     d_tc->AddNode(node);
  562. };
  563.  
  564. /***************************************************************************
  565. *   FUNCTION: AddOneItem(HTREEITEM, LPSTR, HTREEITEM, int)
  566. *
  567. *   PURPOSE: Inserts a tree view item in the specified place. 
  568. *
  569. ****************************************************************************/
  570.  
  571. HTREEITEM TreeController::AddOneItem( HTREEITEM hParent
  572.                                     , LPCSTR szText
  573.                                     , HTREEITEM hInsAfter
  574.                                     , int iImage
  575.                                     , LPARAM lParam)
  576. {
  577.   HTREEITEM hItem;
  578.   TV_ITEM tvI;
  579.   TV_INSERTSTRUCT tvIns;
  580.  
  581.   tvI.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
  582.   tvI.pszText = (char*)szText;
  583.   tvI.cchTextMax = lstrlen(szText);
  584.   tvI.iImage = iImage;
  585.   tvI.iSelectedImage = iImage;
  586.   tvI.lParam = lParam;
  587.  
  588.   tvIns.item = tvI;
  589.   tvIns.hInsertAfter = hInsAfter;
  590.   tvIns.hParent = hParent;
  591.   
  592.   hItem = (HTREEITEM)SendMessage(d_hwnd, TVM_INSERTITEM, 0,
  593.     (LPARAM)(LPTV_INSERTSTRUCT)&tvIns);
  594.  
  595.   return (hItem);
  596. }
  597.  
  598. /****************************************************************************
  599. *
  600. *   Context Menu Processing
  601. *
  602. ****************************************************************************/
  603. VOID APIENTRY DisplayContextMenu(HWND hwnd, POINT pt)
  604. {
  605.   // Load the menu resource.
  606.  
  607.   HINSTANCE hInst = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
  608.   HMENU hmenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_ADDON_POPUP));  // top-level menu 
  609.   if (hmenu == NULL)
  610.       return;
  611.  
  612.   HMENU hmenuTrackPopup = GetSubMenu(hmenu, 0);  // pop-up menu
  613.  
  614.   // Display the floating pop-up menu. Track the right mouse
  615.   // button on the assumption that this function is called
  616.   // during WM_CONTEXTMENU processing.
  617.  
  618.   TrackPopupMenu(hmenuTrackPopup,
  619.           TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  620.           pt.x, pt.y, 0, hwnd, NULL);
  621.  
  622.   // Destroy the menu.
  623.  
  624.   DestroyMenu(hmenu);
  625. }
  626.  
  627.  
  628. BOOL WINAPI OnContextMenu(HWND hwnd, int x, int y)
  629. {
  630.   RECT rc;                    // client area of window 
  631.   POINT pt = { x, y };        // location of mouse click 
  632.  
  633.   // Get the bounding rectangle of the client area. 
  634.  
  635.   GetClientRect(hwnd, &rc);
  636.  
  637.   // Convert the mouse position to client coordinates. 
  638.  
  639.   ScreenToClient(hwnd, &pt);
  640.  
  641.   // If the position is in the client area, display a floating 
  642.   // pop-up menu. 
  643.  
  644.   if (PtInRect(&rc, pt)) {
  645.       ClientToScreen(hwnd, &pt);
  646.       DisplayContextMenu(hwnd, pt);
  647.       return TRUE;
  648.   }
  649.   // Return FALSE if no menu is displayed. 
  650.   return FALSE;
  651. }
  652.  
  653.  
  654. LONG APIENTRY TreeViewWndProc(
  655.   HWND hWnd,                /* window handle                   */
  656.   UINT message,            /* type of message                */
  657.   UINT wParam,              /* additional information         */
  658.   LONG lParam)              /* additional information         */
  659. {
  660.   TreeModel* tm = GetTreeModelFromHWND(hWnd);
  661.   switch (message)
  662.   {
  663.  
  664.     case WM_CREATE:
  665.     {
  666.       // Create the tree view window and initialize its
  667.       // image list
  668.       TreeController* tc = new TreeController();
  669.       TreeModel* tm = new TreeModel(hWnd);
  670.       SetWindowLong(hWnd, GWL_USERDATA, (long)tm);
  671.  
  672.       tc->InitWindow(hWnd);
  673.       tm->Attach(tc);
  674.    }
  675.  
  676.       break;          
  677.     case WM_SIZE:
  678.     {
  679.       tm->Resize(LOWORD(lParam), HIWORD(lParam));
  680.     }
  681.       break;
  682.     case WM_CONTEXTMENU:
  683.      if (!OnContextMenu(hWnd, LOWORD(lParam), HIWORD(lParam)))
  684.        return DefWindowProc(hWnd, message, wParam, lParam);
  685.      break;
  686.     case WM_COMMAND:
  687.     {
  688.      tm->OnCommand(LOWORD(wParam), HIWORD(wParam)); 
  689.     }
  690.      break;
  691.  
  692.     case WM_NOTIFY:
  693.     {
  694.       LPNMHDR pnmh = (LPNMHDR) lParam;
  695.       switch (pnmh->code) {
  696.         case TVN_SELCHANGED:
  697.         {
  698.           LPNM_TREEVIEW ptv = (LPNM_TREEVIEW)lParam;
  699.           tm->SetSelected(ptv->itemNew.hItem);
  700.         };
  701.         break;
  702.         case TVN_ITEMEXPANDED:
  703.         {
  704.           tm->GetController()->OnExpanded((LPNM_TREEVIEW)lParam);
  705.         }
  706.         break;
  707.       };
  708.     }
  709.       break;
  710.     case UM_SETROOT:
  711.     {
  712.       TreeController* tc = tm->GetController();
  713.       tc->SetTopNode((ProjectNode)lParam);
  714.       tc->AddTreeViewItems();
  715.     }
  716.       break;
  717.     case WM_DESTROY:
  718.     {
  719.       TreeController* tc = tm->GetController();
  720.       delete tm;
  721.       delete tc;
  722.       SetWindowLong(hWnd, GWL_USERDATA, 0L);
  723.     }
  724.     default:
  725.       return (DefWindowProc(hWnd, message, wParam, lParam));
  726.   }
  727.   return (0);
  728. }
  729.  
  730. BOOL RegisterTreeViewClass(HINSTANCE hInstance)      /* current instance             */
  731. {
  732.   WNDCLASS  wcTreeView;
  733.  
  734.   if ( GetClassInfo(hInstance,              // handle of application instance
  735.                     TEXT("TreeViewWClass"), // address of class name string
  736.                     &wcTreeView)            // address of structure for class data
  737.       ) {
  738.     return TRUE;
  739.   }
  740.  
  741.   /* Fill in window class structure with parameters that describe the      */
  742.   /* main window.                                                          */
  743.  
  744.   wcTreeView.style = 0;                    
  745.   wcTreeView.lpfnWndProc = (WNDPROC)TreeViewWndProc; 
  746.   wcTreeView.cbClsExtra = 0;              
  747.   wcTreeView.cbWndExtra = 0;              
  748.   wcTreeView.hInstance = hInstance;
  749.   wcTreeView.hIcon = NULL;
  750.   wcTreeView.hCursor = LoadCursor(NULL, IDC_ARROW);
  751.   wcTreeView.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  752.   wcTreeView.lpszMenuName = NULL; 
  753.   wcTreeView.lpszClassName = TEXT("TreeViewWClass");
  754.  
  755.   return (RegisterClass(&wcTreeView));
  756. }
  757.  
  758. /****************************************************************************
  759. *
  760. *   FUNCTION: CreateTreeWindow(HINSTANCE hInstance, HWND hwndParent)
  761. *
  762. *   PURPOSE:  Creates a treeview window
  763. *
  764. ****************************************************************************/
  765.  
  766. HWND CreateTreeWindow(HINSTANCE hInstance, HWND hwndParent) {
  767.  
  768.   RegisterTreeViewClass(hInstance);
  769.   return CreateWindow(
  770.                         TEXT("TreeViewWClass"),          
  771.                         TEXT("TreeView Sample"), 
  772.                         WS_CHILD|WS_VISIBLE,
  773.                         CW_USEDEFAULT,
  774.                         CW_USEDEFAULT,
  775.                         CW_USEDEFAULT,
  776.                         CW_USEDEFAULT,
  777.                         hwndParent,              
  778.                         NULL,              
  779.                         hInstance,          
  780.                         NULL);
  781. };
  782.  
  783.  
  784. 
  785.