home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / quickfil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  23.4 KB  |  911 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. //        This file contains the implementations of the various Bookmark Quick
  20. //        File classes.
  21.  
  22.  
  23. /**    INCLUDE    **/
  24. #include "stdafx.h"
  25. #include "cxicon.h"
  26. #include "quickfil.h"
  27.  
  28. #ifdef _DEBUG
  29. #undef THIS_FILE
  30. static char    BASED_CODE THIS_FILE[] = __FILE__;
  31. #endif
  32.  
  33. typedef struct {
  34.     UINT nCommand;
  35.     int  nPosition;
  36. } MnemonicStruct;
  37.  
  38.  
  39. /****************************************************************************
  40. *
  41. *    Class: CTreeItem
  42. *
  43. *    DESCRIPTION:
  44. *        This class provides an abstract object for representing an item
  45. *        within a hierarchical tree.
  46. *
  47. ****************************************************************************/
  48.  
  49. /****************************************************************************
  50. *
  51. *    CTreeItem::CTreeItem
  52. *
  53. *    PARAMETERS:
  54. *        pImg        - image to be drawn with this item (NULL if none)
  55. *        uID            - unique item identifier
  56. *        strLabel    - text label for this item
  57. *
  58. *    RETURNS:
  59. *        N/A
  60. *
  61. *    DESCRIPTION:
  62. *        Constructor.
  63. *
  64. ****************************************************************************/
  65.  
  66. CTreeItem::CTreeItem(CBitmap * pUnselectedImg, CBitmap *pSelectedImg, const UINT uID, const CString & strLabel, CMenu *pSubMenu)
  67. {
  68.     m_pUnselectedImg = pUnselectedImg;
  69.     m_pSelectedImg = pSelectedImg;
  70.  
  71.     m_uID = uID;
  72.     m_strLabel = strLabel;
  73.  
  74.     m_unselectedBitmapSize.cx = m_unselectedBitmapSize.cy = 0;
  75.     m_selectedBitmapSize.cx = m_selectedBitmapSize.cy = 0;
  76.     m_textSize.cx = m_textSize.cy = 0;
  77.     m_accelSize.cx = m_accelSize.cy =0;
  78.     m_pSubMenu = pSubMenu;
  79.  
  80. } // END OF    FUNCTION CTreeItem::CTreeItem()
  81.  
  82. /****************************************************************************
  83. *
  84. *    CTreeItem::~CTreeItem
  85. *
  86. *    PARAMETERS:
  87. *        N/A
  88. *
  89. *    RETURNS:
  90. *        N/A
  91. *
  92. *    DESCRIPTION:
  93. *        Destructor.
  94. *
  95. ****************************************************************************/
  96.  
  97. CTreeItem::~CTreeItem()
  98. {
  99.     if(m_pSubMenu)
  100.         delete m_pSubMenu;
  101. } // END OF    FUNCTION CTreeItem::~CTreeItem()
  102.  
  103.  
  104. /****************************************************************************
  105. *
  106. *    Class: CTreeItemList
  107. *
  108. *    DESCRIPTION:
  109. *        This is a collection class for holding CTreeItem objects.
  110. *
  111. ****************************************************************************/
  112.  
  113. /****************************************************************************
  114. *
  115. *    CTreeItemList::CTreeItemList
  116. *
  117. *    PARAMETERS:
  118. *        None
  119. *
  120. *    RETURNS:
  121. *        N/A
  122. *
  123. *    DESCRIPTION:
  124. *        Constructor
  125. *
  126. ****************************************************************************/
  127.  
  128. CTreeItemList::CTreeItemList()
  129. {
  130.  
  131. } // END OF    FUNCTION CTreeItemList::CTreeItemList()
  132.  
  133. /****************************************************************************
  134. *
  135. *    CTreeItemList::~CTreeItemList
  136. *
  137. *    PARAMETERS:
  138. *        N/A
  139. *
  140. *    RETURNS:
  141. *        N/A
  142. *
  143. *    DESCRIPTION:
  144. *        Destructor. We provide auto-cleanup for the objects in the collection.
  145. *
  146. ****************************************************************************/
  147.  
  148. CTreeItemList::~CTreeItemList()
  149. {
  150.     int nCount = GetSize();
  151.  
  152.     for (int i = 0; i < nCount; i++)
  153.     {
  154.         CTreeItem * pItem = Get(i);
  155.         if (pItem != NULL)
  156.         {
  157.             delete pItem;
  158.         }
  159.     }
  160.     RemoveAll();
  161.  
  162.  
  163. } // END OF    FUNCTION CTreeItemList::~CTreeItemList()
  164.  
  165.  
  166. /****************************************************************************
  167. *
  168. *    Class: CTreeMenu
  169. *
  170. *    DESCRIPTION:
  171. *        This class provides a custom, self drawing menu object for displaying
  172. *        graphics as well as text in a menu item.
  173. *
  174. ****************************************************************************/
  175.  
  176. /****************************************************************************
  177. *
  178. *    CONSTANTS
  179. *
  180. ****************************************************************************/
  181. static int nIMG_SPACE = 3;    // Gap between image and text in menu item
  182.  
  183. /****************************************************************************
  184. *
  185. *    CTreeMenu::CTreeMenu
  186. *
  187. *    PARAMETERS:
  188. *        None
  189. *
  190. *    RETURNS:
  191. *        N/A
  192. *
  193. *    DESCRIPTION:
  194. *        Constructor.
  195. *
  196. ****************************************************************************/
  197.  
  198. CTreeMenu::CTreeMenu()
  199. {
  200.     m_WidestImage=0;
  201.     m_WidestText=0;
  202.     m_WidestAccelerator=0;
  203.     m_pParent = NULL;
  204.  
  205. } // END OF    FUNCTION CTreeMenu::CTreeMenu()
  206.  
  207. CTreeMenu::~CTreeMenu()
  208. {
  209.     m_itemList.RemoveAll();
  210.  
  211.     DeleteMnemonics();
  212.  
  213. }
  214.  
  215. void CTreeMenu::DeleteMnemonics(void)
  216. {
  217.     POSITION pos;
  218.     WORD dwKey;
  219.     MnemonicStruct *pMnemonic = NULL;
  220.  
  221.     // also destroy bitmaps;
  222.     pos = m_mnemonicMap.GetStartPosition();
  223.  
  224.     while(pos)
  225.     {
  226.         m_mnemonicMap.GetNextAssoc(pos, dwKey,(void *&)pMnemonic);
  227.         delete pMnemonic;
  228.     }
  229.  
  230.     m_mnemonicMap.RemoveAll();
  231.  
  232. }
  233.  
  234. /****************************************************************************
  235. *
  236. *    CTreeMenu::AddItem
  237. *
  238. *    PARAMETERS:
  239. *        pItem        - pointer to abstract item
  240. *        hSubMenu    - handle of sub-menu is this item is a new node
  241. *
  242. *    RETURNS:
  243. *        TRUE if successful.
  244. *
  245. *    DESCRIPTION:
  246. *        This function is called to add a new menu item to the main trunk. The
  247. *        new item can also be a branch, if hSubMenu is set properly.
  248. *****************************************************************************/
  249.  
  250. BOOL CTreeMenu::AddItem(CTreeItem * pItem, int nPosition /*=0*/, CTreeMenu *pSubMenu /*= NULL*/, 
  251.                         void* pIcon /* = NULL */, IconType nIconType /* = BUILTIN_BITMAP */)
  252. {
  253.     BOOL bRtn = FALSE;
  254.     
  255.     
  256.     m_itemList.Add(pItem);
  257.  
  258.     pItem->SetIcon(pIcon, nIconType);
  259.  
  260.     if (pSubMenu != NULL)
  261.     {
  262.         
  263.         bRtn = InsertMenu(nPosition, MF_BYPOSITION | MF_OWNERDRAW | MF_POPUP, (UINT)pSubMenu->GetSafeHmenu(),
  264.             (const char *)pItem);
  265.     }
  266.     else
  267.     {
  268.         bRtn = InsertMenu(nPosition, MF_BYPOSITION | MF_OWNERDRAW, pItem->GetID(), (const char *)pItem);
  269.     }
  270.     
  271.     return(bRtn);
  272.  
  273. } // END OF    FUNCTION CTreeMenu::AddItem()
  274.  
  275. CMenu * CTreeMenu::FindMenu(CString& menuName)
  276. {
  277.     int nSize = m_itemList.GetSize();
  278.  
  279.     for(int i = 0; i < nSize; i ++)
  280.     {
  281.         CTreeItem *pItem = (CTreeItem*)m_itemList[i];
  282.  
  283.         if(pItem->GetLabel() == menuName)
  284.             return pItem->GetSubMenu();
  285.     }
  286.  
  287.     return NULL;
  288.  
  289. }
  290. /****************************************************************************
  291. *
  292. *    CTreeMenu::ClearItems
  293. *
  294. *    PARAMETERS:
  295. *        start:        Clear all elements starting with this index 
  296. *        fromEnd:    Delete up until this many elements from end
  297. *    RETURNS:
  298. *        N/A
  299. *
  300. *    DESCRIPTION:
  301. *        Removes all items from the itemList starting with start until
  302. *        fromEnd elements from the end
  303. *
  304. ****************************************************************************/
  305.  
  306. void CTreeMenu::ClearItems(int start, int fromEnd)
  307. {
  308.  
  309.     m_itemList.RemoveAt(start, m_itemList.GetSize() - fromEnd - start);
  310. }
  311.  
  312. void CTreeMenu::AddMnemonic(TCHAR cMnemonic, UINT nCommand, int nPosition)
  313. {
  314.     MnemonicStruct *pMnemonic = new MnemonicStruct;
  315.  
  316.     pMnemonic->nCommand = nCommand;
  317.     pMnemonic->nPosition = nPosition;
  318.  
  319.     m_mnemonicMap.SetAt(toupper(cMnemonic), pMnemonic);
  320.  
  321. }
  322.  
  323. BOOL CTreeMenu::GetMnemonic(TCHAR cMnemonic, UINT &nCommand, int &nPosition)
  324. {
  325.     MnemonicStruct *pMnemonic;
  326.  
  327.     if(m_mnemonicMap.Lookup(toupper(cMnemonic), (void*&)pMnemonic) )
  328.     {
  329.         nCommand = pMnemonic->nCommand;
  330.         nPosition = pMnemonic->nPosition;
  331.         return TRUE;
  332.     }
  333.     else
  334.         return FALSE;
  335. }
  336.  
  337. /****************************************************************************
  338. *
  339. *    CTreeMenu::CalculateItemDimensions
  340. *
  341. *    PARAMETERS:
  342. *        N/A
  343. *
  344. *    RETURNS:
  345. *        N/A
  346. *
  347. *    DESCRIPTION:
  348. *        For each item in the menu, this calculates the size of that item's
  349. *        bitmap, menuitem text, and menuitem accelerator text.  In addition,
  350. *        this keeps track of the widest bitmap, text, and accelerator text in
  351. *        the menu.  This is done so that the accelerator can appear in a
  352. *        reasonable position on the menu and assuring that enough space will
  353. *        given to the menu item to draw itself
  354. *
  355. ****************************************************************************/
  356.  
  357. void CTreeMenu::CalculateItemDimensions(void)
  358. {
  359.  
  360.     CSize unselectedBitmapSize, selectedBitmapSize, textSize, acceleratorSize;
  361.     CString label;
  362.  
  363.     m_WidestImage=0;
  364.     m_WidestText=0;
  365.     m_WidestAccelerator=0;
  366.  
  367.     int numItems = m_itemList.GetSize();
  368.  
  369.     for(int i=0; i<numItems; i++)
  370.     {
  371.         CTreeItem *item = (CTreeItem*)m_itemList.Get(i);
  372.  
  373.         unselectedBitmapSize=MeasureBitmap(item->GetUnselectedImage());
  374.         item->SetUnselectedBitmapSize(unselectedBitmapSize);
  375.  
  376.         selectedBitmapSize=MeasureBitmap(item->GetSelectedImage());
  377.         item->SetSelectedBitmapSize(selectedBitmapSize);
  378.  
  379.         if(unselectedBitmapSize.cx > m_WidestImage)
  380.             m_WidestImage = unselectedBitmapSize.cx;
  381.  
  382.         if(selectedBitmapSize.cx > m_WidestImage)
  383.             m_WidestImage = selectedBitmapSize.cx;
  384.  
  385.         label = item->GetLabel();
  386.  
  387.         //Figure out if there is an accelerator    
  388.         int tabPos=label.Find('\t');
  389.  
  390.         if(tabPos!=-1)
  391.         {
  392.             textSize = MeasureText(label.Left(tabPos));
  393.             acceleratorSize = MeasureText(label.Right(label.GetLength() - (tabPos +1)));
  394.             item->SetAcceleratorSize(acceleratorSize);
  395.  
  396.             if(acceleratorSize.cx > m_WidestAccelerator)
  397.                 m_WidestAccelerator = acceleratorSize.cx;
  398.  
  399.         }
  400.         else
  401.             textSize = MeasureText(label);
  402.  
  403.         if(textSize.cx > m_WidestText)
  404.             m_WidestText = textSize.cx;
  405.  
  406.         item->SetTextSize(textSize);
  407.     }
  408. }
  409.  
  410. /****************************************************************************
  411. *
  412. *    CTreeMenu::MeasureBitmap
  413. *
  414. *    PARAMETERS:
  415. *        pBitmap:  The bitmap to measure
  416. *
  417. *    RETURNS:
  418. *        The size of the bitmap
  419. *
  420. *    DESCRIPTION:
  421. *        Given a bitmap, this returns its dimensions
  422. *
  423. ****************************************************************************/
  424.  
  425. CSize CTreeMenu::MeasureBitmap(CBitmap *pBitmap)
  426. {
  427.  
  428.     CSize size;
  429.  
  430.     if (pBitmap != NULL)
  431.     {
  432.         BITMAP bmp;
  433.         pBitmap->GetObject(sizeof(bmp), &bmp);
  434.  
  435.         size.cx = bmp.bmWidth;
  436.         size.cy = bmp.bmHeight;
  437.     }
  438.     else
  439.         size.cx = size.cy = 0;
  440.  
  441.     return size;
  442.  
  443.  
  444. }
  445.  
  446.  
  447. /****************************************************************************
  448. *
  449. *    CTreeMenu::MeasureText
  450. *
  451. *    PARAMETERS:
  452. *        text:  The CString text to be measured
  453. *
  454. *    RETURNS:
  455. *        Returns the size of the text in the current font
  456. *
  457. *    DESCRIPTION:
  458. *        Given a CString this returns the dimensions of that text
  459. *
  460. ****************************************************************************/
  461.  
  462. CSize CTreeMenu::MeasureText(CString text)
  463. {
  464.  
  465.     HFONT MenuFont;
  466.  
  467. #if defined(WIN32)
  468.     NONCLIENTMETRICS ncm;
  469.     ncm.cbSize = sizeof(NONCLIENTMETRICS);
  470.     if (::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
  471.     {
  472.         MenuFont = theApp.CreateAppFont( ncm.lfMenuFont );
  473.     }
  474.     else
  475.     {
  476.         MenuFont = (HFONT)::GetStockObject(SYSTEM_FONT);
  477.     }
  478. #else    // Win16
  479.         MenuFont = (HFONT)::GetStockObject(SYSTEM_FONT);
  480. #endif    // WIN32
  481.  
  482.     CDC dc;
  483.     dc.CreateCompatibleDC(NULL);
  484.     CFont * pOldFont = dc.SelectObject(CFont::FromHandle(MenuFont));
  485.     CSize sizeTxt = dc.GetTabbedTextExtent((LPCSTR)text, strlen(text), 0, NULL);
  486.     dc.SelectObject(pOldFont);
  487.  
  488.     return sizeTxt;
  489.  
  490. }
  491.  
  492. /****************************************************************************
  493. *
  494. *    CTreeMenu::MeasureItem
  495. *
  496. *    PARAMETERS:
  497. *        lpMI    - pointer to LPMEASUREITEMSTRUCT
  498. *
  499. *    RETURNS:
  500. *        void
  501. *
  502. *    DESCRIPTION:
  503. *        We must override this function to inform the system of our menu
  504. *        item dimensions, since we're owner draw style.
  505. *
  506. ****************************************************************************/
  507. #define ACCELERATOR_TAB 5        //Leave some space between the text and the accelerator
  508. #define ACCELERATOR_RIGHT 15    //Leave a right margin between end of
  509.                                 //menu item and end of accelerator
  510. #define MENU_LEFT_MARGIN 7        //Leave a left margin for text with no bitmaps
  511. void CTreeMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMI)
  512. {
  513.     CTreeItem * pItem = (CTreeItem *)(lpMI->itemData);
  514.     ASSERT(pItem != NULL);
  515.     
  516.     // First, get all of the dimensions
  517.     CSize sizeUnselectedImg=pItem->GetUnselectedBitmapSize();
  518.     CSize sizeSelectedImg=pItem->GetSelectedBitmapSize();
  519.     CSize sizeText=pItem->GetTextSize();
  520.     CSize sizeAccelerator=pItem->GetAcceleratorSize();
  521.  
  522.     //if there's no bitmap we need to provide a margin for the text
  523.     lpMI->itemWidth = (m_WidestImage == 0) ? MENU_LEFT_MARGIN : 0;
  524.     //Return the values depending upon whether there is an accelerator
  525.     if(sizeAccelerator.cx !=0)
  526.     {
  527.         lpMI->itemWidth += m_WidestImage + m_WidestText + sizeAccelerator.cx + ACCELERATOR_TAB + ACCELERATOR_RIGHT + (2*nIMG_SPACE);
  528.     }
  529.     else
  530.         lpMI->itemWidth += m_WidestImage + sizeText.cx + (nIMG_SPACE * 2);
  531.  
  532.     int nImageHeight = max(sizeUnselectedImg.cy, sizeSelectedImg.cy);
  533.     lpMI->itemHeight = max(nImageHeight, sizeText.cy) + 4;
  534.     
  535. } // END OF    FUNCTION CTreeMenu::MeasureItem()
  536.  
  537. /****************************************************************************
  538. *
  539. *    CTreeMenu::DrawItem
  540. *
  541. *    PARAMETERS:
  542. *        lpDI    - pointer to LPDRAWITEMSTRUCT
  543. *
  544. *    RETURNS:
  545. *        void
  546. *
  547. *    DESCRIPTION:
  548. *        We must override this function to draw our image and text for the
  549. *        menu item, since we're owner draw style.
  550. *
  551. ****************************************************************************/
  552.  
  553. void CTreeMenu::DrawItem(LPDRAWITEMSTRUCT lpDI)
  554. {
  555.     // Extract the goods from lpDI
  556.     CTreeItem * pItem = (CTreeItem *)(lpDI->itemData);
  557.     ASSERT(pItem != NULL);
  558.     CDC * pDC = CDC::FromHandle(lpDI->hDC);
  559.     CRect rc(&(lpDI->rcItem));
  560.  
  561.     // Get proper colors and paint the background first
  562.     CBrush brBG;
  563.     COLORREF rgbTxt;
  564.     if (lpDI->itemState & ODS_SELECTED)
  565.     {
  566.         brBG.CreateSolidBrush(::GetSysColor(COLOR_HIGHLIGHT));
  567.         rgbTxt = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
  568.     }
  569.     else
  570.     {
  571.         brBG.CreateSolidBrush(::GetSysColor(COLOR_MENU));
  572.         rgbTxt = ::GetSysColor(COLOR_MENUTEXT);
  573.     }
  574.     pDC->FillRect(&rc, &brBG);
  575.     
  576.     // Now paint the bitmap, left side of menu
  577.     rc.left += nIMG_SPACE;
  578.     CSize imgSize = DrawImage(pDC, rc, pItem, lpDI->itemState & ODS_SELECTED);
  579.     
  580.     // And now the text
  581.     HFONT MenuFont;
  582. #if defined(WIN32)
  583.     NONCLIENTMETRICS ncm;
  584.     ncm.cbSize = sizeof(NONCLIENTMETRICS);
  585.     if (::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
  586.     {
  587.         MenuFont = theApp.CreateAppFont( ncm.lfMenuFont );
  588.     }
  589.     else
  590.     {
  591.         MenuFont = (HFONT)::GetStockObject(SYSTEM_FONT);
  592.     }
  593. #else    // Win16
  594.     MenuFont = (HFONT)::GetStockObject(SYSTEM_FONT);
  595. #endif    // WIN32
  596.  
  597.     CFont * pOldFont = pDC->SelectObject(CFont::FromHandle(MenuFont));
  598.     int nOldBkMode = pDC->SetBkMode(TRANSPARENT);
  599.     COLORREF rgbOldTxt = pDC->SetTextColor(rgbTxt);
  600.  
  601.     //Figure out where text should go in relation to bitmaps
  602.     if(m_WidestImage == 0)
  603.         rc.left += MENU_LEFT_MARGIN;
  604.  
  605.     rc.left += imgSize.cx + nIMG_SPACE + (m_WidestImage-imgSize.cx);
  606.  
  607.     //Deal with the case where there is a tab for an accelerator
  608.     CString label=pItem->GetLabel();
  609.     int tabPos=label.Find('\t');
  610.  
  611.     if(tabPos!=-1)
  612.     {
  613.         pDC->DrawText(label.Left(tabPos), -1, &rc, DT_LEFT | DT_VCENTER  |DT_SINGLELINE);
  614.         //Give the accelerator some room on the right
  615.         rc.right-=ACCELERATOR_RIGHT + (m_WidestAccelerator - pItem->GetAcceleratorSize().cx);
  616.         pDC->DrawText(label.Right(label.GetLength()-(tabPos+1)), -1, &rc, DT_RIGHT | DT_VCENTER  |DT_SINGLELINE);
  617.     }
  618.     else
  619.     {
  620.         pDC->DrawText(label, -1, &rc, DT_LEFT | DT_VCENTER | DT_SINGLELINE |DT_EXPANDTABS);
  621.     }
  622.     
  623.     pDC->SetBkMode(nOldBkMode);
  624.     pDC->SetTextColor(rgbOldTxt);
  625.     pDC->SelectObject(pOldFont);
  626.     
  627. } // END OF    FUNCTION CTreeMenu::DrawItem()
  628.  
  629. /****************************************************************************
  630. *
  631. *    CTreeMenu::DrawImage
  632. *
  633. *    PARAMETERS:
  634. *        pDC        - pointer to device context to draw on
  635. *        rect    - bounding rectangle to draw in
  636. *        pItem    - pointer to CTreeItem that contains the data
  637. *        bIsSelected - is this item selected
  638. *
  639. *    RETURNS:
  640. *        width of the image, in pixels
  641. *
  642. *    DESCRIPTION:
  643. *        Protected helper function for drawing the bitmap image in a menu
  644. *        item. We return the size of the painted image so the caller can
  645. *        position the menu text after the image.
  646. *
  647. ****************************************************************************/
  648.  
  649. CSize CTreeMenu::DrawImage(CDC * pDC, const CRect & rect, CTreeItem * pItem,
  650.                            BOOL bIsSelected)
  651. {
  652.     CSize sizeImg;
  653.     
  654.     sizeImg.cx = sizeImg.cy = 0;
  655.  
  656.     CBitmap * pImg = bIsSelected ? pItem->GetSelectedImage() : pItem->GetUnselectedImage();
  657.     if (pImg != NULL)
  658.     {
  659.         HPALETTE hPalette= WFE_GetUIPalette(m_pParent);
  660.  
  661.         HPALETTE hOldPalette = ::SelectPalette(pDC->m_hDC, hPalette, FALSE);
  662.         // Get image dimensions
  663.         BITMAP bmp;
  664.         pImg->GetObject(sizeof(bmp), &bmp);
  665.  
  666.         sizeImg.cx = bmp.bmWidth;
  667.         sizeImg.cy = bmp.bmHeight;
  668.         
  669.         // Create a scratch DC and select our bitmap into it.
  670.         CDC * pBmpDC = new CDC;
  671.         pBmpDC->CreateCompatibleDC(pDC);
  672.         CBitmap * pOldBmp = pBmpDC->SelectObject(pImg);
  673.     
  674.         // Center the image horizontally and vertically
  675.         CPoint ptDst(rect.left + (m_WidestImage - sizeImg.cx)/2, rect.top +
  676.             (((rect.Height() - sizeImg.cy) + 1) / 2));
  677.             
  678.         // Call the handy transparent blit function to paint the bitmap over
  679.         // the background.
  680.         if (pItem->GetIconType() == LOCAL_FILE)
  681.         {
  682.             HICON hIcon = pItem->GetLocalFileIcon();
  683.             DrawIconEx(pDC->m_hDC, ptDst.x, ptDst.y, hIcon, 0, 0, 0, NULL, DI_NORMAL);
  684.         }
  685.         else if (pItem->GetIconType() == ARBITRARY_URL)
  686.         {
  687.             NSNavCenterImage* pImage = pItem->GetCustomIcon();
  688.             HDC hDC = pDC->m_hDC;
  689.             int left = ptDst.x;
  690.             int top = ptDst.y;
  691.             int imageWidth = 16;
  692.             int imageHeight = 16;
  693.             COLORREF bkColor = bIsSelected  ? 
  694.                 GetSysColor(COLOR_HIGHLIGHT) : GetSysColor(COLOR_MENU);
  695.             if (pImage && pImage->CompletelyLoaded()) 
  696.             {
  697.                 // Now we draw this bad boy.
  698.                 if (pImage->m_BadImage) 
  699.                 {         
  700.                     // display broken icon.
  701.                     HDC tempDC = ::CreateCompatibleDC(hDC);
  702.                     HBITMAP hOldBmp = (HBITMAP)::SelectObject(tempDC,  NSNavCenterImage::m_hBadImageBitmap);
  703.                     ::StretchBlt(hDC, 
  704.                          left, top,
  705.                         imageWidth, imageHeight, 
  706.                         tempDC, 0, 0, 
  707.                         imageWidth, imageHeight, SRCCOPY);
  708.                     ::SelectObject(tempDC, hOldBmp);
  709.                     ::DeleteDC(tempDC);
  710.                 }
  711.                 else if (pImage->bits ) 
  712.                 {
  713.                     // Center the image. 
  714.                     long width = pImage->bmpInfo->bmiHeader.biWidth;
  715.                     long height = pImage->bmpInfo->bmiHeader.biHeight;
  716.                     int xoffset = (imageWidth-width)/2;
  717.                     int yoffset = (imageHeight-height)/2;
  718.                     if (xoffset < 0) xoffset = 0;
  719.                     if (yoffset < 0) yoffset = 0;
  720.                     if (width > imageWidth) width = imageWidth;
  721.                     if (height > imageHeight) height = imageHeight;
  722.  
  723.                     HPALETTE hPal = WFE_GetUIPalette(NULL);
  724.                     HPALETTE hOldPal = ::SelectPalette(hDC, hPal, TRUE);
  725.  
  726.                     ::RealizePalette(hDC);
  727.                     
  728.                     if (pImage->maskbits) 
  729.                     {
  730.                         WFE_StretchDIBitsWithMask(hDC, TRUE, NULL,
  731.                             left+xoffset, top+xoffset,
  732.                             width, height,
  733.                             0, 0, width, height,
  734.                             pImage->bits, pImage->bmpInfo,
  735.                             pImage->maskbits, FALSE, bkColor);
  736.                     }
  737.                     else 
  738.                     {
  739.                         ::StretchDIBits(hDC,
  740.                             left+xoffset, top+xoffset,
  741.                             width, height,
  742.                             0, 0, width, height, pImage->bits, pImage->bmpInfo, DIB_RGB_COLORS,
  743.                             SRCCOPY);
  744.                     }
  745.  
  746.                     ::SelectPalette(hDC, hOldPal, TRUE);
  747.                 }
  748.             }
  749.         }
  750.         else ::FEU_TransBlt(pBmpDC, pDC, CPoint(0, 0), ptDst, sizeImg.cx, sizeImg.cy, hPalette, PALETTERGB(255, 0, 255));
  751.  
  752.         ::SelectPalette(pDC->m_hDC, hOldPalette, TRUE);
  753.         // Cleanup
  754.         pBmpDC->SelectObject(pOldBmp);
  755.         pBmpDC->DeleteDC();
  756.         delete pBmpDC;
  757.     }
  758.  
  759.     return(sizeImg);
  760.     
  761. } // END OF    FUNCTION CTreeMenu::DrawImage()
  762.     
  763. /****************************************************************************
  764. *
  765. *    Class: CPopupTree
  766. *
  767. *    DESCRIPTION:
  768. *        This class represents a hierarchical popup menu object that can be
  769. *        used for selecting from a list of sub-categorized items.
  770. *
  771. ****************************************************************************/
  772.  
  773. /****************************************************************************
  774. *
  775. *    CPopupTree::CPopupTree
  776. *
  777. *    PARAMETERS:
  778. *        pItems    - list of items for filling the tree
  779. *
  780. *    RETURNS:
  781. *        N/A
  782. *
  783. *    DESCRIPTION:
  784. *        Constructor.
  785. *
  786. ****************************************************************************/
  787.  
  788. CPopupTree::CPopupTree(CTreeItemList * pItems)
  789. {
  790.     m_pTree = pItems;
  791.  
  792. } // END OF    FUNCTION CPopupTree::CPopupTree()
  793.  
  794. /****************************************************************************
  795. *
  796. *    CPopupTree::~CPopupTree
  797. *
  798. *    PARAMETERS:
  799. *        N/A
  800. *
  801. *    RETURNS:
  802. *        N/A
  803. *
  804. *    DESCRIPTION:
  805. *        Destructor.
  806. *
  807. ****************************************************************************/
  808.  
  809. CPopupTree::~CPopupTree()
  810. {
  811.     // Time to take out the trash! We maintain a list of objects that were
  812.     // dynamically allocated on the heap, but couldn't be conveniently
  813.     // deleted.
  814.     for (int i = 0; i < m_GarbageList.GetSize(); i++)
  815.     {
  816.         CObject * pObject = m_GarbageList.GetAt(i);
  817.         if (pObject != NULL)
  818.         {
  819.             delete pObject;
  820.         }
  821.     }
  822.     m_GarbageList.RemoveAll();
  823.  
  824. } // END OF    FUNCTION CPopupTree::~CPopupTree()
  825.  
  826. /****************************************************************************
  827. *
  828. *    CPopupTree::Activate
  829. *
  830. *    PARAMETERS:
  831. *        nX        - horizontal position (screen coordinates)
  832. *        nY        - vertical position
  833. *        pParent    - pointer to parent window
  834. *
  835. *    RETURNS:
  836. *        TRUE if creation is successful
  837. *
  838. *    DESCRIPTION:
  839. *        This function is called to display the popup menu, after construction.
  840. *
  841. ****************************************************************************/
  842.  
  843. BOOL CPopupTree::Activate(int nX, int nY, CWnd * pParent)
  844. {
  845.     CTreeMenu Menu;
  846.     BOOL bRtn = Menu.Create();
  847.     
  848.     // Now construct the menu from our tree
  849.     BuildMenu(&Menu, m_pTree);
  850.     
  851.     if (bRtn)
  852.     {
  853.         bRtn = Menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, nX, nY, pParent);
  854.     }
  855.     
  856.     return(bRtn);
  857.  
  858. } // END OF    FUNCTION CPopupTree::Activate()
  859.  
  860. /****************************************************************************
  861. *
  862. *    CPopupTree::BuildMenu
  863. *
  864. *    PARAMETERS:
  865. *        pMenu    - pointer to the menu to be constructed
  866. *        pItems    - list of item objects for building the menu
  867. *
  868. *    RETURNS:
  869. *        void
  870. *
  871. *    DESCRIPTION:
  872. *        This function is called to construct a custom menu from a list
  873. *        of item objects. It is recursive and can be called for each node
  874. *        that contains sub-items.
  875. *
  876. ****************************************************************************/
  877.  
  878. void CPopupTree::BuildMenu(CTreeMenu * pMenu, CTreeItemList * pItems)
  879. {
  880.     for (int i = 0; i < pItems->GetSize(); i++)
  881.     {
  882.         CTreeItem * pItem = pItems->Get(i);
  883.         ASSERT(pItem != NULL);
  884.         if (pItem != NULL)
  885.         {
  886.             // See if this item has sub-items
  887.             CTreeItemList * pSubItems = pItem->GetSubItems();
  888.             if (pSubItems->GetSize() > 0)
  889.             {
  890.                 // It does, so create a new menu and call this function
  891.                 // recursively to construct it.
  892.                 CTreeMenu * pSubMenu = new CTreeMenu;
  893.             //    m_GarbageList.Add(pSubMenu);
  894.                 pSubMenu->Create();
  895.                 BuildMenu(pSubMenu, pSubItems);
  896.                 pSubMenu->CalculateItemDimensions();
  897.                 // Last but not least, add the new branch to the main menu
  898.                 BOOL bOk = pMenu->AddItem(pItem, 0, pSubMenu);
  899.                 ASSERT(bOk);
  900.             }
  901.             else
  902.             {
  903.                 // Just add top-level item
  904.                 BOOL bOk = pMenu->AddItem(pItem);
  905.                 ASSERT(bOk);
  906.             }
  907.         }
  908.     }
  909.     pMenu->CalculateItemDimensions();
  910. } // END OF    FUNCTION CPopupTree::BuildMenu()
  911.