2324 lines
70 KiB
C++
2324 lines
70 KiB
C++
/*=============================================================================
|
|
*
|
|
* Filename: Sort3Lst.cpp
|
|
* Version: 1.0
|
|
* Date: 06/11/96
|
|
* Author: V.L.
|
|
*
|
|
* Description: implementation of ThreeSortedList class
|
|
*
|
|
*===========================================================================*/
|
|
|
|
#include "stdafx.h"
|
|
#ifdef ACTIVE_EDITOR
|
|
|
|
#include "itf/Sort3lst.hpp"
|
|
#include "itf/CPADD.hpp"
|
|
#include "IncTUT.h"
|
|
|
|
/*=============================================================================
|
|
* implementation of CBitmapList
|
|
=============================================================================*/
|
|
|
|
/*BOOL CTextureDlg::m_fn_bIsAValidTexture(CString csFileName)
|
|
{
|
|
FILE *hFile;
|
|
BITMAPFILEHEADER bf;
|
|
BITMAPINFOHEADER bi;
|
|
|
|
if ( (hFile = fopen(csFileName, "rb")) == NULL)
|
|
return FALSE;
|
|
|
|
CString csExtension(strrchr(LPCTSTR(csFileName), '.'));
|
|
if ( !csExtension.CompareNoCase(".tga") )
|
|
{
|
|
unsigned char a18_ucTgaHeader[18];
|
|
//read TGA header
|
|
if ( fread(a18_ucTgaHeader, 18, 1, hFile) != 1 )
|
|
{
|
|
fclose(hFile);
|
|
return FALSE;
|
|
}
|
|
//get image width and height
|
|
bi.biWidth = (a18_ucTgaHeader[13]<<8) + a18_ucTgaHeader[12];
|
|
bi.biHeight = (a18_ucTgaHeader[15]<<8) + a18_ucTgaHeader[14];
|
|
bi.biBitCount = a18_ucTgaHeader[16];
|
|
}
|
|
else if ( !csExtension.CompareNoCase(".bmp") )
|
|
{
|
|
if (sizeof(bf) != fread( &bf, 1, sizeof(bf), hFile ))
|
|
{
|
|
fclose(hFile);
|
|
return FALSE;
|
|
}
|
|
if (bf.bfType != 0x4d42 ) //BM
|
|
{
|
|
fclose(hFile);
|
|
return FALSE;
|
|
}
|
|
if (sizeof(bi) != fread( &bi, 1, sizeof(bi), hFile ))
|
|
{
|
|
fclose(hFile);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fclose(hFile);
|
|
return FALSE;
|
|
}
|
|
|
|
// verify color depth
|
|
if ( (bi.biBitCount == 24) || (bi.biBitCount == 32) )
|
|
{
|
|
LONG lSize = bi.biWidth * bi.biHeight;
|
|
LONG lMask = 1;
|
|
while (lMask != 0)
|
|
{
|
|
if ((lSize ^ lMask) == 0)
|
|
{
|
|
fclose(hFile);
|
|
return TRUE;
|
|
}
|
|
lMask <<= 1;
|
|
}
|
|
}
|
|
|
|
fclose(hFile);
|
|
return FALSE;
|
|
} */
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : load a bitmap file, returns the handle on the image
|
|
*---------------------------------------------------------------------------*/
|
|
HBITMAP CBitmapList::m_hLoadImage(
|
|
CString _csName, int _cx, int _cy,
|
|
CString _csNameOfSmallVersion,
|
|
BOOL _bOverrideOptimizedImages
|
|
)
|
|
{
|
|
HBITMAP hBitmap = NULL;
|
|
CString csExtension = strrchr(LPCTSTR(_csName), '.');
|
|
short wImageType;
|
|
|
|
if ( !csExtension.CompareNoCase(".bmp") ) // load a bmp file
|
|
wImageType = 'BM';
|
|
else if ( !csExtension.CompareNoCase(".tga") ) // load a tga file
|
|
wImageType = 'TG';
|
|
else
|
|
wImageType = 0;
|
|
|
|
if ( wImageType )
|
|
{
|
|
FILE *p_stTextureFile;
|
|
p_stTextureFile = fopen(LPCTSTR(_csName),"rb");
|
|
if ( p_stTextureFile )
|
|
{
|
|
BITMAPINFO stBitmapInfo;
|
|
unsigned char aDEF_ucReadBuffer[512L*4L];
|
|
short wTgaWidth, wTgaHeight;
|
|
unsigned char ucBBP;
|
|
|
|
if ( wImageType == 'BM' ) // load a bmp file
|
|
{
|
|
BITMAPFILEHEADER bf;
|
|
BITMAPINFOHEADER bi;
|
|
fread(&bf, 1, sizeof(bf), p_stTextureFile);
|
|
fread(&bi, 1, sizeof(bi), p_stTextureFile);
|
|
stBitmapInfo.bmiHeader = bi;
|
|
wTgaWidth = (short) bi.biWidth;
|
|
wTgaHeight = (short) bi.biHeight;
|
|
ucBBP = (unsigned char) bi.biBitCount;
|
|
}
|
|
else if ( wImageType == 'TG' ) // load a bmp file
|
|
{
|
|
//read TGA header
|
|
fread(aDEF_ucReadBuffer,18,1,p_stTextureFile);
|
|
//get image width and height
|
|
wTgaWidth = (aDEF_ucReadBuffer[13]<<8) + aDEF_ucReadBuffer[12];
|
|
wTgaHeight = (aDEF_ucReadBuffer[15]<<8) + aDEF_ucReadBuffer[14];
|
|
ucBBP = aDEF_ucReadBuffer[16];
|
|
}
|
|
else
|
|
{
|
|
if ( m_bLoadOnlyOptimizedImages )
|
|
{
|
|
CString csBadTextureName = _csName + "\n";
|
|
if ( m_hBadTexturesLogFile )
|
|
{
|
|
fprintf(m_hBadTexturesLogFile, LPCTSTR(csBadTextureName));
|
|
fflush(m_hBadTexturesLogFile);
|
|
}
|
|
}
|
|
fclose(p_stTextureFile);
|
|
return NULL;
|
|
}
|
|
//here, we have read the header of the image file, either BMP or TGA
|
|
|
|
//check that the image has the proper size, only if we are trying to load the original one
|
|
if
|
|
(
|
|
(m_bLoadOnlyOptimizedImages && !_bOverrideOptimizedImages)
|
|
#if defined(D_UseSmallBitmaps)
|
|
&& !_csNameOfSmallVersion.IsEmpty() //do not test image optimisation on small versions
|
|
#endif //D_UseSmallBitmaps
|
|
)
|
|
{
|
|
LONG lSize = wTgaWidth * wTgaHeight;
|
|
LONG lMask = 1;
|
|
while (lMask != 0)
|
|
{
|
|
if ((lSize ^ lMask) == 0)
|
|
break;
|
|
else
|
|
lMask <<= 1;
|
|
}
|
|
if ( lMask == 0 )
|
|
{
|
|
CString csBadTextureName = _csName + "\n";
|
|
if ( m_hBadTexturesLogFile )
|
|
{
|
|
fprintf(m_hBadTexturesLogFile, LPCTSTR(csBadTextureName));
|
|
fflush(m_hBadTexturesLogFile);
|
|
}
|
|
fclose(p_stTextureFile);
|
|
return NULL;
|
|
}
|
|
}
|
|
//here, the file has a size that we accept
|
|
|
|
if ( wImageType == 'BM' ) // load a bmp file with the Windows API
|
|
{
|
|
fclose(p_stTextureFile);
|
|
hBitmap = (HBITMAP) LoadImage(NULL, _csName, IMAGE_BITMAP, _cx, _cy, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
|
|
}
|
|
else if ( wImageType = 'TG' ) // load a tga file
|
|
{
|
|
BITMAPINFO stBitmapInfo;
|
|
unsigned char *pRawBits;
|
|
|
|
//we load only true color images
|
|
if ( ucBBP != 24 && ucBBP != 32 )
|
|
{
|
|
if ( m_bLoadOnlyOptimizedImages )
|
|
{
|
|
CString csBadTextureName = _csName + "\n";
|
|
if ( m_hBadTexturesLogFile )
|
|
{
|
|
fprintf(m_hBadTexturesLogFile, LPCTSTR(csBadTextureName));
|
|
fflush(m_hBadTexturesLogFile);
|
|
}
|
|
}
|
|
fclose(p_stTextureFile);
|
|
return NULL;
|
|
}
|
|
|
|
//get the number of bytes per pixel (3 or 4)
|
|
ucBBP >>= 3;
|
|
|
|
ASSERT(wTgaWidth * ucBBP <= sizeof(aDEF_ucReadBuffer));
|
|
//fill the other useful fields of the header
|
|
stBitmapInfo.bmiHeader.biWidth = _cx;
|
|
stBitmapInfo.bmiHeader.biHeight = _cy;
|
|
stBitmapInfo.bmiHeader.biPlanes = 1;
|
|
stBitmapInfo.bmiHeader.biBitCount = 24; //we dont care about alpha channel here, so we wont save it
|
|
stBitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
stBitmapInfo.bmiHeader.biCompression = BI_RGB;
|
|
stBitmapInfo.bmiHeader.biSizeImage = 0 /*stBitmapInfo.bmiHeader.biWidth * stBitmapInfo.bmiHeader.biHeight * ucBBP*/;
|
|
stBitmapInfo.bmiHeader.biXPelsPerMeter = 0;
|
|
stBitmapInfo.bmiHeader.biYPelsPerMeter = 0;
|
|
stBitmapInfo.bmiHeader.biClrUsed = 0;
|
|
stBitmapInfo.bmiHeader.biClrImportant = 0;
|
|
//create the bitmap image of the size we want (_cx, _cy)
|
|
hBitmap = CreateDIBSection(NULL, &stBitmapInfo, DIB_RGB_COLORS, (void **) &pRawBits, NULL, 0);
|
|
//copy/stretch the tga raw data in the image's bits area
|
|
if ( hBitmap && pRawBits )
|
|
{
|
|
long lDestLine, lSrcLine, lOldSrcLine = -1;
|
|
for ( lDestLine = 0; lDestLine < _cy; lDestLine ++ )
|
|
{
|
|
lSrcLine = (lDestLine * wTgaHeight) / _cy;
|
|
//read as many lines in the as required to reach the proper source data
|
|
while ( lSrcLine != lOldSrcLine )
|
|
{
|
|
lOldSrcLine ++;
|
|
//read a line in the file
|
|
fread((void*)aDEF_ucReadBuffer, ucBBP, wTgaWidth, p_stTextureFile);
|
|
}
|
|
|
|
unsigned char *pSrcLine = aDEF_ucReadBuffer;
|
|
unsigned char *pDestLine = pRawBits + lDestLine * _cx * 3;
|
|
|
|
long lDestPixel, lSrcPixel;
|
|
for ( lDestPixel = 0; lDestPixel < _cx; lDestPixel ++ )
|
|
{
|
|
lSrcPixel = (lDestPixel * wTgaWidth) / _cx;
|
|
unsigned char *pSrcPixel = pSrcLine + lSrcPixel * ucBBP;
|
|
unsigned char *pDestPixel = pDestLine + lDestPixel * 3;
|
|
|
|
*(pDestPixel ++) = *(pSrcPixel ++);
|
|
*(pDestPixel ++) = *(pSrcPixel ++);
|
|
*(pDestPixel ++) = *(pSrcPixel ++);
|
|
} //column scan loop
|
|
} //image scan loop
|
|
} //bitmap creation test
|
|
else
|
|
hBitmap = NULL;
|
|
fclose(p_stTextureFile);
|
|
} //image type test
|
|
} //file open test
|
|
}//image type test
|
|
|
|
#if defined(D_UseSmallBitmaps)
|
|
//save a small copy if asked for
|
|
if ( !_csNameOfSmallVersion.IsEmpty() && hBitmap )
|
|
{
|
|
//create or truncate the file
|
|
CFile oFile;
|
|
if ( oFile.Open(_csNameOfSmallVersion, CFile::modeCreate + CFile::typeBinary + CFile::modeWrite) )
|
|
{
|
|
BITMAPFILEHEADER bf;
|
|
BITMAPINFOHEADER bi;
|
|
CBitmap *p_oBitmap = CBitmap::FromHandle(hBitmap);
|
|
BITMAP stBitmap;
|
|
p_oBitmap->GetBitmap(&stBitmap);
|
|
//prepare the file's headers
|
|
bf.bfType = 'MB'; //reverse order because of f**ing intel byte swaps!!!
|
|
//file header + image header + image data
|
|
bf.bfSize = sizeof(bf) + sizeof(bi) + stBitmap.bmWidthBytes * stBitmap.bmHeight;
|
|
bf.bfReserved1 = 0;
|
|
bf.bfReserved2 = 0;
|
|
bf.bfOffBits = sizeof(bf) + sizeof(bi);
|
|
bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
bi.biWidth = stBitmap.bmWidth;
|
|
bi.biHeight = stBitmap.bmHeight;
|
|
bi.biPlanes = stBitmap.bmPlanes;
|
|
bi.biBitCount = stBitmap.bmBitsPixel;
|
|
bi.biCompression = BI_RGB;
|
|
bi.biSizeImage = 0;
|
|
bi.biXPelsPerMeter = 0;
|
|
bi.biYPelsPerMeter = 0;
|
|
bi.biClrUsed = 0;
|
|
bi.biClrImportant = 0;
|
|
//write the headers
|
|
oFile.Write(&bf, sizeof(bf));
|
|
oFile.Write(&bi, sizeof(bi));
|
|
//write the image data
|
|
oFile.Write(stBitmap.bmBits, stBitmap.bmWidthBytes * stBitmap.bmHeight);
|
|
oFile.Close();
|
|
}
|
|
}
|
|
#endif //D_UseSmallBitmaps
|
|
|
|
return hBitmap;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : Constructor
|
|
*---------------------------------------------------------------------------*/
|
|
CBitmapList::CBitmapList()
|
|
{
|
|
m_oMaxSize.cx = -1;
|
|
m_oMaxSize.cy = -1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : Destructor
|
|
*---------------------------------------------------------------------------*/
|
|
CBitmapList::~CBitmapList()
|
|
{
|
|
POSITION pos = m_oItemList.GetHeadPosition();
|
|
tdstBitmapItem *p_stItem;
|
|
// delete all item in list
|
|
while (pos)
|
|
{
|
|
p_stItem = m_oItemList.GetNext( pos );
|
|
if (!p_stItem->m_bDeleted)
|
|
{
|
|
DeleteObject( p_stItem->m_hBitmap );
|
|
}
|
|
delete (p_stItem);
|
|
}
|
|
|
|
if ( m_bLoadOnlyOptimizedImages && m_hBadTexturesLogFile )
|
|
{
|
|
fclose(m_hBadTexturesLogFile);
|
|
m_hBadTexturesLogFile = NULL;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : check out the creation of bitmaplist
|
|
*---------------------------------------------------------------------------*/
|
|
void CBitmapList::m_fn_vIsCreated()
|
|
{
|
|
if ( (m_oMaxSize.cx == -1) && (m_oMaxSize.cy == -1) )
|
|
{
|
|
AfxMessageBox("Error : CBitmapList not created");
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : creation of CBitmapList
|
|
* three case : _bSize = C_cFixedSize : bitmap size is fixed and equal to (_cx, _cy)
|
|
* _bSize = C_cVariableSize : bitmap size is variable and
|
|
* _cx = 0 or _cy = 0: not limited
|
|
* else (_cx,_cy) is the maximum the bitmap size can't be exceded
|
|
*---------------------------------------------------------------------------*/
|
|
void CBitmapList::m_fn_vCreate(
|
|
BOOL _bSize /*= TRUE*/,
|
|
int _cx /*= 0*/,
|
|
int _cy /*= 0*/,
|
|
BOOL _bLoadOnlyOptimizedImages /*= FALSE*/,
|
|
BOOL _bUseSmallCopies /*= FALSE*/
|
|
)
|
|
{
|
|
if ( (m_oMaxSize.cx == -1) && (m_oMaxSize.cy == -1) ) //only first call is to be handled
|
|
{
|
|
#if defined(D_UseSmallBitmaps)
|
|
m_bUseSmallCopies =
|
|
#endif //D_UseSmallBitmaps
|
|
_bUseSmallCopies; //prevent compiler warning in case the argument is not used
|
|
|
|
m_bLoadOnlyOptimizedImages = _bLoadOnlyOptimizedImages;
|
|
m_bVariableSize = _bSize;
|
|
|
|
if (m_bVariableSize)
|
|
{
|
|
if ( (_cx == 0) || (_cy == 0) )
|
|
_cx = _cy = 0;
|
|
}
|
|
else
|
|
{
|
|
if (_cx < 8) _cx = 8;
|
|
if (_cy < 8) _cy = 8;
|
|
}
|
|
|
|
m_oMaxSize.cx = _cx;
|
|
m_oMaxSize.cy = _cy;
|
|
|
|
if ( m_bLoadOnlyOptimizedImages )
|
|
m_hBadTexturesLogFile = fopen("BadTextures.log", "wt");
|
|
}
|
|
else
|
|
AfxMessageBox("Warning : CBitmapList created more than once");
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : return number of bitmap in list, warning some element could
|
|
* have been erased so number returned isn't always right
|
|
*---------------------------------------------------------------------------*/
|
|
long CBitmapList::m_fn_lGetCount( void )
|
|
{
|
|
return m_oItemList.GetCount();
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : check out if a bitmap is already loaded or not
|
|
*---------------------------------------------------------------------------*/
|
|
int CBitmapList::m_fn_iFindBitmapByName( CString csName )
|
|
{
|
|
int iPos = 0;
|
|
POSITION pos = m_oItemList.GetHeadPosition();
|
|
tdstBitmapItem *p_stItem;
|
|
|
|
while (pos)
|
|
{
|
|
p_stItem = m_oItemList.GetNext( pos );
|
|
if (!p_stItem->m_bDeleted)
|
|
if (csName.CompareNoCase(p_stItem->m_csName) == 0)
|
|
return iPos;
|
|
iPos ++;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Decription : get index of a bitmap
|
|
*---------------------------------------------------------------------------*/
|
|
int CBitmapList::m_fn_iGetBitmapIndex( char *szBitmapName )
|
|
{
|
|
return m_fn_iFindBitmapByName( szBitmapName );
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : return size of bitmap given by it's name
|
|
*---------------------------------------------------------------------------*/
|
|
BOOL CBitmapList::m_fn_bGetBitmapSize( CString csFileName, CSize *sz)
|
|
{
|
|
FILE *hFile;
|
|
BITMAPFILEHEADER bf;
|
|
BITMAPINFOHEADER bi;
|
|
|
|
CString csExtension = strrchr(LPCTSTR(csFileName), '.');
|
|
|
|
if ( (hFile = fopen( csFileName, "rb")) == NULL)
|
|
return FALSE;
|
|
|
|
if ( !csExtension.CompareNoCase(".tga") )
|
|
{
|
|
unsigned char a18_ucTgaHeader[18];
|
|
//read TGA header
|
|
if ( fread(a18_ucTgaHeader, 18, 1, hFile) != 1 )
|
|
{
|
|
fclose(hFile);
|
|
return FALSE;
|
|
}
|
|
//get image width and height
|
|
bi.biWidth = (a18_ucTgaHeader[13]<<8) + a18_ucTgaHeader[12];
|
|
bi.biHeight = (a18_ucTgaHeader[15]<<8) + a18_ucTgaHeader[14];
|
|
}
|
|
else if ( !csExtension.CompareNoCase(".bmp") )
|
|
{
|
|
if (sizeof(bf) != fread( &bf, 1, sizeof(bf), hFile ))
|
|
{
|
|
fclose(hFile);
|
|
return FALSE;
|
|
}
|
|
if (bf.bfType != 0x4d42 /*BM*/)
|
|
{
|
|
fclose(hFile);
|
|
return FALSE;
|
|
}
|
|
if (sizeof(bi) != fread( &bi, 1, sizeof(bi), hFile ))
|
|
{
|
|
fclose(hFile);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
sz->cx = bi.biWidth;
|
|
sz->cy = bi.biHeight;
|
|
fclose(hFile);
|
|
return TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : return max size to englobe all bitmaps in list
|
|
*---------------------------------------------------------------------------*/
|
|
void CBitmapList::m_fn_vGetBoundBox( int& _cx, int& _cy)
|
|
{
|
|
POSITION pos = m_oItemList.GetHeadPosition();
|
|
tdstBitmapItem *p_stItem;
|
|
BITMAP stBitmap;
|
|
|
|
// init max
|
|
_cx = _cy = 0;
|
|
// for all bitmap in list
|
|
while (pos)
|
|
{
|
|
p_stItem = m_oItemList.GetNext( pos );
|
|
if (!p_stItem->m_bDeleted)
|
|
{
|
|
GetObject( p_stItem->m_hBitmap, sizeof(BITMAP), &stBitmap );
|
|
if ( _cx < stBitmap.bmWidth) _cx = stBitmap.bmWidth;
|
|
if ( _cy < stBitmap.bmHeight) _cy = stBitmap.bmHeight;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : add a bitmap in list, return -1 if it fails
|
|
* the size of bitmap depends on the creation parameters and on
|
|
* the _cx & _cy parameters
|
|
* If m_bVariableSize is false, we load bitmap with a size of m_oMaxSize
|
|
* else if _cx = 0 || _cy = 0 we load the bitmap with real size
|
|
* else with size (_cx,_cy)
|
|
*---------------------------------------------------------------------------*/
|
|
int CBitmapList::m_fn_iAdd(
|
|
CString _csName, int _cx /*= 0*/, int _cy /*= 0*/,
|
|
BOOL _bSmallCopyIfRelevant /*= TRUE*/, BOOL _bOverrideOptimizedImages /*= FALSE*/
|
|
)
|
|
{
|
|
_bSmallCopyIfRelevant; //prevent compiler warnings in case the argument is not used
|
|
//verify the CBitmapList creation
|
|
m_fn_vIsCreated();
|
|
|
|
//create the directory in case it does not exist
|
|
#if defined(D_UseSmallBitmaps)
|
|
CString csNameOfSmallVersion;
|
|
if ( m_bUseSmallCopies && _bSmallCopyIfRelevant )
|
|
{
|
|
char szFullName[_MAX_PATH], szDrive[_MAX_DRIVE], szPath[_MAX_DIR], szName[_MAX_FNAME], szExt[_MAX_EXT];
|
|
//insert a subdirectory in the name of the image to compute the full name of the small file
|
|
strcpy(szFullName, LPCTSTR(_csName));
|
|
_splitpath(szFullName, szDrive, szPath, szName, szExt);
|
|
strcat(szPath, "Small\\");
|
|
_makepath(szFullName, szDrive, szPath, NULL, NULL);
|
|
CreateDirectory(szFullName, NULL);
|
|
_makepath(szFullName, szDrive, szPath, szName, szExt);
|
|
//we will always generate a BMP file, so modify the name and add the extension
|
|
char *pszExtDot = strrchr(szFullName, '.');
|
|
if ( pszExtDot )
|
|
{
|
|
*pszExtDot = '_';
|
|
strcat(szFullName, ".bmp");
|
|
}
|
|
csNameOfSmallVersion = szFullName;
|
|
}
|
|
else
|
|
csNameOfSmallVersion = _csName;
|
|
#endif //D_UseSmallBitmaps
|
|
|
|
int iPos = m_fn_iFindBitmapByName(_csName);
|
|
// bitmap is already loaded
|
|
if (iPos != -1)
|
|
return iPos;
|
|
|
|
if ( !m_bVariableSize )
|
|
{
|
|
_cx = m_oMaxSize.cx;
|
|
_cy = m_oMaxSize.cy;
|
|
}
|
|
else
|
|
{
|
|
CSize oBMSize;
|
|
if ( (_cx == 0) || (_cy == 0))
|
|
{ //if one value is equal to zero set the twice to zero
|
|
_cx = _cy = 0;
|
|
}
|
|
// check if ther's a maximum size
|
|
if ( m_oMaxSize.cx )
|
|
{
|
|
if
|
|
( //try to read the size of one of the files containing the image to load
|
|
#if defined(D_UseSmallBitmaps)
|
|
( (m_bUseSmallCopies && _bSmallCopyIfRelevant) && !m_fn_bGetBitmapSize(csNameOfSmallVersion, &oBMSize) )
|
|
||
|
|
#endif //D_UseSmallBitmaps
|
|
( !m_fn_bGetBitmapSize(_csName, &oBMSize) )
|
|
)
|
|
return -1;
|
|
|
|
if ( (oBMSize.cx > m_oMaxSize.cx) || (oBMSize.cy > m_oMaxSize.cy))
|
|
{ // image is to large, reduce size and keep ratio
|
|
float fx = (float) oBMSize.cx / m_oMaxSize.cx;
|
|
float fy = (float) oBMSize.cy / m_oMaxSize.cy;
|
|
if (fx > fy)
|
|
{
|
|
_cx = m_oMaxSize.cx;
|
|
_cy = (int) (oBMSize.cy / fx);
|
|
}
|
|
else
|
|
{
|
|
_cy = m_oMaxSize.cy;
|
|
_cx = (int) (oBMSize.cx / fy);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// load bitmap
|
|
HBITMAP hBitmap;
|
|
#if defined(D_UseSmallBitmaps)
|
|
if ( m_bUseSmallCopies && _bSmallCopyIfRelevant )
|
|
{
|
|
//try to load the small one
|
|
hBitmap = (HBITMAP) m_hLoadImage(csNameOfSmallVersion, _cx, _cy, _bOverrideOptimizedImages);
|
|
if ( !hBitmap ) //try to load the original one and to save a small version
|
|
hBitmap = (HBITMAP) m_hLoadImage(_csName, _cx, _cy, csNameOfSmallVersion, _bOverrideOptimizedImages);
|
|
}
|
|
else //try only with the original version here
|
|
#endif //D_UseSmallBitmaps
|
|
hBitmap = (HBITMAP) m_hLoadImage(_csName, _cx, _cy, "", _bOverrideOptimizedImages);
|
|
|
|
if ( !hBitmap )
|
|
return -1;
|
|
|
|
// search for the place where to put new item
|
|
int iPlace;
|
|
tdstBitmapItem *p_stItem;
|
|
if ( (iPlace = m_fn_iGetFreeIndex()) == -1)
|
|
p_stItem = new tdstBitmapItem();
|
|
else
|
|
{
|
|
POSITION xPos = m_oItemList.FindIndex(iPlace);
|
|
p_stItem = m_oItemList.GetAt(xPos);
|
|
}
|
|
|
|
// set item members
|
|
p_stItem->m_csName = _csName;
|
|
p_stItem->m_hBitmap = hBitmap;
|
|
p_stItem->m_bDeleted = FALSE;
|
|
|
|
// put item in list in the good place
|
|
if (iPlace == -1)
|
|
{
|
|
m_oItemList.AddTail(p_stItem);
|
|
return (m_oItemList.GetCount() - 1);
|
|
}
|
|
else
|
|
return iPlace;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : reload a bitmap
|
|
*---------------------------------------------------------------------------*/
|
|
void CBitmapList::m_fn_vReload( CString _csBitmapName )
|
|
{
|
|
POSITION pos = m_oItemList.GetHeadPosition();
|
|
tdstBitmapItem *p_stItem;
|
|
|
|
while (pos)
|
|
{
|
|
p_stItem = m_oItemList.GetNext( pos );
|
|
if (!p_stItem->m_bDeleted)
|
|
if (_csBitmapName.CompareNoCase(p_stItem->m_csName) == 0)
|
|
{
|
|
int cx, cy;
|
|
BITMAP stBitmap;
|
|
CBitmap *p_oBitmap = CBitmap::FromHandle( p_stItem->m_hBitmap );
|
|
|
|
p_oBitmap->GetBitmap( &stBitmap );
|
|
cx = stBitmap.bmWidth;
|
|
cy = stBitmap.bmHeight;
|
|
|
|
DeleteObject( p_stItem->m_hBitmap );
|
|
|
|
p_stItem->m_hBitmap = (HBITMAP) m_hLoadImage(_csBitmapName, cx, cy, "", FALSE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : get long associated with a bitmap
|
|
*---------------------------------------------------------------------------*/
|
|
long CBitmapList::m_fn_lGetBitmapLong( int iImage )
|
|
{
|
|
POSITION pos;
|
|
|
|
if ( (iImage>=0) && (pos = m_oItemList.FindIndex( iImage )) != NULL)
|
|
{
|
|
tdstBitmapItem *p_stItem = m_oItemList.GetAt( pos );
|
|
return p_stItem->lData;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : set long associated with a bitmap
|
|
*---------------------------------------------------------------------------*/
|
|
void CBitmapList::m_fn_vSetBitmapLong( int iImage, long lLong )
|
|
{
|
|
POSITION pos;
|
|
|
|
if (iImage < 0)
|
|
return;
|
|
|
|
if ((pos = m_oItemList.FindIndex( iImage )) != NULL)
|
|
{
|
|
tdstBitmapItem *p_stItem = m_oItemList.GetAt( pos );
|
|
p_stItem->lData = lLong;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : set long associated with a bitmap
|
|
*---------------------------------------------------------------------------*/
|
|
int CBitmapList::m_fn_iGetBitmapIndexByLong( long lValue )
|
|
{
|
|
int iPos = 0;
|
|
POSITION pos = m_oItemList.GetHeadPosition();
|
|
tdstBitmapItem *p_stItem;
|
|
|
|
while (pos)
|
|
{
|
|
p_stItem = m_oItemList.GetNext( pos );
|
|
|
|
if ( (!p_stItem->m_bDeleted) && (p_stItem->lData == lValue) )
|
|
return iPos;
|
|
iPos ++;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : get handle of bitmap
|
|
*---------------------------------------------------------------------------*/
|
|
HBITMAP CBitmapList::m_fn_hGetBitmap( int iImage )
|
|
{
|
|
POSITION pos;
|
|
|
|
if ( (iImage>=0) && (pos = m_oItemList.FindIndex( iImage )) != NULL)
|
|
{
|
|
tdstBitmapItem *p_stItem = m_oItemList.GetAt( pos );
|
|
if (!p_stItem->m_bDeleted)
|
|
return p_stItem->m_hBitmap;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : get bitmap name
|
|
*---------------------------------------------------------------------------*/
|
|
CString CBitmapList::m_fn_csGetBitmapName( int iImage )
|
|
{
|
|
POSITION pos;
|
|
|
|
if ( (iImage>=0) && (pos = m_oItemList.FindIndex( iImage )) != NULL)
|
|
{
|
|
tdstBitmapItem *p_stItem = m_oItemList.GetAt( pos );
|
|
if (!p_stItem->m_bDeleted)
|
|
return p_stItem->m_csName;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : delete a bitmap
|
|
*---------------------------------------------------------------------------*/
|
|
void CBitmapList::m_fn_vDelete( int iBitmap )
|
|
{
|
|
POSITION pos;
|
|
|
|
if (iBitmap < 0)
|
|
return;
|
|
|
|
if ((pos= m_oItemList.FindIndex( iBitmap )) != NULL)
|
|
{
|
|
tdstBitmapItem *p_stItem = m_oItemList.GetAt( pos );
|
|
if (!p_stItem->m_bDeleted)
|
|
{
|
|
DeleteObject( p_stItem->m_hBitmap );
|
|
p_stItem->m_bDeleted = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : delete all bitmaps
|
|
*---------------------------------------------------------------------------*/
|
|
void CBitmapList::m_fn_vDeleteAll( void )
|
|
{
|
|
POSITION pos = m_oItemList.GetHeadPosition();
|
|
tdstBitmapItem *p_stItem;
|
|
|
|
// delete all item in list
|
|
while (pos)
|
|
{
|
|
p_stItem = m_oItemList.GetNext( pos );
|
|
if (!p_stItem->m_bDeleted)
|
|
{
|
|
DeleteObject( p_stItem->m_hBitmap );
|
|
}
|
|
delete p_stItem;
|
|
}
|
|
// delete all pointer in list
|
|
m_oItemList.RemoveAll();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : delete all bitmaps
|
|
*---------------------------------------------------------------------------*/
|
|
int CBitmapList::m_fn_iGetFreeIndex( void )
|
|
{
|
|
int iIndex = 0;
|
|
POSITION pos = m_oItemList.GetHeadPosition();
|
|
tdstBitmapItem *p_stItem;
|
|
|
|
//search for a free item
|
|
while (pos)
|
|
{
|
|
p_stItem = m_oItemList.GetNext( pos );
|
|
if (p_stItem->m_bDeleted)
|
|
return iIndex;
|
|
iIndex ++;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : draw an image in the given CDC, at the given point
|
|
*---------------------------------------------------------------------------*/
|
|
void CBitmapList::m_fn_vDraw( CDC* pDC, int iImage, POINT pt, RECT *pClipBox, char cAlignX /*= BA_LEFT*/, char cAlignY /*= BA_TOP*/ )
|
|
{
|
|
//verify the CBitmapList creation
|
|
m_fn_vIsCreated();
|
|
// get position of image in list
|
|
BITMAP stBitmap;
|
|
SIZE sz;
|
|
POSITION pos;
|
|
|
|
if (iImage < 0)
|
|
return;
|
|
|
|
if ((pos = m_oItemList.FindIndex( iImage )) != NULL)
|
|
{
|
|
// get bitmap item
|
|
tdstBitmapItem *p_stItem = m_oItemList.GetAt( pos );
|
|
if (p_stItem->m_bDeleted)
|
|
return;
|
|
// get bitmap information
|
|
GetObject( p_stItem->m_hBitmap, sizeof(BITMAP), &stBitmap );
|
|
// compute x coordinates and width
|
|
switch (cAlignX)
|
|
{
|
|
case BA_LEFT:
|
|
sz.cx = pClipBox->right - pt.x;
|
|
if (sz.cx > stBitmap.bmWidth)
|
|
sz.cx = stBitmap.bmWidth;
|
|
break;
|
|
case BA_RIGHT:
|
|
sz.cx = pt.x - pClipBox->left;
|
|
pt.x -= sz.cx;
|
|
if (sz.cx < stBitmap.bmWidth)
|
|
pt.x = 0;
|
|
else
|
|
sz.cx = stBitmap.bmWidth;
|
|
break;
|
|
case BA_CENTER:
|
|
sz.cx = ( ((pt.x - pClipBox->left) < (pClipBox->right - pt.x)) ?
|
|
(pt.x - pClipBox->left) : (pClipBox->right - pt.x) ) * 2;
|
|
if (sz.cx > stBitmap.bmWidth)
|
|
sz.cx = stBitmap.bmWidth;
|
|
pt.x -= sz.cx / 2;
|
|
break;
|
|
}
|
|
|
|
// compute y coordinates and width
|
|
switch (cAlignY)
|
|
{
|
|
case BA_TOP:
|
|
sz.cy = pClipBox->bottom - pt.y;
|
|
if (sz.cy > stBitmap.bmHeight)
|
|
sz.cy = stBitmap.bmHeight;
|
|
break;
|
|
case BA_BOTTOM:
|
|
sz.cy = pt.y - pClipBox->top;
|
|
if (sz.cy > stBitmap.bmHeight)
|
|
sz.cy = stBitmap.bmHeight;
|
|
pt.y -= sz.cy;
|
|
break;
|
|
case BA_CENTER:
|
|
sz.cy = ( ((pt.y - pClipBox->top) < (pClipBox->bottom- pt.y)) ?
|
|
(pt.y - pClipBox->top) : (pClipBox->bottom - pt.y) ) * 2;
|
|
if (sz.cy > stBitmap.bmHeight)
|
|
sz.cy = stBitmap.bmHeight;
|
|
pt.y -= sz.cy / 2;
|
|
break;
|
|
}
|
|
|
|
pDC->DrawState( pt, sz, p_stItem->m_hBitmap, DSS_NORMAL );
|
|
}
|
|
}
|
|
|
|
/*=============================================================================
|
|
*
|
|
* implementation of CThreeSortedList
|
|
*
|
|
=============================================================================*/
|
|
|
|
/******************************************************************************
|
|
* INTERNAL FUNCTION
|
|
*****************************************************************************/
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : macro that return a boolean that indicate if index is valid or not
|
|
*---------------------------------------------------------------------------*/
|
|
#define M_bIsIndexValid(wIndex) ((wIndex >= 0) && (wIndex < m_lNumberOfElements))
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : function that verify validity off index and give true index
|
|
* switch given order
|
|
*---------------------------------------------------------------------------*/
|
|
short CThreeSortedList::m_fn_wGetIndexSwitchOrder( short wIndex, char cOrder )
|
|
{
|
|
// verify index
|
|
if ( !M_bIsIndexValid(wIndex) )
|
|
return TSL_cItemNotFound;
|
|
// transform index switch order
|
|
switch (cOrder)
|
|
{
|
|
case C_cAlphaOrder:
|
|
return wIndex;
|
|
|
|
case C_cCommonOrder:
|
|
return (short) m_d_lCommonIndex[wIndex];
|
|
|
|
case C_cEditedOrder:
|
|
return (short) m_d_lEditedIndex[wIndex];
|
|
}
|
|
// no correspondant order, return TSL_cItemNotFound
|
|
return TSL_cItemNotFound;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : find index in order list of an item index in alpha order
|
|
*---------------------------------------------------------------------------*/
|
|
short CThreeSortedList::m_fn_wAlphaToAnotherOrder(short wIndex, char cOrder)
|
|
{
|
|
long *m_p_lOrder;
|
|
short wResult;
|
|
// verify index
|
|
if ( !M_bIsIndexValid(wIndex) )
|
|
return TSL_cItemNotFound;
|
|
|
|
switch (cOrder)
|
|
{
|
|
case C_cAlphaOrder:
|
|
return wIndex;
|
|
|
|
case C_cCommonOrder:
|
|
m_p_lOrder = m_d_lCommonIndex;
|
|
break;
|
|
|
|
case C_cEditedOrder:
|
|
m_p_lOrder = m_d_lEditedIndex;
|
|
break;
|
|
|
|
default:
|
|
return TSL_cItemNotFound;
|
|
}
|
|
//find in the reorder array which element references the alpha index we specified
|
|
for ( wResult = 0; wResult < m_lNumberOfElements; wResult ++ )
|
|
if ( m_p_lOrder[wResult] == wIndex )
|
|
return wResult;
|
|
|
|
return TSL_cItemNotFound;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* CONSTRUCTOR / DESTRUCTOR
|
|
*****************************************************************************/
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : Constructor
|
|
*---------------------------------------------------------------------------*/
|
|
CThreeSortedList::CThreeSortedList()
|
|
{
|
|
// initialised item list to null, zero items
|
|
//m_d_stItem = NULL;
|
|
m_lMaxElements = 0;
|
|
m_lNumberOfElements = 0;
|
|
m_d_lCommonIndex = NULL;
|
|
m_d_lEditedIndex = NULL;
|
|
m_p_oBitmapList = NULL;
|
|
m_lSelectedItem = TSL_cItemNotFound;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : destructor
|
|
*---------------------------------------------------------------------------*/
|
|
CThreeSortedList::~CThreeSortedList()
|
|
{
|
|
m_fn_bDeleteAllItems();
|
|
m_p_oBitmapList = NULL;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : Add an item
|
|
*---------------------------------------------------------------------------*/
|
|
int CThreeSortedList::m_fn_iAddItem(CString csName, short wImage, long lContent, char cSortType /* = C_cAlphaOrder*/)
|
|
{
|
|
// allocate memory if necessary
|
|
if ( m_lMaxElements == m_lNumberOfElements )
|
|
{
|
|
// if no more place in list, increase max of elemenst
|
|
m_lMaxElements += 20;
|
|
// reallocate pointers
|
|
m_oArrayOfTSLItem . SetSize(m_lMaxElements);
|
|
m_d_lCommonIndex = (long *) realloc(m_d_lCommonIndex, sizeof(long) * m_lMaxElements);
|
|
m_d_lEditedIndex = (long *) realloc(m_d_lEditedIndex, sizeof(long) * m_lMaxElements);
|
|
}
|
|
|
|
// find place where to put new item in alphabetic order
|
|
long lTopIndex, lBottomIndex, lInsertIndex;
|
|
lTopIndex = 0; //up is first in alpha order
|
|
lBottomIndex = m_lNumberOfElements; //bottom is last
|
|
if ( lBottomIndex == lTopIndex )
|
|
lInsertIndex = 0;
|
|
else
|
|
do
|
|
{
|
|
lInsertIndex = (lTopIndex + lBottomIndex) / 2;
|
|
short wCompareResult = csName.CompareNoCase(m_oArrayOfTSLItem[lInsertIndex]->m_csName);
|
|
if ( wCompareResult < 0 ) //string is in the upper part of the array
|
|
lBottomIndex = lInsertIndex; //move the bottom of the range up
|
|
else if ( wCompareResult > 0 ) //string is in the lower part of the array
|
|
lTopIndex = lInsertIndex + 1; //move the top of the range down, leaving the tested element out of the range
|
|
else //the string is equal to the middle's string
|
|
lTopIndex = lBottomIndex = lInsertIndex; //insert it here
|
|
} while ( lTopIndex != lBottomIndex );
|
|
lInsertIndex = lTopIndex;
|
|
//create the new item and fill it
|
|
tdstTSLItem *p_stTSLItem = new tdstTSLItem;
|
|
p_stTSLItem->m_csName = csName;
|
|
p_stTSLItem->m_wImage = wImage;
|
|
p_stTSLItem->m_lContent = lContent;
|
|
|
|
// insert item at the found position
|
|
m_oArrayOfTSLItem.InsertAt(lInsertIndex, p_stTSLItem);
|
|
// if item is inserted before the selected item, shift selection number
|
|
if ( (m_lSelectedItem != TSL_cItemNotFound) && m_lSelectedItem >= lInsertIndex )
|
|
m_lSelectedItem ++;
|
|
|
|
//shift all items in the reorder lists that are after the one referenced
|
|
for
|
|
(
|
|
long lIndex = 0, *p_lCommon = m_d_lCommonIndex, *p_lEdited = m_d_lEditedIndex;
|
|
lIndex < m_lNumberOfElements;
|
|
lIndex ++, p_lCommon ++, p_lEdited ++
|
|
)
|
|
{
|
|
if ( *p_lCommon >= lInsertIndex )
|
|
(*p_lCommon) ++;
|
|
if ( *p_lEdited >= lInsertIndex )
|
|
(*p_lEdited) ++;
|
|
}
|
|
// add item in order list
|
|
m_d_lCommonIndex[m_lNumberOfElements] = lInsertIndex;
|
|
m_d_lEditedIndex[m_lNumberOfElements] = lInsertIndex;
|
|
|
|
// increase number of elements
|
|
m_lNumberOfElements ++;
|
|
|
|
return m_fn_wAlphaToAnotherOrder((short) lInsertIndex, cSortType);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : change name for the given item, this operation change
|
|
* order in alphabetical list.
|
|
* return the new index in list of the item
|
|
*---------------------------------------------------------------------------*/
|
|
int CThreeSortedList::m_fn_iSetItemName( long lIndex, char *szName, char cSortType /*= C_cAlphaOrder */)
|
|
{
|
|
short wImage;
|
|
long lContent;
|
|
BOOL bIsTheSelectedItem;
|
|
|
|
// recuperate true index, return if invalid index
|
|
if ( (lIndex = m_fn_wGetIndexSwitchOrder((short) lIndex, cSortType )) == TSL_cItemNotFound )
|
|
return TSL_cItemNotFound;
|
|
|
|
// check if item is the selected one
|
|
bIsTheSelectedItem = (lIndex == m_lSelectedItem);
|
|
|
|
// save item data
|
|
wImage = m_oArrayOfTSLItem[lIndex]->m_wImage;
|
|
lContent = m_oArrayOfTSLItem[lIndex]->m_lContent;
|
|
|
|
// delete item
|
|
m_fn_bDeleteItem(lIndex);
|
|
// add an item with old image and content but new name
|
|
lIndex = m_fn_iAddItem(szName, wImage, lContent);
|
|
|
|
// set the new number for selected item if the item was the selected one
|
|
if (bIsTheSelectedItem)
|
|
m_lSelectedItem = lIndex;
|
|
|
|
// return item index in the given order
|
|
return m_fn_wAlphaToAnotherOrder((short) lIndex, cSortType);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : change image index for the given item
|
|
*---------------------------------------------------------------------------*/
|
|
void CThreeSortedList::m_fn_vSetItemImage( long lIndex, short _wImage, char cSortType /*= C_cAlphaOrder */)
|
|
{
|
|
// recuperate true index
|
|
if ( (lIndex = m_fn_wGetIndexSwitchOrder((short) lIndex, cSortType )) == TSL_cItemNotFound )
|
|
return;
|
|
// set item image
|
|
m_oArrayOfTSLItem[lIndex]->m_wImage = _wImage;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : change pointer on content
|
|
*---------------------------------------------------------------------------*/
|
|
void CThreeSortedList::m_fn_vSetItemContent( long lIndex, long lContent, char cSortType /*= C_cAlphaOrder */)
|
|
{
|
|
// recuperate true index
|
|
if ( (lIndex = m_fn_wGetIndexSwitchOrder((short) lIndex, cSortType )) == TSL_cItemNotFound )
|
|
return;
|
|
// set content of item
|
|
m_oArrayOfTSLItem[lIndex]->m_lContent = lContent;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : delete an item
|
|
*---------------------------------------------------------------------------*/
|
|
BOOL CThreeSortedList::m_fn_bDeleteItem( long lIndex, char cSortType /*= C_cAlphaOrder */ )
|
|
{
|
|
// recuperate true index
|
|
if ( (lIndex = m_fn_wGetIndexSwitchOrder((short) lIndex, cSortType )) == TSL_cItemNotFound)
|
|
return FALSE;
|
|
|
|
// update selected item
|
|
if (lIndex == m_lSelectedItem)
|
|
m_lSelectedItem = TSL_cItemNotFound;
|
|
else if (m_lSelectedItem > lIndex)
|
|
m_lSelectedItem --;
|
|
|
|
//destroy the item, and remove it from the array
|
|
delete (m_oArrayOfTSLItem[lIndex]);
|
|
m_oArrayOfTSLItem.RemoveAt(lIndex);
|
|
|
|
|
|
//shift all items in the reorder lists that are after the one referenced
|
|
for
|
|
(
|
|
long lOrder = 0, *p_lCommon = m_d_lCommonIndex, *p_lEdited = m_d_lEditedIndex;
|
|
lOrder < m_lNumberOfElements;
|
|
lOrder ++, p_lCommon ++, p_lEdited ++
|
|
)
|
|
{
|
|
if ( *p_lCommon >= lIndex )
|
|
(*p_lCommon) --;
|
|
if ( *p_lEdited >= lIndex )
|
|
(*p_lEdited) --;
|
|
}
|
|
|
|
// decrease number of item
|
|
m_lNumberOfElements --;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : delete all items
|
|
*---------------------------------------------------------------------------*/
|
|
BOOL CThreeSortedList::m_fn_bDeleteAllItems(void)
|
|
{
|
|
for( int i = 0; i< m_lNumberOfElements ; i ++ )
|
|
delete m_oArrayOfTSLItem[i];
|
|
if ( m_d_lCommonIndex )
|
|
{
|
|
free(m_d_lCommonIndex);
|
|
m_d_lCommonIndex = NULL;
|
|
}
|
|
if ( m_d_lEditedIndex )
|
|
{
|
|
free(m_d_lEditedIndex);
|
|
m_d_lEditedIndex = NULL;
|
|
}
|
|
m_lSelectedItem = TSL_cItemNotFound;
|
|
m_lMaxElements = 0;
|
|
m_lNumberOfElements = 0;
|
|
m_oArrayOfTSLItem.SetSize(0);
|
|
return TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : swaps two items
|
|
*---------------------------------------------------------------------------*/
|
|
void CThreeSortedList::m_fn_vSwapEditedItems( long lIndex1, long lIndex2 )
|
|
{
|
|
long lTemp;
|
|
if ( M_bIsIndexValid(lIndex1) && M_bIsIndexValid(lIndex2) )
|
|
{
|
|
lTemp = m_d_lEditedIndex[lIndex1];
|
|
m_d_lEditedIndex[lIndex1] = m_d_lEditedIndex[lIndex2];
|
|
m_d_lEditedIndex[lIndex2] = lTemp;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* description : deplace one item in a order list
|
|
*---------------------------------------------------------------------------*/
|
|
void CThreeSortedList::m_fn_vDeplaceOrderedItem(long lIndex, long lNewIndex, char cSortType)
|
|
{
|
|
long *m_p_lOrder;
|
|
// get order list, or exit if order is invalid (unknown or alpha order)
|
|
switch (cSortType)
|
|
{
|
|
case C_cCommonOrder:
|
|
m_p_lOrder = m_d_lCommonIndex;
|
|
break;
|
|
|
|
case C_cEditedOrder:
|
|
m_p_lOrder = m_d_lEditedIndex;
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
// verify data (the two index)
|
|
if (M_bIsIndexValid(lIndex) && M_bIsIndexValid(lNewIndex) && (lIndex != lNewIndex) )
|
|
{
|
|
// save index item to deplace
|
|
long lTemp = m_p_lOrder[lIndex];
|
|
// move other index to make a place
|
|
if (lIndex > lNewIndex)
|
|
memmove(m_p_lOrder + lNewIndex + 1, m_p_lOrder + lNewIndex, sizeof(long) * (lIndex - lNewIndex));
|
|
else // lIndex < lNewIndex
|
|
memmove(m_p_lOrder + lIndex, m_p_lOrder + lIndex + 1, sizeof(long) * (lNewIndex - lIndex));
|
|
// set item in the new place
|
|
m_p_lOrder[lNewIndex] = lTemp;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* description : set the more common item
|
|
*---------------------------------------------------------------------------*/
|
|
void CThreeSortedList::m_fn_vSetCommonItem(long lIndex)
|
|
{
|
|
m_fn_vDeplaceOrderedItem(lIndex, 0, C_cCommonOrder);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : get an item
|
|
*---------------------------------------------------------------------------*/
|
|
tdstTSLItem *CThreeSortedList::m_fn_p_stGetItem(long lIndex, char cSortType /*= C_cAlphaOrder */)
|
|
{
|
|
// recuperate true index
|
|
if ( (lIndex = m_fn_wGetIndexSwitchOrder((short) lIndex, cSortType )) == TSL_cItemNotFound)
|
|
return NULL;
|
|
|
|
//return &m_d_stItem[lIndex];
|
|
return m_oArrayOfTSLItem[lIndex];
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : get name of an item
|
|
*---------------------------------------------------------------------------*/
|
|
CString CThreeSortedList::m_fn_csGetName( long lIndex, char cSortType /*= C_cAlphaOrder */)
|
|
{
|
|
// get item
|
|
tdstTSLItem *p_stItem = m_fn_p_stGetItem(lIndex, cSortType);
|
|
// return item string if item was found
|
|
if (p_stItem)
|
|
return ( p_stItem->m_csName );
|
|
return "";
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : get image of an item
|
|
*---------------------------------------------------------------------------*/
|
|
short CThreeSortedList::m_fn_wGetImage(long lIndex, char cSortType /*= C_cAlphaOrder */)
|
|
{
|
|
// get item
|
|
tdstTSLItem *p_stItem = m_fn_p_stGetItem(lIndex, cSortType);
|
|
// return image index of item
|
|
if (p_stItem)
|
|
return ( p_stItem->m_wImage);
|
|
return -1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : get content of an item
|
|
*---------------------------------------------------------------------------*/
|
|
long CThreeSortedList::m_fn_lGetContent( long lIndex, char cSortType /*= C_cAlphaOrder */ )
|
|
{
|
|
// get item
|
|
tdstTSLItem *p_stItem = m_fn_p_stGetItem( lIndex, cSortType );
|
|
// return item content if item was found
|
|
if (p_stItem)
|
|
return ( p_stItem->m_lContent );
|
|
return NULL;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : find an item that correspond to the given item pointer
|
|
*---------------------------------------------------------------------------*/
|
|
long CThreeSortedList::m_fn_lFindItem(long lStartAt, tdstTSLItem *p_stItem, char cSortType /*= C_cAlphaOrder */)
|
|
{
|
|
if ( lStartAt < 0 )
|
|
lStartAt = 0;
|
|
|
|
for (short wIndex = (short) lStartAt; wIndex < (short) m_lNumberOfElements; wIndex ++)
|
|
{
|
|
//if ( &m_d_stItem[ m_fn_wGetIndexSwitchOrder(wIndex, cSortType) ] == p_stItem )
|
|
if ( (m_oArrayOfTSLItem[m_fn_wGetIndexSwitchOrder(wIndex, cSortType)]) == p_stItem )
|
|
return wIndex;
|
|
}
|
|
return TSL_cItemNotFound;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : find item with same name as the given one
|
|
*---------------------------------------------------------------------------*/
|
|
long CThreeSortedList::m_fn_lFindName(long lStartAt, CString csName, char cSortType /*= C_cAlphaOrder */)
|
|
{
|
|
if ( lStartAt < 0 )
|
|
lStartAt = 0;
|
|
|
|
for (short wIndex = (short) lStartAt; wIndex < (short) m_lNumberOfElements; wIndex ++)
|
|
{
|
|
if (csName == (m_oArrayOfTSLItem[m_fn_wGetIndexSwitchOrder(wIndex, cSortType)])->m_csName )
|
|
return wIndex;
|
|
}
|
|
return TSL_cItemNotFound;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : find item with the same image as the given one
|
|
*---------------------------------------------------------------------------*/
|
|
long CThreeSortedList::m_fn_lFindImage( long lStartAt, short wImage, char cSortType /*= C_cAlphaOrder */)
|
|
{
|
|
if ( lStartAt < 0 )
|
|
lStartAt = 0;
|
|
|
|
for (short wIndex = (short) lStartAt; wIndex < (short) m_lNumberOfElements; wIndex ++)
|
|
{
|
|
if (m_oArrayOfTSLItem[m_fn_wGetIndexSwitchOrder(wIndex, cSortType)]->m_wImage == wImage )
|
|
return wIndex;
|
|
}
|
|
return TSL_cItemNotFound;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : find item with the same content as the given one
|
|
*---------------------------------------------------------------------------*/
|
|
long CThreeSortedList::m_fn_lFindContent( long lStartAt, long lContent, char cSortType /*= C_cAlphaOrder*/ )
|
|
{
|
|
if ( lStartAt < 0 )
|
|
lStartAt = 0;
|
|
|
|
for (short wIndex = (short) lStartAt; wIndex < (short) m_lNumberOfElements; wIndex ++)
|
|
{
|
|
if (m_oArrayOfTSLItem[m_fn_wGetIndexSwitchOrder(wIndex, cSortType)]->m_lContent == lContent )
|
|
return wIndex;
|
|
}
|
|
return TSL_cItemNotFound;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : set selected item
|
|
*---------------------------------------------------------------------------*/
|
|
void CThreeSortedList::m_fn_vSetSelectedItem( long lIndex, char cSortType )
|
|
{
|
|
m_lSelectedItem = m_fn_wGetIndexSwitchOrder( (short) lIndex, cSortType );
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : return selected item
|
|
*---------------------------------------------------------------------------*/
|
|
long CThreeSortedList::m_fn_lGetSelectedItem( char cSortType )
|
|
{
|
|
return m_fn_wAlphaToAnotherOrder( (short) m_lSelectedItem, cSortType );
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : is the given item the selected one ?
|
|
*---------------------------------------------------------------------------*/
|
|
BOOL CThreeSortedList::m_fn_bIsItemSelected( long lIndex, char cSortType )
|
|
{
|
|
return (m_lSelectedItem == m_fn_wGetIndexSwitchOrder( (short) lIndex, cSortType ));
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : unselect item
|
|
*---------------------------------------------------------------------------*/
|
|
void CThreeSortedList::m_fn_vUnselectItem( void )
|
|
{
|
|
m_lSelectedItem = TSL_cItemNotFound;
|
|
}
|
|
|
|
|
|
/*=============================================================================
|
|
* implementation of class C3ListFrame
|
|
=============================================================================*/
|
|
IMPLEMENT_DYNCREATE(C3ListFrame, FRMBase)
|
|
BEGIN_MESSAGE_MAP(C3ListFrame, FRMBase)
|
|
ON_WM_CREATE()
|
|
ON_WM_CLOSE()
|
|
END_MESSAGE_MAP()
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : constructor
|
|
*---------------------------------------------------------------------------*/
|
|
C3ListFrame::C3ListFrame(void)
|
|
{
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : create the window
|
|
*---------------------------------------------------------------------------*/
|
|
int C3ListFrame::OnCreate(LPCREATESTRUCT _p_stCreateStruct)
|
|
{
|
|
// Create frame
|
|
if (CFrameWnd::OnCreate(_p_stCreateStruct) == -1)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : close the window
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListFrame::OnClose(void)
|
|
{
|
|
CFrameWnd::OnClose();
|
|
}
|
|
|
|
|
|
/*=============================================================================
|
|
* implementation off C3ListView class
|
|
=============================================================================*/
|
|
IMPLEMENT_DYNCREATE(C3ListView, CScrollView)
|
|
BEGIN_MESSAGE_MAP(C3ListView, CScrollView)
|
|
ON_WM_PAINT()
|
|
ON_WM_CREATE()
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_MESSAGE( WM_DRAGDROP_END, OnDragDropEnd )
|
|
ON_MESSAGE( WM_DRAGDROP_MOVE, OnDragDropMove )
|
|
ON_MESSAGE( WM_DRAGDROP_SCROLL, OnDragDropScroll )
|
|
ON_WM_WINDOWPOSCHANGED()
|
|
ON_WM_KEYDOWN()
|
|
END_MESSAGE_MAP()
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : constructor
|
|
*---------------------------------------------------------------------------*/
|
|
C3ListView::C3ListView( void ): CScrollView(), CThreeSortedList()
|
|
{
|
|
// initialise member variables
|
|
// box to display bitmap alone
|
|
m_a_oDisplayBox[C_cDisplayBitmap].cx = 30;
|
|
m_a_oDisplayBox[C_cDisplayBitmap].cy = 30;
|
|
// box to display text & bitmap
|
|
m_a_oDisplayBox[C_cDisplayBitmapAndText].cx = 80;
|
|
m_a_oDisplayBox[C_cDisplayBitmapAndText].cy = 50;
|
|
// box to display text alone
|
|
m_a_oDisplayBox[C_cDisplayText].cx = 80;
|
|
m_a_oDisplayBox[C_cDisplayText].cy = 20;
|
|
// display grid
|
|
m_bGrid = TRUE;
|
|
// current order
|
|
m_cCurrentOrder = C_cAlphaOrder;
|
|
// current deplacement type
|
|
m_cMoveType = C_cSwap;
|
|
// init menu flags
|
|
m_lMenuFlags = TLVM_lMenu | TLVM_lGrid | TLVM_lOrder | TLVM_lDisplay;
|
|
|
|
//Init Drag&Drop data
|
|
m_oDDCase.fn_vSetDataType( 1234 );
|
|
m_oDDCase.fn_vSetEditorName("coucou");
|
|
|
|
m_wCaseWithTips = -1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : set Drag and drop data and editor type
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::m_fn_vSetDDTypeAndEditor( UINT uiDataType, char *szEditorName )
|
|
{
|
|
m_oDDCase.fn_vSetDataType( uiDataType );
|
|
m_oDDCase.fn_vSetEditorName( szEditorName );
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : get case index following point in client window rect
|
|
*---------------------------------------------------------------------------*/
|
|
short C3ListView::m_fn_wGetCaseFromClientPoint( int x, int y)
|
|
{
|
|
short wLine, wCase, wCol;
|
|
// compute coordinates in View
|
|
x += GetScrollPosition().x;
|
|
y += GetScrollPosition().y;
|
|
// compute col, line and case were point is
|
|
wCol = (short) (x / m_oCurrentBox.cx);
|
|
wLine = (short) (y / m_oCurrentBox.cy);
|
|
wCase = wLine * m_wNumberOfCols + wCol;
|
|
// check if case is valid
|
|
if ( (wCol >= m_wNumberOfCols) || (wLine >= m_wNumberOfLines) || (wCase >= m_fn_lGetCount()) )
|
|
return TSL_cItemNotFound;
|
|
return wCase;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : get case rectangle of a case given by it's index
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::m_fn_vGetCaseRect( short wIndex, RECT *pRect )
|
|
{
|
|
// get line and column of case
|
|
short wLine = wIndex / m_wNumberOfCols;
|
|
short wCol = wIndex - wLine * m_wNumberOfCols;
|
|
// compute rect
|
|
pRect->left = wCol * m_oCurrentBox.cx;
|
|
pRect->right = pRect->left + m_oCurrentBox.cx;
|
|
pRect->top = wLine * m_oCurrentBox.cy;
|
|
pRect->bottom = pRect->top + m_oCurrentBox.cy;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : Hide the tips for the m_wCaseWithTips case
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::m_fn_vHideTips( )
|
|
{
|
|
CDC *p_oDC;
|
|
long lWidth;
|
|
long lHeight;
|
|
|
|
if (m_wCaseWithTips == -1)
|
|
return;
|
|
|
|
m_wCaseWithTips = -1;
|
|
|
|
//p_oDC = GetWindowDC();
|
|
p_oDC = GetDesktopWindow()->GetWindowDC();
|
|
|
|
lWidth = m_stTipsRect.right - m_stTipsRect.left + 1;
|
|
lHeight = m_stTipsRect.bottom - m_stTipsRect.top + 1;
|
|
|
|
p_oDC->BitBlt( m_stTipsRect.left, m_stTipsRect.top, lWidth, lHeight, &m_oCDCTip, 0, 0, SRCCOPY );
|
|
|
|
ReleaseDC( p_oDC );
|
|
m_oCDCTip.DeleteDC();
|
|
m_oBitmapTip.DeleteObject();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : show the tips for the m_wCaseWithTips case
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::m_fn_vShowTips( void )
|
|
{
|
|
CDC *p_oDC;
|
|
CFont xFnt, *xFntPrev = NULL;
|
|
PLOGFONT plf = (PLOGFONT) LocalAlloc(LPTR, sizeof(LOGFONT));
|
|
CString csString;
|
|
CSize oTextSize;
|
|
RECT stWinRect;
|
|
|
|
if (m_wCaseWithTips == -1)
|
|
return;
|
|
|
|
p_oDC = GetDesktopWindow()->GetWindowDC();
|
|
|
|
/*
|
|
* compute tip rect
|
|
*/
|
|
m_fn_vGetCaseRect( m_wCaseWithTips, &m_stTipsRect );
|
|
m_stTipsRect.left -= GetScrollPosition().x;
|
|
m_stTipsRect.right -= GetScrollPosition().x;
|
|
m_stTipsRect.top -= GetScrollPosition().y;
|
|
m_stTipsRect.bottom -= GetScrollPosition().y;
|
|
|
|
ClientToScreen( &m_stTipsRect );
|
|
|
|
lstrcpy(plf->lfFaceName, "Arial Narrow");
|
|
plf->lfWeight = FW_NORMAL;
|
|
plf->lfHeight = 16;
|
|
plf->lfEscapement = 0;
|
|
if (xFnt.CreateFontIndirect(plf))
|
|
xFntPrev = p_oDC->SelectObject( &xFnt );
|
|
|
|
csString = m_fn_csGetName( m_wCaseWithTips, m_cCurrentOrder );
|
|
|
|
oTextSize = p_oDC->GetTextExtent( csString, csString.GetLength() );
|
|
oTextSize.cx += 4;
|
|
oTextSize.cy += 4;
|
|
|
|
m_stTipsRect.left = (m_stTipsRect.left + m_stTipsRect.right - 1 - oTextSize.cx) / 2;
|
|
m_stTipsRect.right = m_stTipsRect.left + oTextSize.cx;
|
|
|
|
if (m_cDisplayType == C_cDisplayBitmap)
|
|
{
|
|
m_stTipsRect.top = m_stTipsRect.bottom;
|
|
m_stTipsRect.bottom += oTextSize.cy;
|
|
}
|
|
else
|
|
m_stTipsRect.top = m_stTipsRect.bottom - oTextSize.cy;
|
|
|
|
GetWindowRect( &stWinRect );
|
|
if (m_stTipsRect.top > stWinRect.bottom)
|
|
{
|
|
m_stTipsRect.top = stWinRect.bottom;
|
|
m_stTipsRect.bottom = m_stTipsRect.top + oTextSize.cy;
|
|
}
|
|
|
|
/*
|
|
* save tip background
|
|
*/
|
|
m_oCDCTip.CreateCompatibleDC( p_oDC );
|
|
m_oBitmapTip.CreateCompatibleBitmap( p_oDC, oTextSize.cx , oTextSize.cy );
|
|
m_oCDCTip.SelectObject( &m_oBitmapTip );
|
|
|
|
m_oCDCTip.BitBlt( 0, 0, oTextSize.cx, oTextSize.cy, p_oDC, m_stTipsRect.left, m_stTipsRect.top, SRCCOPY);
|
|
|
|
/*
|
|
* draw tip
|
|
*/
|
|
p_oDC->Rectangle( &m_stTipsRect );
|
|
//p_oDC->FillSolidRect( &m_stTipsRect, RGB(255,255,255) );
|
|
|
|
// draw string
|
|
p_oDC->SetBkMode( TRANSPARENT );
|
|
p_oDC->SetTextAlign( TA_CENTER | TA_BOTTOM );
|
|
p_oDC->TextOut((m_stTipsRect.left + m_stTipsRect.right + 1) / 2, m_stTipsRect.bottom - 2, csString, csString.GetLength());
|
|
|
|
|
|
if ( xFntPrev )
|
|
{
|
|
p_oDC->SelectObject(xFntPrev);
|
|
xFnt.DeleteObject();
|
|
}
|
|
//do not forget to free the memory for the font
|
|
LocalFree(plf);
|
|
|
|
|
|
ReleaseDC( p_oDC);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : make the view scroll so that the item is visible, if necessary
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::m_vScrollToMakeItemVisible(short _wItem)
|
|
{
|
|
Invalidate();
|
|
if ( _wItem == TSL_cItemNotFound )
|
|
return;
|
|
|
|
CRect oItemRect, oClientRect;
|
|
GetClientRect(oClientRect);
|
|
oClientRect.OffsetRect(GetScrollPosition());
|
|
m_fn_vGetCaseRect(_wItem, &oItemRect);
|
|
//if the item's rectangle is not entirely visible in the client
|
|
if ( (oClientRect & oItemRect) != oItemRect )
|
|
{
|
|
//make the view scroll so that the center of the item's rectangle is
|
|
//vertically moved to the middle of the client area
|
|
POINT stPoint;
|
|
stPoint.x = GetScrollPosition().x;
|
|
stPoint.y = oItemRect.CenterPoint().y - oClientRect.Height() / 2;
|
|
ScrollToPosition(stPoint);
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : change display type
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::m_fn_vChangeDisplayType( char _cDisplayType )
|
|
{
|
|
// check display type
|
|
if
|
|
(
|
|
(((unsigned char) _cDisplayType) >= C_cNumberOfDisplayTypes)
|
|
//|| (m_cDisplayType == _cDisplayType)
|
|
)
|
|
|
|
return;
|
|
|
|
// change current case size
|
|
m_oCurrentBox = m_a_oDisplayBox[ _cDisplayType ];
|
|
// change display type varialbe
|
|
m_cDisplayType = _cDisplayType;
|
|
|
|
// calculate new size of CScrollView
|
|
RECT rect;
|
|
CSize sz;
|
|
|
|
//GetParent()->GetClientRect( &rect );
|
|
GetWindowRect( &rect );
|
|
|
|
// compute number of columns that fit in view rect
|
|
//m_wNumberOfCols = rect.right / m_oCurrentCase.cx;
|
|
m_wNumberOfCols = (short) ((rect.right - rect.left - 14) / m_oCurrentBox.cx);
|
|
if (m_wNumberOfCols <= 0) m_wNumberOfCols = 1;
|
|
// compute number of lines
|
|
m_wNumberOfLines = (m_fn_lGetCount() + m_wNumberOfCols - 1) / m_wNumberOfCols;
|
|
// compute size of view
|
|
sz.cx = m_wNumberOfCols * m_oCurrentBox.cx;
|
|
sz.cy = m_wNumberOfLines * m_oCurrentBox.cy;
|
|
if (sz.cy == 0) sz.cy = 1;
|
|
SetScrollSizes( MM_TEXT, sz );
|
|
// redraw view
|
|
m_vScrollToMakeItemVisible((short) m_fn_lGetSelectedItem(m_cCurrentOrder));
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : change order
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::m_fn_vChangeOrder( char _cOrder )
|
|
{
|
|
if (_cOrder == m_cCurrentOrder)
|
|
return;
|
|
// resize view if necessary
|
|
/*
|
|
if ( _cOrder == C_cEditedOrder || m_cCurrentOrder == C_cEditedOrder)
|
|
{
|
|
CWnd *pFrameBase = GetParent();
|
|
while ( !pFrameBase->IsKindOf( RUNTIME_CLASS( FRMBase ) ) )
|
|
{
|
|
pFrameBase = pFrameBase->GetParent();
|
|
}
|
|
((FRMBase *) pFrameBase)->m_fn_vSwapFullScreen();
|
|
}
|
|
*/
|
|
// change order variable
|
|
m_cCurrentOrder = _cOrder;
|
|
|
|
// redraw view
|
|
m_vScrollToMakeItemVisible((short) m_fn_lGetSelectedItem(m_cCurrentOrder));
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : change size of a display box
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::m_fn_vSetBox( char _cDisplayType, int _iWidth, int _iHeight)
|
|
{
|
|
// check display type
|
|
if (((unsigned char) _cDisplayType) >= C_cNumberOfDisplayTypes)
|
|
return;
|
|
// set new size
|
|
m_a_oDisplayBox[ _cDisplayType ].cx = _iWidth;
|
|
m_a_oDisplayBox[ _cDisplayType ].cy = _iHeight;
|
|
|
|
if (_cDisplayType == m_cDisplayType )
|
|
m_fn_vChangeDisplayType( _cDisplayType ); // to refresh display
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : enable a menu flag
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::m_fn_vEnableMenuItem( long lFlags )
|
|
{
|
|
m_lMenuFlags |= lFlags;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : disable some menu flag
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::m_fn_vDisableMenuItem( long lFlags )
|
|
{
|
|
m_lMenuFlags &= ~lFlags;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : handle function fo WM_CREATE message
|
|
*---------------------------------------------------------------------------*/
|
|
int C3ListView::OnCreate( LPCREATESTRUCT _p_stCreateStruct )
|
|
{
|
|
if ( CScrollView::OnCreate(_p_stCreateStruct) == -1 )
|
|
return -1;
|
|
|
|
m_fn_vChangeDisplayType( C_cDisplayText );
|
|
|
|
m_oDDCase.fn_vSetOwner( this );
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : handle function fo WM_RBUTTONDOWN message
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::OnRButtonDown(UINT nFlags, CPoint pt )
|
|
{
|
|
if ((m_lMenuFlags & TLVM_lMenu) == 0)
|
|
return;
|
|
|
|
// hide tips if one
|
|
m_fn_vHideTips();
|
|
|
|
ClientToScreen( &pt );
|
|
// create popup menu
|
|
CMenu oMenu;
|
|
oMenu.CreatePopupMenu();
|
|
// entries to change display type
|
|
if (m_lMenuFlags & TLVM_lBitmapAndText)
|
|
oMenu.AppendMenu( MF_STRING | ((m_cDisplayType == C_cDisplayBitmapAndText)?MF_CHECKED:MF_UNCHECKED), 1, "Bitmap and Text");
|
|
if (m_lMenuFlags & TLVM_lText)
|
|
oMenu.AppendMenu( MF_STRING | ((m_cDisplayType == C_cDisplayText)?MF_CHECKED:MF_UNCHECKED), 2, "Only Text");
|
|
if (m_lMenuFlags & TLVM_lBitmap)
|
|
oMenu.AppendMenu( MF_STRING | ((m_cDisplayType == C_cDisplayBitmap)?MF_CHECKED:MF_UNCHECKED), 3, "Only Bitmap");
|
|
|
|
if ((m_lMenuFlags & TLVM_lDisplay ) && (m_lMenuFlags & (TLVM_lGrid | TLVM_lOrder)) )
|
|
oMenu.AppendMenu( MF_SEPARATOR );
|
|
// entry to swap grid on/off
|
|
if (m_lMenuFlags & TLVM_lGrid)
|
|
{
|
|
oMenu.AppendMenu( (m_bGrid ? MF_CHECKED : MF_UNCHECKED) | MF_STRING, 4, "Grid");
|
|
if (m_lMenuFlags & TLVM_lOrder)
|
|
oMenu.AppendMenu( MF_SEPARATOR );
|
|
}
|
|
// entries to change display order
|
|
if (m_lMenuFlags & TLVM_lAlphabetic)
|
|
oMenu.AppendMenu( MF_STRING | ((m_cCurrentOrder == C_cAlphaOrder)?MF_CHECKED:MF_UNCHECKED), 5, "Alphabetic");
|
|
if (m_lMenuFlags & TLVM_lCommon)
|
|
oMenu.AppendMenu( MF_STRING | ((m_cCurrentOrder == C_cCommonOrder)?MF_CHECKED:MF_UNCHECKED), 6, "Common");
|
|
if (m_lMenuFlags & TLVM_lEdited)
|
|
oMenu.AppendMenu( MF_STRING | ((m_cCurrentOrder == C_cEditedOrder)?MF_CHECKED:MF_UNCHECKED), 7, "Edited");
|
|
// entry to change move type (if in edited order)
|
|
if (m_cCurrentOrder == C_cEditedOrder)
|
|
{
|
|
oMenu.AppendMenu( MF_SEPARATOR );
|
|
if (m_cMoveType == C_cSwap)
|
|
oMenu.AppendMenu( MF_STRING, 8, "Deplace");
|
|
else
|
|
oMenu.AppendMenu( MF_STRING, 8, "Swap");
|
|
}
|
|
|
|
//enable derived instances to add their own entries in the menu, starting with this value
|
|
_InitPopupMenu(oMenu, 9);
|
|
|
|
// register the popup menu for the tutorial module
|
|
TUT_M_vGetTutDll ();
|
|
TUT_M_vRegisterMenu (this -> m_hWnd , oMenu . m_hMenu , pt. x , pt . y);
|
|
|
|
// display & track popup menu
|
|
oMenu.TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);
|
|
// destroy menus
|
|
oMenu.DestroyMenu();
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : on select item
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::OnSelectItem( short wCase )
|
|
{
|
|
RECT rect;
|
|
CDC *pDC = GetDC();
|
|
CPoint oPt = GetScrollPosition();
|
|
|
|
long lOldSelected = m_fn_lGetSelectedItem(m_cCurrentOrder);
|
|
|
|
m_fn_vSetSelectedItem( wCase, m_cCurrentOrder );
|
|
if (wCase != lOldSelected )
|
|
{
|
|
if ( lOldSelected != TSL_cItemNotFound )
|
|
{
|
|
m_fn_vGetCaseRect((short) lOldSelected, &rect );
|
|
rect.top -= oPt.y;
|
|
rect.bottom -= oPt.y;
|
|
rect.left -= oPt.x;
|
|
rect.right -= oPt.x;
|
|
pDC->InvertRect( &rect );
|
|
}
|
|
if ( wCase != TSL_cItemNotFound )
|
|
{
|
|
m_fn_vGetCaseRect(wCase, &rect );
|
|
rect.top -= oPt.y;
|
|
rect.bottom -= oPt.y;
|
|
rect.left -= oPt.x;
|
|
rect.right -= oPt.x;
|
|
pDC->InvertRect( &rect );
|
|
}
|
|
}
|
|
ReleaseDC( pDC );
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : handle function fo WM_LBUTTONDOWN message
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::OnLButtonDown(UINT nFlags, CPoint pt )
|
|
{
|
|
short wCase;
|
|
RECT rect;
|
|
|
|
// hide tips if one
|
|
m_fn_vHideTips();
|
|
|
|
// compute case under mouse
|
|
wCase = m_fn_wGetCaseFromClientPoint( pt.x, pt.y);
|
|
OnSelectItem( wCase );
|
|
|
|
if ( wCase == TSL_cItemNotFound )
|
|
return;
|
|
|
|
// get case rectangle
|
|
m_fn_vGetCaseRect( wCase, &rect );
|
|
|
|
// Set Drag & drop data
|
|
m_oDDCase.fn_vSetData( (void *) wCase );
|
|
|
|
// Add reference on window that accept Drop message
|
|
// can drag and drop in this window only if we are in Edited order
|
|
if (m_cCurrentOrder == C_cEditedOrder )
|
|
{
|
|
RECT windowRect;
|
|
RECT scrollRect;
|
|
int iWidth;
|
|
|
|
GetWindowRect( &windowRect );
|
|
if ((iWidth = (windowRect.bottom - windowRect.top) / 2) > 10)
|
|
iWidth = 10;
|
|
|
|
scrollRect.right = windowRect.right;
|
|
scrollRect.left = windowRect.left;
|
|
|
|
scrollRect.top = windowRect.top;
|
|
scrollRect.bottom = scrollRect.top + iWidth;
|
|
DD_vRegisterRect( &scrollRect, this->GetSafeHwnd() );
|
|
|
|
scrollRect.bottom = windowRect.bottom;
|
|
scrollRect.top = scrollRect.bottom - iWidth;
|
|
DD_vRegisterRect( &scrollRect, this->GetSafeHwnd() );
|
|
DD_vSetScrollTime( 100 );
|
|
DD_eAddReference( this->GetSafeHwnd(), m_oDDCase.fn_p_szGetEditorName(), m_oDDCase.fn_uiGetDataType(), FALSE );
|
|
}
|
|
|
|
// launch drag & drop operation
|
|
HWND hWnd = DD_hBeginDragDrop( &rect, &m_oDDCase );
|
|
|
|
// if item was dragged to another window, set first in the common order
|
|
if ( (hWnd != this->GetSafeHwnd()) && (hWnd != NULL) )
|
|
{
|
|
m_fn_vSetCommonItem( wCase );
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : handle function fo WM_MOUSEMOVE message
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::OnMouseMove( UINT nFlags, CPoint pt)
|
|
{
|
|
short wCase;
|
|
|
|
|
|
if (GetCapture() == this)
|
|
{
|
|
RECT stRect;
|
|
GetClientRect( &stRect );
|
|
if( (pt.x < 0) || (pt.y < 0) || (pt.x>stRect.right) || (pt.y>stRect.bottom) )
|
|
{
|
|
m_fn_vHideTips();
|
|
ReleaseCapture();
|
|
return;
|
|
}
|
|
if ((GetForegroundWindow() != this) || (GetActiveWindow() != this))
|
|
{
|
|
m_fn_vHideTips();
|
|
ReleaseCapture();
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetCapture();
|
|
}
|
|
|
|
wCase = m_fn_wGetCaseFromClientPoint( pt.x, pt.y);
|
|
|
|
if (wCase == TSL_cItemNotFound)
|
|
{
|
|
if (m_wCaseWithTips != -1 )
|
|
m_fn_vHideTips();
|
|
}
|
|
else
|
|
{
|
|
if (m_wCaseWithTips != wCase)
|
|
{
|
|
if (m_wCaseWithTips != -1)
|
|
m_fn_vHideTips();
|
|
m_wCaseWithTips = wCase;
|
|
m_fn_vShowTips();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : handle function fo WM_DRAGDROP_SCROLL message
|
|
*---------------------------------------------------------------------------*/
|
|
LONG C3ListView::OnDragDropScroll( UINT wParam , LONG lParam)
|
|
{
|
|
RECT windowRect;
|
|
RECT *scrollRect = (RECT *) lParam;
|
|
POINT pos = GetScrollPosition();
|
|
|
|
GetWindowRect( &windowRect );
|
|
|
|
if (scrollRect->top == windowRect.top)
|
|
pos.y -= 20;
|
|
else
|
|
pos.y += 20;
|
|
|
|
ScrollToPosition( pos );
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : handle function fo WM_DRAGDROP_END message
|
|
*---------------------------------------------------------------------------*/
|
|
LONG C3ListView::OnDragDropEnd( UINT wParam , LONG lParam)
|
|
{
|
|
short wCase;
|
|
|
|
// check current order
|
|
if (m_cCurrentOrder != C_cEditedOrder)
|
|
return 0;
|
|
|
|
DD_Object *p_oDDObject = (DD_Object *) lParam;
|
|
|
|
// check if data come from this
|
|
if (p_oDDObject != &m_oDDCase )
|
|
return 0;
|
|
|
|
// compute case where object were dropped
|
|
ScreenToClient( &p_oDDObject->m_stMousePos );
|
|
wCase = m_fn_wGetCaseFromClientPoint( p_oDDObject->m_stMousePos.x, p_oDDObject->m_stMousePos.y );
|
|
if ( wCase == TSL_cItemNotFound )
|
|
return 0;
|
|
|
|
// swap item or deplace item switch move type
|
|
if (m_cMoveType == C_cSwap)
|
|
m_fn_vSwapEditedItems( (short) p_oDDObject->fn_p_vGetData(), wCase );
|
|
else
|
|
m_fn_vDeplaceOrderedItem( (short) p_oDDObject->fn_p_vGetData(), wCase, C_cEditedOrder );
|
|
|
|
//redraw list;
|
|
Invalidate();
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : handle function fo WM_DRAGDROP_MOVE message
|
|
*---------------------------------------------------------------------------*/
|
|
LONG C3ListView::OnDragDropMove( UINT wParam , LONG lParam)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : pretranslate message
|
|
*---------------------------------------------------------------------------*/
|
|
BOOL C3ListView::PreTranslateMessage( MSG* pMsg )
|
|
{
|
|
if (pMsg->message == WM_KEYDOWN)
|
|
{
|
|
if (pMsg->wParam != VK_TAB)
|
|
{
|
|
OnKeyDown( pMsg->wParam, LOWORD(pMsg->lParam),HIWORD(pMsg->lParam) );
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : handle function fo WM_COMMAND message
|
|
*---------------------------------------------------------------------------*/
|
|
BOOL C3ListView::OnCommand( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
if (HIWORD(wParam) == 0) // command from a menu
|
|
{
|
|
switch (LOWORD(wParam) ) //ID of menu item
|
|
{
|
|
case 1:
|
|
m_fn_vChangeDisplayType( C_cDisplayBitmapAndText );
|
|
break;
|
|
case 2:
|
|
m_fn_vChangeDisplayType( C_cDisplayText );
|
|
break;
|
|
case 3:
|
|
m_fn_vChangeDisplayType( C_cDisplayBitmap );
|
|
break;
|
|
case 4:
|
|
m_bGrid = !m_bGrid;
|
|
Invalidate();
|
|
break;
|
|
case 5:
|
|
m_fn_vChangeOrder( C_cAlphaOrder );
|
|
break;
|
|
case 6:
|
|
m_fn_vChangeOrder( C_cCommonOrder );
|
|
break;
|
|
case 7:
|
|
m_fn_vChangeOrder( C_cEditedOrder );
|
|
break;
|
|
case 8:
|
|
m_cMoveType = 1 - m_cMoveType;
|
|
break;
|
|
//handle entries added by derived instances
|
|
default:
|
|
_OnCommand(LOWORD(wParam));
|
|
break;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : handle function fo WM_KEYDOW message
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
|
|
{
|
|
short wDeltaY = 0;
|
|
switch (nChar)
|
|
{
|
|
case VK_DOWN: wDeltaY = 10; break;
|
|
case VK_UP: wDeltaY = -10; break;
|
|
case VK_PRIOR: wDeltaY = -50; break;
|
|
case VK_NEXT: wDeltaY = 50; break;
|
|
case VK_HOME: wDeltaY = (short) -GetScrollPosition().y; break;
|
|
case VK_END: wDeltaY = (short) (GetTotalSize().cy - GetScrollPosition().y); break;
|
|
}
|
|
if (wDeltaY)
|
|
{
|
|
CPoint pt = GetScrollPosition();
|
|
pt.y += wDeltaY;
|
|
ScrollToPosition( (POINT) pt );
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : handle function for WM_WINDOWPOSCHANGED message
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::OnWindowPosChanged( WINDOWPOS* lpwndpos )
|
|
{
|
|
m_fn_vChangeDisplayType(m_cDisplayType);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : handle function for drawing message
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::OnDraw(CDC *pDC )
|
|
{
|
|
RECT rect;
|
|
pDC->GetClipBox( &rect);
|
|
|
|
m_fn_vHideTips();
|
|
|
|
// calculate first case and last case in drawing zone
|
|
short wFirstLine = (short) (rect.top / m_oCurrentBox.cy);
|
|
short wLastLine = (short) (rect.bottom / m_oCurrentBox.cy);
|
|
if (wFirstLine < 0) wFirstLine = 0;
|
|
if (wLastLine >= m_wNumberOfLines) wLastLine = m_wNumberOfLines - 1;
|
|
|
|
rect.top = wFirstLine * m_oCurrentBox.cy;
|
|
rect.bottom = rect.top + m_oCurrentBox.cy;
|
|
|
|
short wCase = wFirstLine * m_wNumberOfCols;
|
|
|
|
for ( short wLine = wFirstLine; wLine <= wLastLine ; wLine ++)
|
|
{
|
|
rect.left = 0;
|
|
rect.right = m_oCurrentBox.cx;
|
|
for ( short wCol = 0; wCol < m_wNumberOfCols && wCase < m_fn_lGetCount(); wCase ++, wCol ++ )
|
|
{
|
|
m_fn_vOverriddenDrawItem( wCase, pDC, &rect );
|
|
rect.left += m_oCurrentBox.cx;
|
|
rect.right += m_oCurrentBox.cx;
|
|
}
|
|
rect.top += m_oCurrentBox.cy;
|
|
rect.bottom += m_oCurrentBox.cy;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : draw an item
|
|
*---------------------------------------------------------------------------*/
|
|
void C3ListView::m_fn_vDrawItem(short wItem, CDC *pDC, RECT *p_Rect, short _wSpecialImage /*= TSL_cItemNotFound */ )
|
|
{
|
|
RECT stBitmapRect;
|
|
CPoint oImageOrg;
|
|
short wImage = m_fn_wGetImage(wItem, m_cCurrentOrder);
|
|
|
|
// draw rectangle
|
|
if ( m_bGrid )
|
|
pDC->Rectangle(p_Rect);
|
|
else
|
|
pDC->FillRect(p_Rect, pDC->GetCurrentBrush());
|
|
|
|
switch ( m_cDisplayType )
|
|
{
|
|
case C_cDisplayBitmap:
|
|
if ( (m_fn_p_oGetBitmapList()) && (wImage != TSL_cItemNotFound) )
|
|
{
|
|
stBitmapRect.top = p_Rect->top - GetScrollPosition().y + 1;
|
|
stBitmapRect.bottom = p_Rect->bottom - GetScrollPosition().y - 1;
|
|
stBitmapRect.left = p_Rect->left - GetScrollPosition().x + 1;
|
|
stBitmapRect.right = p_Rect->right - GetScrollPosition().x - 1;
|
|
|
|
oImageOrg.x = (stBitmapRect.left + stBitmapRect.right) / 2;
|
|
oImageOrg.y = (stBitmapRect.top + stBitmapRect.bottom) / 2;
|
|
|
|
m_fn_p_oGetBitmapList()->m_fn_vDraw( pDC, wImage, oImageOrg, &stBitmapRect, BA_CENTER , BA_CENTER );
|
|
}
|
|
break;
|
|
|
|
case C_cDisplayBitmapAndText:
|
|
// display bitmap
|
|
if ( (m_fn_p_oGetBitmapList()) && (wImage != TSL_cItemNotFound) )
|
|
{
|
|
stBitmapRect.top = p_Rect->top - GetScrollPosition().y + 2;
|
|
stBitmapRect.bottom = p_Rect->bottom - GetScrollPosition().y - 20;
|
|
stBitmapRect.left = p_Rect->left - GetScrollPosition().x + 1;
|
|
stBitmapRect.right = p_Rect->right - GetScrollPosition().x - 1;
|
|
|
|
oImageOrg.x = (stBitmapRect.left + stBitmapRect.right) / 2;
|
|
oImageOrg.y = stBitmapRect.top;
|
|
|
|
m_fn_p_oGetBitmapList()->m_fn_vDraw( pDC, wImage, oImageOrg, &stBitmapRect, BA_CENTER , BA_TOP );
|
|
}
|
|
// no break : draw bitmap too
|
|
|
|
case C_cDisplayText:
|
|
// compute max number char to show to stay in rect
|
|
{
|
|
CFont xFnt, *xFntPrev = NULL;
|
|
PLOGFONT plf = (PLOGFONT) LocalAlloc(LPTR, sizeof(LOGFONT));
|
|
|
|
lstrcpy(plf->lfFaceName, "Arial Narrow");
|
|
plf->lfWeight = (m_cDisplayType == C_cDisplayBitmapAndText || wImage == _wSpecialImage) ? FW_NORMAL : FW_BOLD;
|
|
plf->lfHeight = 16;
|
|
plf->lfEscapement = 0;
|
|
if (xFnt.CreateFontIndirect(plf))
|
|
xFntPrev = pDC->SelectObject( &xFnt );
|
|
|
|
CString csString = m_fn_csGetName( wItem, m_cCurrentOrder );
|
|
short wNbChar = csString.GetLength() + 1;
|
|
CSize oTextSize;
|
|
do
|
|
{
|
|
wNbChar --;
|
|
oTextSize = pDC->GetTextExtent( csString, wNbChar );
|
|
} while (oTextSize.cx > (p_Rect->right - p_Rect->left -2) );
|
|
// draw string
|
|
pDC->SetBkMode( TRANSPARENT );
|
|
pDC->SetTextAlign( TA_CENTER | TA_BOTTOM );
|
|
pDC->TextOut((p_Rect->left + p_Rect->right) / 2, p_Rect->bottom - 2, csString, wNbChar);
|
|
if ( xFntPrev )
|
|
{
|
|
pDC->SelectObject(xFntPrev);
|
|
xFnt.DeleteObject();
|
|
}
|
|
//do not forget to free the memory for the font
|
|
LocalFree(plf);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( m_fn_bIsItemSelected( wItem, m_cCurrentOrder) )
|
|
pDC->InvertRect( p_Rect );
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : add an item
|
|
*---------------------------------------------------------------------------*/
|
|
int C3ListView::m_fn_iAddItem( CString csName, short wImage , long lContent, char cSortType /* C_cAlphaOrder*/ )
|
|
{
|
|
int iResult = CThreeSortedList::m_fn_iAddItem( csName, wImage, lContent, cSortType );
|
|
m_fn_vChangeDisplayType( m_cDisplayType );
|
|
return iResult;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : delete an item
|
|
*---------------------------------------------------------------------------*/
|
|
BOOL C3ListView::m_fn_bDeleteItem( long lIndex, char cSortType /*= C_cAlphaOrder*/ )
|
|
{
|
|
BOOL bResult = CThreeSortedList::m_fn_bDeleteItem( lIndex, cSortType );
|
|
if (bResult)
|
|
m_fn_vChangeDisplayType( m_cDisplayType);
|
|
return bResult;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* Description : delete all items
|
|
*---------------------------------------------------------------------------*/
|
|
BOOL C3ListView::m_fn_bDeleteAllItems()
|
|
{
|
|
BOOL bResult = CThreeSortedList::m_fn_bDeleteAllItems();
|
|
if (bResult)
|
|
m_fn_vChangeDisplayType(m_cDisplayType);
|
|
return bResult;
|
|
}
|
|
|
|
|
|
#endif // ACTIVE_EDITOR
|