/*============================================================================= * * 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