mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 14:45:29 +00:00
911 lines
22 KiB
C++
Executable File
911 lines
22 KiB
C++
Executable File
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
// This file contains the implementations of the various Bookmark Quick
|
|
// File classes.
|
|
|
|
|
|
/** INCLUDE **/
|
|
#include "stdafx.h"
|
|
#include "cxicon.h"
|
|
#include "quickfil.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
typedef struct {
|
|
UINT nCommand;
|
|
int nPosition;
|
|
} MnemonicStruct;
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Class: CTreeItem
|
|
*
|
|
* DESCRIPTION:
|
|
* This class provides an abstract object for representing an item
|
|
* within a hierarchical tree.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CTreeItem::CTreeItem
|
|
*
|
|
* PARAMETERS:
|
|
* pImg - image to be drawn with this item (NULL if none)
|
|
* uID - unique item identifier
|
|
* strLabel - text label for this item
|
|
*
|
|
* RETURNS:
|
|
* N/A
|
|
*
|
|
* DESCRIPTION:
|
|
* Constructor.
|
|
*
|
|
****************************************************************************/
|
|
|
|
CTreeItem::CTreeItem(CBitmap * pUnselectedImg, CBitmap *pSelectedImg, const UINT uID, const CString & strLabel, CMenu *pSubMenu)
|
|
{
|
|
m_pUnselectedImg = pUnselectedImg;
|
|
m_pSelectedImg = pSelectedImg;
|
|
|
|
m_uID = uID;
|
|
m_strLabel = strLabel;
|
|
|
|
m_unselectedBitmapSize.cx = m_unselectedBitmapSize.cy = 0;
|
|
m_selectedBitmapSize.cx = m_selectedBitmapSize.cy = 0;
|
|
m_textSize.cx = m_textSize.cy = 0;
|
|
m_accelSize.cx = m_accelSize.cy =0;
|
|
m_pSubMenu = pSubMenu;
|
|
|
|
} // END OF FUNCTION CTreeItem::CTreeItem()
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CTreeItem::~CTreeItem
|
|
*
|
|
* PARAMETERS:
|
|
* N/A
|
|
*
|
|
* RETURNS:
|
|
* N/A
|
|
*
|
|
* DESCRIPTION:
|
|
* Destructor.
|
|
*
|
|
****************************************************************************/
|
|
|
|
CTreeItem::~CTreeItem()
|
|
{
|
|
if(m_pSubMenu)
|
|
delete m_pSubMenu;
|
|
} // END OF FUNCTION CTreeItem::~CTreeItem()
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Class: CTreeItemList
|
|
*
|
|
* DESCRIPTION:
|
|
* This is a collection class for holding CTreeItem objects.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CTreeItemList::CTreeItemList
|
|
*
|
|
* PARAMETERS:
|
|
* None
|
|
*
|
|
* RETURNS:
|
|
* N/A
|
|
*
|
|
* DESCRIPTION:
|
|
* Constructor
|
|
*
|
|
****************************************************************************/
|
|
|
|
CTreeItemList::CTreeItemList()
|
|
{
|
|
|
|
} // END OF FUNCTION CTreeItemList::CTreeItemList()
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CTreeItemList::~CTreeItemList
|
|
*
|
|
* PARAMETERS:
|
|
* N/A
|
|
*
|
|
* RETURNS:
|
|
* N/A
|
|
*
|
|
* DESCRIPTION:
|
|
* Destructor. We provide auto-cleanup for the objects in the collection.
|
|
*
|
|
****************************************************************************/
|
|
|
|
CTreeItemList::~CTreeItemList()
|
|
{
|
|
int nCount = GetSize();
|
|
|
|
for (int i = 0; i < nCount; i++)
|
|
{
|
|
CTreeItem * pItem = Get(i);
|
|
if (pItem != NULL)
|
|
{
|
|
delete pItem;
|
|
}
|
|
}
|
|
RemoveAll();
|
|
|
|
|
|
} // END OF FUNCTION CTreeItemList::~CTreeItemList()
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Class: CTreeMenu
|
|
*
|
|
* DESCRIPTION:
|
|
* This class provides a custom, self drawing menu object for displaying
|
|
* graphics as well as text in a menu item.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CONSTANTS
|
|
*
|
|
****************************************************************************/
|
|
static int nIMG_SPACE = 3; // Gap between image and text in menu item
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CTreeMenu::CTreeMenu
|
|
*
|
|
* PARAMETERS:
|
|
* None
|
|
*
|
|
* RETURNS:
|
|
* N/A
|
|
*
|
|
* DESCRIPTION:
|
|
* Constructor.
|
|
*
|
|
****************************************************************************/
|
|
|
|
CTreeMenu::CTreeMenu()
|
|
{
|
|
m_WidestImage=0;
|
|
m_WidestText=0;
|
|
m_WidestAccelerator=0;
|
|
m_pParent = NULL;
|
|
|
|
} // END OF FUNCTION CTreeMenu::CTreeMenu()
|
|
|
|
CTreeMenu::~CTreeMenu()
|
|
{
|
|
m_itemList.RemoveAll();
|
|
|
|
DeleteMnemonics();
|
|
|
|
}
|
|
|
|
void CTreeMenu::DeleteMnemonics(void)
|
|
{
|
|
POSITION pos;
|
|
WORD dwKey;
|
|
MnemonicStruct *pMnemonic = NULL;
|
|
|
|
// also destroy bitmaps;
|
|
pos = m_mnemonicMap.GetStartPosition();
|
|
|
|
while(pos)
|
|
{
|
|
m_mnemonicMap.GetNextAssoc(pos, dwKey,(void *&)pMnemonic);
|
|
delete pMnemonic;
|
|
}
|
|
|
|
m_mnemonicMap.RemoveAll();
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CTreeMenu::AddItem
|
|
*
|
|
* PARAMETERS:
|
|
* pItem - pointer to abstract item
|
|
* hSubMenu - handle of sub-menu is this item is a new node
|
|
*
|
|
* RETURNS:
|
|
* TRUE if successful.
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to add a new menu item to the main trunk. The
|
|
* new item can also be a branch, if hSubMenu is set properly.
|
|
*****************************************************************************/
|
|
|
|
BOOL CTreeMenu::AddItem(CTreeItem * pItem, int nPosition /*=0*/, CTreeMenu *pSubMenu /*= NULL*/,
|
|
void* pIcon /* = NULL */, IconType nIconType /* = BUILTIN_BITMAP */)
|
|
{
|
|
BOOL bRtn = FALSE;
|
|
|
|
|
|
m_itemList.Add(pItem);
|
|
|
|
pItem->SetIcon(pIcon, nIconType);
|
|
|
|
if (pSubMenu != NULL)
|
|
{
|
|
|
|
bRtn = InsertMenu(nPosition, MF_BYPOSITION | MF_OWNERDRAW | MF_POPUP, (UINT)pSubMenu->GetSafeHmenu(),
|
|
(const char *)pItem);
|
|
}
|
|
else
|
|
{
|
|
bRtn = InsertMenu(nPosition, MF_BYPOSITION | MF_OWNERDRAW, pItem->GetID(), (const char *)pItem);
|
|
}
|
|
|
|
return(bRtn);
|
|
|
|
} // END OF FUNCTION CTreeMenu::AddItem()
|
|
|
|
CMenu * CTreeMenu::FindMenu(CString& menuName)
|
|
{
|
|
int nSize = m_itemList.GetSize();
|
|
|
|
for(int i = 0; i < nSize; i ++)
|
|
{
|
|
CTreeItem *pItem = (CTreeItem*)m_itemList[i];
|
|
|
|
if(pItem->GetLabel() == menuName)
|
|
return pItem->GetSubMenu();
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
/****************************************************************************
|
|
*
|
|
* CTreeMenu::ClearItems
|
|
*
|
|
* PARAMETERS:
|
|
* start: Clear all elements starting with this index
|
|
* fromEnd: Delete up until this many elements from end
|
|
* RETURNS:
|
|
* N/A
|
|
*
|
|
* DESCRIPTION:
|
|
* Removes all items from the itemList starting with start until
|
|
* fromEnd elements from the end
|
|
*
|
|
****************************************************************************/
|
|
|
|
void CTreeMenu::ClearItems(int start, int fromEnd)
|
|
{
|
|
|
|
m_itemList.RemoveAt(start, m_itemList.GetSize() - fromEnd - start);
|
|
}
|
|
|
|
void CTreeMenu::AddMnemonic(TCHAR cMnemonic, UINT nCommand, int nPosition)
|
|
{
|
|
MnemonicStruct *pMnemonic = new MnemonicStruct;
|
|
|
|
pMnemonic->nCommand = nCommand;
|
|
pMnemonic->nPosition = nPosition;
|
|
|
|
m_mnemonicMap.SetAt(toupper(cMnemonic), pMnemonic);
|
|
|
|
}
|
|
|
|
BOOL CTreeMenu::GetMnemonic(TCHAR cMnemonic, UINT &nCommand, int &nPosition)
|
|
{
|
|
MnemonicStruct *pMnemonic;
|
|
|
|
if(m_mnemonicMap.Lookup(toupper(cMnemonic), (void*&)pMnemonic) )
|
|
{
|
|
nCommand = pMnemonic->nCommand;
|
|
nPosition = pMnemonic->nPosition;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CTreeMenu::CalculateItemDimensions
|
|
*
|
|
* PARAMETERS:
|
|
* N/A
|
|
*
|
|
* RETURNS:
|
|
* N/A
|
|
*
|
|
* DESCRIPTION:
|
|
* For each item in the menu, this calculates the size of that item's
|
|
* bitmap, menuitem text, and menuitem accelerator text. In addition,
|
|
* this keeps track of the widest bitmap, text, and accelerator text in
|
|
* the menu. This is done so that the accelerator can appear in a
|
|
* reasonable position on the menu and assuring that enough space will
|
|
* given to the menu item to draw itself
|
|
*
|
|
****************************************************************************/
|
|
|
|
void CTreeMenu::CalculateItemDimensions(void)
|
|
{
|
|
|
|
CSize unselectedBitmapSize, selectedBitmapSize, textSize, acceleratorSize;
|
|
CString label;
|
|
|
|
m_WidestImage=0;
|
|
m_WidestText=0;
|
|
m_WidestAccelerator=0;
|
|
|
|
int numItems = m_itemList.GetSize();
|
|
|
|
for(int i=0; i<numItems; i++)
|
|
{
|
|
CTreeItem *item = (CTreeItem*)m_itemList.Get(i);
|
|
|
|
unselectedBitmapSize=MeasureBitmap(item->GetUnselectedImage());
|
|
item->SetUnselectedBitmapSize(unselectedBitmapSize);
|
|
|
|
selectedBitmapSize=MeasureBitmap(item->GetSelectedImage());
|
|
item->SetSelectedBitmapSize(selectedBitmapSize);
|
|
|
|
if(unselectedBitmapSize.cx > m_WidestImage)
|
|
m_WidestImage = unselectedBitmapSize.cx;
|
|
|
|
if(selectedBitmapSize.cx > m_WidestImage)
|
|
m_WidestImage = selectedBitmapSize.cx;
|
|
|
|
label = item->GetLabel();
|
|
|
|
//Figure out if there is an accelerator
|
|
int tabPos=label.Find('\t');
|
|
|
|
if(tabPos!=-1)
|
|
{
|
|
textSize = MeasureText(label.Left(tabPos));
|
|
acceleratorSize = MeasureText(label.Right(label.GetLength() - (tabPos +1)));
|
|
item->SetAcceleratorSize(acceleratorSize);
|
|
|
|
if(acceleratorSize.cx > m_WidestAccelerator)
|
|
m_WidestAccelerator = acceleratorSize.cx;
|
|
|
|
}
|
|
else
|
|
textSize = MeasureText(label);
|
|
|
|
if(textSize.cx > m_WidestText)
|
|
m_WidestText = textSize.cx;
|
|
|
|
item->SetTextSize(textSize);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CTreeMenu::MeasureBitmap
|
|
*
|
|
* PARAMETERS:
|
|
* pBitmap: The bitmap to measure
|
|
*
|
|
* RETURNS:
|
|
* The size of the bitmap
|
|
*
|
|
* DESCRIPTION:
|
|
* Given a bitmap, this returns its dimensions
|
|
*
|
|
****************************************************************************/
|
|
|
|
CSize CTreeMenu::MeasureBitmap(CBitmap *pBitmap)
|
|
{
|
|
|
|
CSize size;
|
|
|
|
if (pBitmap != NULL)
|
|
{
|
|
BITMAP bmp;
|
|
pBitmap->GetObject(sizeof(bmp), &bmp);
|
|
|
|
size.cx = bmp.bmWidth;
|
|
size.cy = bmp.bmHeight;
|
|
}
|
|
else
|
|
size.cx = size.cy = 0;
|
|
|
|
return size;
|
|
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CTreeMenu::MeasureText
|
|
*
|
|
* PARAMETERS:
|
|
* text: The CString text to be measured
|
|
*
|
|
* RETURNS:
|
|
* Returns the size of the text in the current font
|
|
*
|
|
* DESCRIPTION:
|
|
* Given a CString this returns the dimensions of that text
|
|
*
|
|
****************************************************************************/
|
|
|
|
CSize CTreeMenu::MeasureText(CString text)
|
|
{
|
|
|
|
HFONT MenuFont;
|
|
|
|
#if defined(WIN32)
|
|
NONCLIENTMETRICS ncm;
|
|
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
|
if (::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
|
|
{
|
|
MenuFont = theApp.CreateAppFont( ncm.lfMenuFont );
|
|
}
|
|
else
|
|
{
|
|
MenuFont = (HFONT)::GetStockObject(SYSTEM_FONT);
|
|
}
|
|
#else // Win16
|
|
MenuFont = (HFONT)::GetStockObject(SYSTEM_FONT);
|
|
#endif // WIN32
|
|
|
|
CDC dc;
|
|
dc.CreateCompatibleDC(NULL);
|
|
CFont * pOldFont = dc.SelectObject(CFont::FromHandle(MenuFont));
|
|
CSize sizeTxt = dc.GetTabbedTextExtent((LPCSTR)text, strlen(text), 0, NULL);
|
|
dc.SelectObject(pOldFont);
|
|
|
|
return sizeTxt;
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CTreeMenu::MeasureItem
|
|
*
|
|
* PARAMETERS:
|
|
* lpMI - pointer to LPMEASUREITEMSTRUCT
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
* DESCRIPTION:
|
|
* We must override this function to inform the system of our menu
|
|
* item dimensions, since we're owner draw style.
|
|
*
|
|
****************************************************************************/
|
|
#define ACCELERATOR_TAB 5 //Leave some space between the text and the accelerator
|
|
#define ACCELERATOR_RIGHT 15 //Leave a right margin between end of
|
|
//menu item and end of accelerator
|
|
#define MENU_LEFT_MARGIN 7 //Leave a left margin for text with no bitmaps
|
|
void CTreeMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMI)
|
|
{
|
|
CTreeItem * pItem = (CTreeItem *)(lpMI->itemData);
|
|
ASSERT(pItem != NULL);
|
|
|
|
// First, get all of the dimensions
|
|
CSize sizeUnselectedImg=pItem->GetUnselectedBitmapSize();
|
|
CSize sizeSelectedImg=pItem->GetSelectedBitmapSize();
|
|
CSize sizeText=pItem->GetTextSize();
|
|
CSize sizeAccelerator=pItem->GetAcceleratorSize();
|
|
|
|
//if there's no bitmap we need to provide a margin for the text
|
|
lpMI->itemWidth = (m_WidestImage == 0) ? MENU_LEFT_MARGIN : 0;
|
|
//Return the values depending upon whether there is an accelerator
|
|
if(sizeAccelerator.cx !=0)
|
|
{
|
|
lpMI->itemWidth += m_WidestImage + m_WidestText + sizeAccelerator.cx + ACCELERATOR_TAB + ACCELERATOR_RIGHT + (2*nIMG_SPACE);
|
|
}
|
|
else
|
|
lpMI->itemWidth += m_WidestImage + sizeText.cx + (nIMG_SPACE * 2);
|
|
|
|
int nImageHeight = max(sizeUnselectedImg.cy, sizeSelectedImg.cy);
|
|
lpMI->itemHeight = max(nImageHeight, sizeText.cy) + 4;
|
|
|
|
} // END OF FUNCTION CTreeMenu::MeasureItem()
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CTreeMenu::DrawItem
|
|
*
|
|
* PARAMETERS:
|
|
* lpDI - pointer to LPDRAWITEMSTRUCT
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
* DESCRIPTION:
|
|
* We must override this function to draw our image and text for the
|
|
* menu item, since we're owner draw style.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void CTreeMenu::DrawItem(LPDRAWITEMSTRUCT lpDI)
|
|
{
|
|
// Extract the goods from lpDI
|
|
CTreeItem * pItem = (CTreeItem *)(lpDI->itemData);
|
|
ASSERT(pItem != NULL);
|
|
CDC * pDC = CDC::FromHandle(lpDI->hDC);
|
|
CRect rc(&(lpDI->rcItem));
|
|
|
|
// Get proper colors and paint the background first
|
|
CBrush brBG;
|
|
COLORREF rgbTxt;
|
|
if (lpDI->itemState & ODS_SELECTED)
|
|
{
|
|
brBG.CreateSolidBrush(::GetSysColor(COLOR_HIGHLIGHT));
|
|
rgbTxt = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
|
|
}
|
|
else
|
|
{
|
|
brBG.CreateSolidBrush(::GetSysColor(COLOR_MENU));
|
|
rgbTxt = ::GetSysColor(COLOR_MENUTEXT);
|
|
}
|
|
pDC->FillRect(&rc, &brBG);
|
|
|
|
// Now paint the bitmap, left side of menu
|
|
rc.left += nIMG_SPACE;
|
|
CSize imgSize = DrawImage(pDC, rc, pItem, lpDI->itemState & ODS_SELECTED);
|
|
|
|
// And now the text
|
|
HFONT MenuFont;
|
|
#if defined(WIN32)
|
|
NONCLIENTMETRICS ncm;
|
|
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
|
if (::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
|
|
{
|
|
MenuFont = theApp.CreateAppFont( ncm.lfMenuFont );
|
|
}
|
|
else
|
|
{
|
|
MenuFont = (HFONT)::GetStockObject(SYSTEM_FONT);
|
|
}
|
|
#else // Win16
|
|
MenuFont = (HFONT)::GetStockObject(SYSTEM_FONT);
|
|
#endif // WIN32
|
|
|
|
CFont * pOldFont = pDC->SelectObject(CFont::FromHandle(MenuFont));
|
|
int nOldBkMode = pDC->SetBkMode(TRANSPARENT);
|
|
COLORREF rgbOldTxt = pDC->SetTextColor(rgbTxt);
|
|
|
|
//Figure out where text should go in relation to bitmaps
|
|
if(m_WidestImage == 0)
|
|
rc.left += MENU_LEFT_MARGIN;
|
|
|
|
rc.left += imgSize.cx + nIMG_SPACE + (m_WidestImage-imgSize.cx);
|
|
|
|
//Deal with the case where there is a tab for an accelerator
|
|
CString label=pItem->GetLabel();
|
|
int tabPos=label.Find('\t');
|
|
|
|
if(tabPos!=-1)
|
|
{
|
|
pDC->DrawText(label.Left(tabPos), -1, &rc, DT_LEFT | DT_VCENTER |DT_SINGLELINE);
|
|
//Give the accelerator some room on the right
|
|
rc.right-=ACCELERATOR_RIGHT + (m_WidestAccelerator - pItem->GetAcceleratorSize().cx);
|
|
pDC->DrawText(label.Right(label.GetLength()-(tabPos+1)), -1, &rc, DT_RIGHT | DT_VCENTER |DT_SINGLELINE);
|
|
}
|
|
else
|
|
{
|
|
pDC->DrawText(label, -1, &rc, DT_LEFT | DT_VCENTER | DT_SINGLELINE |DT_EXPANDTABS);
|
|
}
|
|
|
|
pDC->SetBkMode(nOldBkMode);
|
|
pDC->SetTextColor(rgbOldTxt);
|
|
pDC->SelectObject(pOldFont);
|
|
|
|
} // END OF FUNCTION CTreeMenu::DrawItem()
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CTreeMenu::DrawImage
|
|
*
|
|
* PARAMETERS:
|
|
* pDC - pointer to device context to draw on
|
|
* rect - bounding rectangle to draw in
|
|
* pItem - pointer to CTreeItem that contains the data
|
|
* bIsSelected - is this item selected
|
|
*
|
|
* RETURNS:
|
|
* width of the image, in pixels
|
|
*
|
|
* DESCRIPTION:
|
|
* Protected helper function for drawing the bitmap image in a menu
|
|
* item. We return the size of the painted image so the caller can
|
|
* position the menu text after the image.
|
|
*
|
|
****************************************************************************/
|
|
|
|
CSize CTreeMenu::DrawImage(CDC * pDC, const CRect & rect, CTreeItem * pItem,
|
|
BOOL bIsSelected)
|
|
{
|
|
CSize sizeImg;
|
|
|
|
sizeImg.cx = sizeImg.cy = 0;
|
|
|
|
CBitmap * pImg = bIsSelected ? pItem->GetSelectedImage() : pItem->GetUnselectedImage();
|
|
if (pImg != NULL)
|
|
{
|
|
HPALETTE hPalette= WFE_GetUIPalette(m_pParent);
|
|
|
|
HPALETTE hOldPalette = ::SelectPalette(pDC->m_hDC, hPalette, FALSE);
|
|
// Get image dimensions
|
|
BITMAP bmp;
|
|
pImg->GetObject(sizeof(bmp), &bmp);
|
|
|
|
sizeImg.cx = bmp.bmWidth;
|
|
sizeImg.cy = bmp.bmHeight;
|
|
|
|
// Create a scratch DC and select our bitmap into it.
|
|
CDC * pBmpDC = new CDC;
|
|
pBmpDC->CreateCompatibleDC(pDC);
|
|
CBitmap * pOldBmp = pBmpDC->SelectObject(pImg);
|
|
|
|
// Center the image horizontally and vertically
|
|
CPoint ptDst(rect.left + (m_WidestImage - sizeImg.cx)/2, rect.top +
|
|
(((rect.Height() - sizeImg.cy) + 1) / 2));
|
|
|
|
// Call the handy transparent blit function to paint the bitmap over
|
|
// the background.
|
|
if (pItem->GetIconType() == LOCAL_FILE)
|
|
{
|
|
HICON hIcon = pItem->GetLocalFileIcon();
|
|
DrawIconEx(pDC->m_hDC, ptDst.x, ptDst.y, hIcon, 0, 0, 0, NULL, DI_NORMAL);
|
|
}
|
|
else if (pItem->GetIconType() == ARBITRARY_URL)
|
|
{
|
|
NSNavCenterImage* pImage = pItem->GetCustomIcon();
|
|
HDC hDC = pDC->m_hDC;
|
|
int left = ptDst.x;
|
|
int top = ptDst.y;
|
|
int imageWidth = 16;
|
|
int imageHeight = 16;
|
|
COLORREF bkColor = bIsSelected ?
|
|
GetSysColor(COLOR_HIGHLIGHT) : GetSysColor(COLOR_MENU);
|
|
if (pImage && pImage->CompletelyLoaded())
|
|
{
|
|
// Now we draw this bad boy.
|
|
if (pImage->m_BadImage)
|
|
{
|
|
// display broken icon.
|
|
HDC tempDC = ::CreateCompatibleDC(hDC);
|
|
HBITMAP hOldBmp = (HBITMAP)::SelectObject(tempDC, NSNavCenterImage::m_hBadImageBitmap);
|
|
::StretchBlt(hDC,
|
|
left, top,
|
|
imageWidth, imageHeight,
|
|
tempDC, 0, 0,
|
|
imageWidth, imageHeight, SRCCOPY);
|
|
::SelectObject(tempDC, hOldBmp);
|
|
::DeleteDC(tempDC);
|
|
}
|
|
else if (pImage->bits )
|
|
{
|
|
// Center the image.
|
|
long width = pImage->bmpInfo->bmiHeader.biWidth;
|
|
long height = pImage->bmpInfo->bmiHeader.biHeight;
|
|
int xoffset = (imageWidth-width)/2;
|
|
int yoffset = (imageHeight-height)/2;
|
|
if (xoffset < 0) xoffset = 0;
|
|
if (yoffset < 0) yoffset = 0;
|
|
if (width > imageWidth) width = imageWidth;
|
|
if (height > imageHeight) height = imageHeight;
|
|
|
|
HPALETTE hPal = WFE_GetUIPalette(NULL);
|
|
HPALETTE hOldPal = ::SelectPalette(hDC, hPal, TRUE);
|
|
|
|
::RealizePalette(hDC);
|
|
|
|
if (pImage->maskbits)
|
|
{
|
|
WFE_StretchDIBitsWithMask(hDC, TRUE, NULL,
|
|
left+xoffset, top+xoffset,
|
|
width, height,
|
|
0, 0, width, height,
|
|
pImage->bits, pImage->bmpInfo,
|
|
pImage->maskbits, FALSE, bkColor);
|
|
}
|
|
else
|
|
{
|
|
::StretchDIBits(hDC,
|
|
left+xoffset, top+xoffset,
|
|
width, height,
|
|
0, 0, width, height, pImage->bits, pImage->bmpInfo, DIB_RGB_COLORS,
|
|
SRCCOPY);
|
|
}
|
|
|
|
::SelectPalette(hDC, hOldPal, TRUE);
|
|
}
|
|
}
|
|
}
|
|
else ::FEU_TransBlt(pBmpDC, pDC, CPoint(0, 0), ptDst, sizeImg.cx, sizeImg.cy, hPalette, PALETTERGB(255, 0, 255));
|
|
|
|
::SelectPalette(pDC->m_hDC, hOldPalette, TRUE);
|
|
// Cleanup
|
|
pBmpDC->SelectObject(pOldBmp);
|
|
pBmpDC->DeleteDC();
|
|
delete pBmpDC;
|
|
}
|
|
|
|
return(sizeImg);
|
|
|
|
} // END OF FUNCTION CTreeMenu::DrawImage()
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Class: CPopupTree
|
|
*
|
|
* DESCRIPTION:
|
|
* This class represents a hierarchical popup menu object that can be
|
|
* used for selecting from a list of sub-categorized items.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CPopupTree::CPopupTree
|
|
*
|
|
* PARAMETERS:
|
|
* pItems - list of items for filling the tree
|
|
*
|
|
* RETURNS:
|
|
* N/A
|
|
*
|
|
* DESCRIPTION:
|
|
* Constructor.
|
|
*
|
|
****************************************************************************/
|
|
|
|
CPopupTree::CPopupTree(CTreeItemList * pItems)
|
|
{
|
|
m_pTree = pItems;
|
|
|
|
} // END OF FUNCTION CPopupTree::CPopupTree()
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CPopupTree::~CPopupTree
|
|
*
|
|
* PARAMETERS:
|
|
* N/A
|
|
*
|
|
* RETURNS:
|
|
* N/A
|
|
*
|
|
* DESCRIPTION:
|
|
* Destructor.
|
|
*
|
|
****************************************************************************/
|
|
|
|
CPopupTree::~CPopupTree()
|
|
{
|
|
// Time to take out the trash! We maintain a list of objects that were
|
|
// dynamically allocated on the heap, but couldn't be conveniently
|
|
// deleted.
|
|
for (int i = 0; i < m_GarbageList.GetSize(); i++)
|
|
{
|
|
CObject * pObject = m_GarbageList.GetAt(i);
|
|
if (pObject != NULL)
|
|
{
|
|
delete pObject;
|
|
}
|
|
}
|
|
m_GarbageList.RemoveAll();
|
|
|
|
} // END OF FUNCTION CPopupTree::~CPopupTree()
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CPopupTree::Activate
|
|
*
|
|
* PARAMETERS:
|
|
* nX - horizontal position (screen coordinates)
|
|
* nY - vertical position
|
|
* pParent - pointer to parent window
|
|
*
|
|
* RETURNS:
|
|
* TRUE if creation is successful
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to display the popup menu, after construction.
|
|
*
|
|
****************************************************************************/
|
|
|
|
BOOL CPopupTree::Activate(int nX, int nY, CWnd * pParent)
|
|
{
|
|
CTreeMenu Menu;
|
|
BOOL bRtn = Menu.Create();
|
|
|
|
// Now construct the menu from our tree
|
|
BuildMenu(&Menu, m_pTree);
|
|
|
|
if (bRtn)
|
|
{
|
|
bRtn = Menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON, nX, nY, pParent);
|
|
}
|
|
|
|
return(bRtn);
|
|
|
|
} // END OF FUNCTION CPopupTree::Activate()
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CPopupTree::BuildMenu
|
|
*
|
|
* PARAMETERS:
|
|
* pMenu - pointer to the menu to be constructed
|
|
* pItems - list of item objects for building the menu
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to construct a custom menu from a list
|
|
* of item objects. It is recursive and can be called for each node
|
|
* that contains sub-items.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void CPopupTree::BuildMenu(CTreeMenu * pMenu, CTreeItemList * pItems)
|
|
{
|
|
for (int i = 0; i < pItems->GetSize(); i++)
|
|
{
|
|
CTreeItem * pItem = pItems->Get(i);
|
|
ASSERT(pItem != NULL);
|
|
if (pItem != NULL)
|
|
{
|
|
// See if this item has sub-items
|
|
CTreeItemList * pSubItems = pItem->GetSubItems();
|
|
if (pSubItems->GetSize() > 0)
|
|
{
|
|
// It does, so create a new menu and call this function
|
|
// recursively to construct it.
|
|
CTreeMenu * pSubMenu = new CTreeMenu;
|
|
// m_GarbageList.Add(pSubMenu);
|
|
pSubMenu->Create();
|
|
BuildMenu(pSubMenu, pSubItems);
|
|
pSubMenu->CalculateItemDimensions();
|
|
// Last but not least, add the new branch to the main menu
|
|
BOOL bOk = pMenu->AddItem(pItem, 0, pSubMenu);
|
|
ASSERT(bOk);
|
|
}
|
|
else
|
|
{
|
|
// Just add top-level item
|
|
BOOL bOk = pMenu->AddItem(pItem);
|
|
ASSERT(bOk);
|
|
}
|
|
}
|
|
}
|
|
pMenu->CalculateItemDimensions();
|
|
} // END OF FUNCTION CPopupTree::BuildMenu()
|