496 lines
12 KiB
C++
496 lines
12 KiB
C++
// ==========================================================================
|
|
// Class Implementation
|
|
// COXHistoryCtrl
|
|
// ==========================================================================
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "OXImageListBox.h"
|
|
#include "UTB64Bit.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COXImageListBox
|
|
|
|
COXImageListBox::COXImageListBox(int cx/*=::GetSystemMetrics(SM_CXSMICON)*/,
|
|
int cy/*=::GetSystemMetrics(SM_CYSMICON)*/,
|
|
UINT nFlags/*=ILC_COLOR24|ILC_MASK*/) :
|
|
m_nOrigWidth(cx),
|
|
m_nOrigHeight(cy),
|
|
m_clrBackground(::GetSysColor(COLOR_WINDOW)),
|
|
m_clrHighlight(::GetSysColor(COLOR_HIGHLIGHT))
|
|
|
|
{
|
|
VERIFY(m_imageList.Create(cx,cy,nFlags,0,0));
|
|
}
|
|
|
|
|
|
COXImageListBox::~COXImageListBox()
|
|
{
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(COXImageListBox, CListBox)
|
|
//{{AFX_MSG_MAP(COXImageListBox)
|
|
ON_WM_CREATE()
|
|
ON_WM_DESTROY()
|
|
ON_WM_ERASEBKGND()
|
|
//}}AFX_MSG_MAP
|
|
ON_MESSAGE(LB_DELETESTRING,OnDeleteString)
|
|
ON_MESSAGE(LB_RESETCONTENT,OnResetContent)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COXImageListBox message handlers
|
|
|
|
int COXImageListBox::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if(CListBox::OnCreate(lpCreateStruct) == -1)
|
|
return -1;
|
|
|
|
// TODO: Add your specialized creation code here
|
|
if(!InitializeImageListBox())
|
|
{
|
|
TRACE(_T("COXImageListBox::OnCreate: failed to initialize the control\n"));
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void COXImageListBox::OnDestroy()
|
|
{
|
|
EmptyImageList();
|
|
CListBox::OnDestroy();
|
|
}
|
|
|
|
|
|
void COXImageListBox::PreSubclassWindow()
|
|
{
|
|
// TODO: Add your specialized code here and/or call the base class
|
|
|
|
DWORD dwStyle=GetStyle();
|
|
// make sure LBS_OWNERDRAWFIXED and LBS_MULTICOLUMN styles are specified
|
|
ASSERT(dwStyle&LBS_OWNERDRAWFIXED);
|
|
ASSERT(dwStyle&LBS_MULTICOLUMN);
|
|
// make sure LBS_OWNERDRAWVARIABLE and LBS_MULTIPLESEL styles are not specified
|
|
ASSERT(!(dwStyle&(LBS_OWNERDRAWVARIABLE|LBS_MULTIPLESEL)));
|
|
|
|
// make sure the control is empty
|
|
ASSERT(GetCount()==0);
|
|
|
|
_AFX_THREAD_STATE* pThreadState=AfxGetThreadState();
|
|
// hook not already in progress
|
|
if(pThreadState->m_pWndInit==NULL)
|
|
{
|
|
if(!InitializeImageListBox())
|
|
{
|
|
TRACE(_T("COXImageListBox::PreSubclassWindow: failed to initialize the control\n"));
|
|
}
|
|
}
|
|
|
|
CListBox::PreSubclassWindow();
|
|
}
|
|
|
|
|
|
BOOL COXImageListBox::PreCreateWindow(CREATESTRUCT& cs)
|
|
{
|
|
// TODO: Add your specialized code here and/or call the base class
|
|
|
|
// make sure LBS_OWNERDRAWVARIABLE and LBS_MULTIPLESEL styles are not specified
|
|
cs.style&=~(LBS_OWNERDRAWVARIABLE|LBS_MULTIPLESEL);
|
|
// make sure LBS_OWNERDRAWFIXED and LBS_MULTICOLUMN styles are specified
|
|
cs.style|=LBS_OWNERDRAWFIXED|LBS_MULTICOLUMN;
|
|
|
|
return CListBox::PreCreateWindow(cs);
|
|
}
|
|
|
|
|
|
BOOL COXImageListBox::InitializeImageListBox()
|
|
{
|
|
ASSERT(::IsWindow(GetSafeHwnd()));
|
|
|
|
if(m_imageList.GetImageCount()>0)
|
|
{
|
|
IMAGEINFO imageInfo;
|
|
VERIFY(m_imageList.GetImageInfo(0,&imageInfo));
|
|
CRect rect(imageInfo.rcImage);
|
|
SetItemHeight(0,rect.Height()+rect.Height()/4);
|
|
SetColumnWidth(rect.Width()+rect.Width()/4);
|
|
}
|
|
else
|
|
{
|
|
SetItemHeight(0,m_nOrigWidth+m_nOrigWidth/4);
|
|
SetColumnWidth(m_nOrigHeight+m_nOrigHeight/4);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
LRESULT COXImageListBox::OnDeleteString(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
LRESULT lResult=Default();
|
|
if(lResult!=LB_ERR)
|
|
{
|
|
m_imageList.Remove(PtrToInt(wParam));
|
|
// update internal data
|
|
for(int nIndex=(int)wParam; nIndex<GetCount(); nIndex++)
|
|
{
|
|
SetItemData(nIndex,GetItemData(nIndex)-1);
|
|
}
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
LRESULT COXImageListBox::OnResetContent(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
LRESULT lResult=Default();
|
|
#if _MFC_VER>0x0421
|
|
VERIFY(m_imageList.SetImageCount(0));
|
|
#else
|
|
while(m_imageList.Remove(0));
|
|
#endif
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
void COXImageListBox::EmptyImageList()
|
|
{
|
|
ResetContent();
|
|
}
|
|
|
|
|
|
int COXImageListBox::SetImageList(CImageList* pImageList)
|
|
{
|
|
EmptyImageList();
|
|
|
|
if(pImageList==NULL || pImageList->GetImageCount()==0)
|
|
return 0;
|
|
|
|
VERIFY(m_imageList.DeleteImageList());
|
|
|
|
IMAGEINFO imageInfo;
|
|
VERIFY(pImageList->GetImageInfo(0,&imageInfo));
|
|
CRect rect(imageInfo.rcImage);
|
|
#if _MFC_VER > 0x0421
|
|
VERIFY(m_imageList.Create(pImageList));
|
|
#else
|
|
VERIFY(m_imageList.Create(rect.Width(),rect.Height(),ILC_COLOR24|ILC_MASK,0,0));
|
|
for(int nButtonIndex=0; nButtonIndex<pImageList->GetImageCount(); nButtonIndex++)
|
|
{
|
|
HICON hIcon=pImageList->ExtractIcon(nButtonIndex);
|
|
ASSERT(hIcon!=NULL);
|
|
VERIFY(m_imageList.Add(hIcon)!=-1);
|
|
VERIFY(::DestroyIcon(hIcon));
|
|
}
|
|
#endif
|
|
SetItemHeight(0,rect.Height()+rect.Height()/4);
|
|
SetColumnWidth(rect.Width()+rect.Width()/4);
|
|
|
|
for(int nIndex=0; nIndex<m_imageList.GetImageCount(); nIndex++)
|
|
{
|
|
AddString((LPCTSTR) (INT_PTR)nIndex);
|
|
}
|
|
|
|
return m_imageList.GetImageCount();
|
|
}
|
|
|
|
|
|
int COXImageListBox::AddImageList(CImageList* pImageList)
|
|
{
|
|
if(m_imageList.GetImageCount()==0)
|
|
return -1;
|
|
|
|
ASSERT(pImageList!=NULL);
|
|
if(pImageList==NULL)
|
|
return -1;
|
|
|
|
if(pImageList->GetImageCount()==0)
|
|
return -1;
|
|
|
|
IMAGEINFO imageInfo;
|
|
VERIFY(pImageList->GetImageInfo(0,&imageInfo));
|
|
CRect rect(imageInfo.rcImage);
|
|
VERIFY(m_imageList.GetImageInfo(0,&imageInfo));
|
|
if(rect.Width()!=imageInfo.rcImage.right-imageInfo.rcImage.left ||
|
|
rect.Height()!=imageInfo.rcImage.bottom-imageInfo.rcImage.top)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int nLastImage=GetCount();
|
|
int nIndex=0;
|
|
for(nIndex=0; nIndex<pImageList->GetImageCount(); nIndex++)
|
|
{
|
|
HICON hIcon=pImageList->ExtractIcon(nIndex);
|
|
ASSERT(hIcon!=NULL);
|
|
VERIFY(m_imageList.Add(hIcon)!=-1);
|
|
VERIFY(::DestroyIcon(hIcon));
|
|
}
|
|
|
|
for(nIndex=nLastImage; nIndex<m_imageList.GetImageCount(); nIndex++)
|
|
{
|
|
VERIFY(AddString((LPCTSTR)(INT_PTR)nIndex)>=0);
|
|
}
|
|
|
|
return nLastImage;
|
|
}
|
|
|
|
int COXImageListBox::AddImage(CBitmap* pbmImage, CBitmap* pbmMask)
|
|
{
|
|
if(m_imageList.Add(pbmImage,pbmMask)==-1)
|
|
return -1;
|
|
|
|
return AddString((LPCTSTR)(INT_PTR)GetCount());
|
|
}
|
|
|
|
int COXImageListBox::AddImage(CBitmap* pbmImage, COLORREF crMask)
|
|
{
|
|
if(m_imageList.Add(pbmImage,crMask)==-1)
|
|
return -1;
|
|
|
|
return AddString((LPCTSTR)(INT_PTR)GetCount());
|
|
}
|
|
|
|
int COXImageListBox::AddImage(HICON hIcon)
|
|
{
|
|
if(m_imageList.Add(hIcon)==-1)
|
|
return -1;
|
|
|
|
return AddString((LPCTSTR)(INT_PTR)GetCount());
|
|
}
|
|
|
|
|
|
BOOL COXImageListBox::ReplaceImage(int nImage, CBitmap* pbmImage,
|
|
CBitmap* pbmMask/*=NULL*/)
|
|
{
|
|
if(nImage<0 || nImage>=GetCount())
|
|
return FALSE;
|
|
|
|
return m_imageList.Replace(nImage,pbmImage,pbmMask);
|
|
}
|
|
|
|
BOOL COXImageListBox::ReplaceImage(int nImage, HICON hIcon)
|
|
{
|
|
if(nImage<0 || nImage>=GetCount())
|
|
return FALSE;
|
|
|
|
return m_imageList.Replace(nImage,hIcon);
|
|
}
|
|
|
|
|
|
BOOL COXImageListBox::GetImageInfo(int nImage, IMAGEINFO* pImageInfo) const
|
|
{
|
|
ASSERT(pImageInfo!=NULL);
|
|
if(nImage<0 || nImage>=GetCount())
|
|
return FALSE;
|
|
|
|
return m_imageList.GetImageInfo(nImage,pImageInfo);
|
|
}
|
|
|
|
HICON COXImageListBox::GetIcon(int nImage)
|
|
{
|
|
if(nImage<0 || nImage>=GetCount())
|
|
return NULL;
|
|
|
|
return m_imageList.ExtractIcon(nImage);
|
|
}
|
|
|
|
|
|
HICON COXImageListBox::GetSelectedIcon()
|
|
{
|
|
int nImage=GetCurSel();
|
|
if(nImage==LB_ERR)
|
|
return NULL;
|
|
|
|
return m_imageList.ExtractIcon(nImage);
|
|
}
|
|
|
|
|
|
BOOL COXImageListBox::LoadIconsFromFile(LPCTSTR lpszFileName/*=NULL*/,
|
|
BOOL bSmallIcon/*=TRUE*/)
|
|
{
|
|
// it might take time to load icons from big file
|
|
CWaitCursor waitCursor;
|
|
|
|
// make sure the specified file exists
|
|
if(lpszFileName!=NULL && lstrlen(lpszFileName)>0)
|
|
{
|
|
CFileStatus fileStatus;
|
|
if(!CFile::GetStatus(lpszFileName,fileStatus))
|
|
{
|
|
TRACE(_T("COXImageListBox::LoadIconsFromFile: failed to find file %s\n"),lpszFileName);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
CString sFileName;
|
|
// if NULL then retrieve the name of the running executable
|
|
if(lpszFileName==NULL || lstrlen(lpszFileName)==0)
|
|
{
|
|
//get the application path
|
|
::GetModuleFileName(NULL,sFileName.GetBuffer(MAX_PATH),MAX_PATH);
|
|
sFileName.ReleaseBuffer();
|
|
}
|
|
else
|
|
{
|
|
sFileName=lpszFileName;
|
|
}
|
|
|
|
if(sFileName.IsEmpty())
|
|
{
|
|
TRACE(_T("COXImageListBox::LoadIconsFromFile: empty file name has been specified\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
CImageList imageList;
|
|
// create new image list to accomodate icon size
|
|
if(bSmallIcon)
|
|
{
|
|
VERIFY(imageList.Create(::GetSystemMetrics(SM_CXSMICON),
|
|
::GetSystemMetrics(SM_CYSMICON),ILC_COLOR24|ILC_MASK,0,0));
|
|
}
|
|
else
|
|
{
|
|
VERIFY(imageList.Create(::GetSystemMetrics(SM_CXICON),
|
|
::GetSystemMetrics(SM_CYICON),ILC_COLOR24|ILC_MASK,0,0));
|
|
}
|
|
|
|
// try to extract icons from the file
|
|
UINT nIconCount=::ExtractIconEx(sFileName,-1,NULL,NULL,0);
|
|
if(nIconCount==0)
|
|
return TRUE;
|
|
|
|
HICON* arrIcons=new HICON[nIconCount];
|
|
ASSERT(arrIcons!=NULL);
|
|
if(bSmallIcon)
|
|
{
|
|
VERIFY(::ExtractIconEx(sFileName,0,NULL,arrIcons,nIconCount)==nIconCount);
|
|
}
|
|
else
|
|
{
|
|
VERIFY(::ExtractIconEx(sFileName,0,arrIcons,NULL,nIconCount)==nIconCount);
|
|
}
|
|
|
|
for(UINT nIndex=0; nIndex<nIconCount; nIndex++)
|
|
{
|
|
VERIFY(imageList.Add(arrIcons[nIndex])!=-1);
|
|
::DestroyIcon(arrIcons[nIndex]);
|
|
}
|
|
|
|
delete[] arrIcons;
|
|
|
|
return (SetImageList(&imageList)==(int)nIconCount);
|
|
}
|
|
|
|
|
|
void COXImageListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
|
|
{
|
|
// TODO: Add your code to draw the specified item
|
|
if(m_imageList.GetImageCount()==0)
|
|
return;
|
|
|
|
int nImageIndex=(int)lpDrawItemStruct->itemData;
|
|
if(nImageIndex<0 || nImageIndex>=GetCount())
|
|
return;
|
|
|
|
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
|
|
CRect rect(lpDrawItemStruct->rcItem);
|
|
CRect rectIcon=rect;
|
|
rectIcon.DeflateRect(rect.Width()/10,rect.Height()/10);
|
|
|
|
if((lpDrawItemStruct->itemAction & (ODA_SELECT|ODA_DRAWENTIRE)))
|
|
{
|
|
// item has been selected - hilite frame
|
|
CBrush brush(lpDrawItemStruct->itemState & ODS_SELECTED ?
|
|
m_clrHighlight : m_clrBackground);
|
|
pDC->FillRect(&rect,&brush);
|
|
}
|
|
else if((lpDrawItemStruct->itemAction & (ODA_FOCUS|ODA_DRAWENTIRE)) &&
|
|
!(lpDrawItemStruct->itemState & ODS_FOCUS))
|
|
{
|
|
CBrush brush((lpDrawItemStruct->itemState & ODS_SELECTED) ?
|
|
m_clrHighlight : m_clrBackground);
|
|
pDC->FrameRect(rect,&brush);
|
|
}
|
|
|
|
if (!(lpDrawItemStruct->itemState & ODS_SELECTED) &&
|
|
(lpDrawItemStruct->itemAction & ODA_SELECT))
|
|
{
|
|
// Item has been unselected - remove frame
|
|
pDC->IntersectClipRect(rect);
|
|
SendMessage(WM_ERASEBKGND,(WPARAM)lpDrawItemStruct->hDC);
|
|
}
|
|
|
|
if(lpDrawItemStruct->itemAction&(ODA_SELECT|ODA_DRAWENTIRE))
|
|
{
|
|
UINT nStyle=ILD_TRANSPARENT;
|
|
m_imageList.Draw(pDC,nImageIndex,rectIcon.TopLeft(),nStyle);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL COXImageListBox::OnEraseBkgnd(CDC* pDC)
|
|
{
|
|
// TODO: Add your message handler code here and/or call default
|
|
|
|
CRect rect;
|
|
GetClientRect(rect);
|
|
if(GetCount()==0)
|
|
{
|
|
CBrush brush(m_clrBackground);
|
|
pDC->FillRect(rect,&brush);
|
|
}
|
|
else
|
|
{
|
|
CRect rectItem;
|
|
VERIFY(GetItemRect(GetCount()-1,rectItem)!=LB_ERR);
|
|
if(rectItem.bottom<rect.bottom)
|
|
{
|
|
CRect rectUpdate=rect;
|
|
rectUpdate.top=rectItem.bottom;
|
|
CBrush brush(m_clrBackground);
|
|
pDC->FillRect(rectUpdate,&brush);
|
|
}
|
|
|
|
if(rectItem.right<rect.right)
|
|
{
|
|
CRect rectUpdate=rect;
|
|
rectUpdate.left=rectItem.right;
|
|
CBrush brush(m_clrBackground);
|
|
pDC->FillRect(rectUpdate,&brush);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|