2025-11-27 16:46:48 +09:00

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;
}