382 lines
10 KiB
C++
382 lines
10 KiB
C++
|
|
||
|
#include "stdafx.h"
|
||
|
|
||
|
|
||
|
#include <direct.h>
|
||
|
|
||
|
#include <tchar.h>
|
||
|
#include "global.h"
|
||
|
|
||
|
#include "pbrush.h"
|
||
|
#include "pbrusdoc.h"
|
||
|
#include "pbrusfrm.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#undef THIS_FILE
|
||
|
static CHAR BASED_CODE THIS_FILE[] = __FILE__;
|
||
|
#endif // _DEBUG
|
||
|
|
||
|
#include "memtrace.h"
|
||
|
|
||
|
/***************************************************************************/
|
||
|
|
||
|
//
|
||
|
// This function returns a pointer to a monochrome GDI brush with
|
||
|
// alternating "black" and "white" pixels. This brush should NOT
|
||
|
// be deleted!
|
||
|
//
|
||
|
CBrush* GetHalftoneBrush()
|
||
|
{
|
||
|
static CBrush NEAR halftoneBrush;
|
||
|
|
||
|
if (halftoneBrush.m_hObject == NULL)
|
||
|
{
|
||
|
static WORD NEAR rgwHalftone [] =
|
||
|
{
|
||
|
0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555
|
||
|
};
|
||
|
|
||
|
CBitmap bitmap;
|
||
|
|
||
|
if (!bitmap.CreateBitmap(8, 8, 1, 1, rgwHalftone))
|
||
|
return NULL;
|
||
|
|
||
|
if (!halftoneBrush.CreatePatternBrush(&bitmap))
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return &halftoneBrush;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// The following code manages a cache of GDI brushes that correspond to
|
||
|
// the system defined colors. The cache is flushed when the user changes
|
||
|
// any of the system colors using the control panel. Using GetSysBrush()
|
||
|
// to get a system colored brush will be more efficient than creating the
|
||
|
// brush yourself.
|
||
|
//
|
||
|
void ResetSysBrushes()
|
||
|
{
|
||
|
//NOTE: we don't include our extensions to the "system" brushes, because
|
||
|
// often the brush handle is used as hbrBackground for a Window class!
|
||
|
for (UINT nBrush = 0; nBrush < nSysBrushes + nOurBrushes; nBrush++)
|
||
|
if (theApp.m_pbrSysColors[nBrush])
|
||
|
{
|
||
|
delete theApp.m_pbrSysColors[nBrush];
|
||
|
theApp.m_pbrSysColors[nBrush] = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
COLORREF MyGetSysColor(UINT nSysColor)
|
||
|
{
|
||
|
if (nSysColor < nSysBrushes)
|
||
|
return ::GetSysColor( nSysColor );
|
||
|
|
||
|
static COLORREF NEAR rgColors[nOurBrushes] =
|
||
|
{
|
||
|
CMP_RGB_HILITE, CMP_RGB_LTGRAY, CMP_RGB_DKGRAY, CMP_RGB_BLACK,
|
||
|
};
|
||
|
|
||
|
ASSERT((int)nSysColor - CMP_COLOR_HILITE >= 0);
|
||
|
ASSERT((int)nSysColor - CMP_COLOR_HILITE < nOurBrushes);
|
||
|
|
||
|
return rgColors[nSysColor - CMP_COLOR_HILITE];
|
||
|
}
|
||
|
|
||
|
CBrush* GetSysBrush(UINT nSysColor)
|
||
|
{
|
||
|
ASSERT(nSysColor < nSysBrushes + nOurBrushes);
|
||
|
|
||
|
if (! theApp.m_pbrSysColors[nSysColor])
|
||
|
{
|
||
|
COLORREF cr = MyGetSysColor(nSysColor);
|
||
|
|
||
|
theApp.m_pbrSysColors[nSysColor] = new CBrush;
|
||
|
|
||
|
if (theApp.m_pbrSysColors[nSysColor])
|
||
|
{
|
||
|
if (! theApp.m_pbrSysColors[nSysColor]->CreateSolidBrush( cr ))
|
||
|
{
|
||
|
TRACE( TEXT("GetSysBrush failed!\n") );
|
||
|
theApp.SetGdiEmergency();
|
||
|
|
||
|
delete theApp.m_pbrSysColors[nSysColor];
|
||
|
theApp.m_pbrSysColors[nSysColor] = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
theApp.SetMemoryEmergency();
|
||
|
}
|
||
|
|
||
|
return theApp.m_pbrSysColors[nSysColor];
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// PreTerminateList
|
||
|
// Helper function for deleting all objects in a list, and then
|
||
|
// truncating the list. Help stop leaks by using this, so your
|
||
|
// objects don't get left in memory.
|
||
|
//
|
||
|
|
||
|
void PreTerminateList( CObList* pList )
|
||
|
{
|
||
|
if (pList == NULL || pList->IsEmpty())
|
||
|
return;
|
||
|
|
||
|
while (! pList->IsEmpty())
|
||
|
{
|
||
|
CObject* pObj = pList->RemoveHead();
|
||
|
delete pObj;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
void MySplitPath (const TCHAR *szPath, TCHAR *szDrive, TCHAR *szDir, TCHAR *szName, TCHAR *szExt)
|
||
|
{
|
||
|
// Found this in tchar.h
|
||
|
_tsplitpath (szPath, szDrive, szDir, szName, szExt);
|
||
|
}
|
||
|
|
||
|
// Remove the drive and directory from a file name...
|
||
|
//
|
||
|
CString StripPath(const TCHAR* szFilePath)
|
||
|
{
|
||
|
TCHAR szName [_MAX_FNAME + _MAX_EXT];
|
||
|
TCHAR szExt [_MAX_EXT];
|
||
|
MySplitPath(szFilePath, NULL, NULL, szName, szExt);
|
||
|
lstrcat(szName, szExt);
|
||
|
return CString(szName);
|
||
|
}
|
||
|
|
||
|
// Remove the name part of a file path. Return just the drive and directory.
|
||
|
//
|
||
|
CString StripName(const TCHAR* szFilePath)
|
||
|
{
|
||
|
TCHAR szPath [_MAX_DRIVE + _MAX_DIR];
|
||
|
TCHAR szDir [_MAX_DIR];
|
||
|
MySplitPath(szFilePath, szPath, szDir, NULL, NULL);
|
||
|
lstrcat(szPath, szDir);
|
||
|
return CString(szPath);
|
||
|
}
|
||
|
|
||
|
// Remove the name part of a file path. Return just the drive and directory, and name.
|
||
|
//
|
||
|
CString StripExtension(const TCHAR* szFilePath)
|
||
|
{
|
||
|
TCHAR szPath [_MAX_DRIVE + _MAX_DIR + _MAX_FNAME];
|
||
|
TCHAR szDir [_MAX_DIR];
|
||
|
TCHAR szName [_MAX_FNAME];
|
||
|
MySplitPath(szFilePath, szPath, szDir, szName, NULL);
|
||
|
lstrcat(szPath, szDir);
|
||
|
lstrcat(szPath, szName);
|
||
|
return CString(szPath);
|
||
|
}
|
||
|
|
||
|
// Get the extension of a file path.
|
||
|
//
|
||
|
CString GetExtension(const TCHAR* szFilePath)
|
||
|
{
|
||
|
TCHAR szExt [_MAX_EXT];
|
||
|
MySplitPath(szFilePath, NULL, NULL, NULL, szExt);
|
||
|
return CString(szExt);
|
||
|
}
|
||
|
|
||
|
// Get the name of a file path.
|
||
|
//
|
||
|
CString GetName(const TCHAR* szFilePath)
|
||
|
{
|
||
|
TCHAR szName [_MAX_FNAME];
|
||
|
MySplitPath(szFilePath, NULL, NULL, szName, NULL);
|
||
|
return CString(szName);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Return the path to szFilePath relative to szDirectory. (E.g. if szFilePath
|
||
|
// is "C:\FOO\BAR\CDR.CAR" and szDirectory is "C:\FOO", then "BAR\CDR.CAR"
|
||
|
// is returned. This will never use '..'; if szFilePath is not in szDirectory
|
||
|
// or a sub-directory, then szFilePath is returned unchanged.
|
||
|
// If szDirectory is NULL, the current directory is used.
|
||
|
//
|
||
|
CString GetRelativeName(const TCHAR* szFilePath, const TCHAR* szDirectory /*= NULL*/)
|
||
|
{
|
||
|
CString strDir;
|
||
|
|
||
|
if ( szDirectory == NULL )
|
||
|
{
|
||
|
GetCurrentDirectory(_MAX_DIR, strDir.GetBuffer(_MAX_DIR) );
|
||
|
strDir.ReleaseBuffer();
|
||
|
strDir += (TCHAR)TEXT('\\');
|
||
|
szDirectory = strDir;
|
||
|
}
|
||
|
|
||
|
int cchDirectory = lstrlen(szDirectory);
|
||
|
if (_tcsnicmp(szFilePath, szDirectory, cchDirectory) == 0)
|
||
|
return CString(szFilePath + cchDirectory);
|
||
|
else if ( szFilePath[0] == szDirectory[0] &&
|
||
|
szFilePath[1] == TEXT(':') && szDirectory[1] == TEXT(':') ) // Remove drive if same.
|
||
|
return CString(szFilePath + 2);
|
||
|
|
||
|
return CString(szFilePath);
|
||
|
}
|
||
|
#if 0
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// Taken from windows system code. Contains intl support.
|
||
|
/* Returns: 0x00 if no matching char,
|
||
|
* 0x01 if menmonic char is matching,
|
||
|
* 0x80 if first char is matching
|
||
|
*/
|
||
|
|
||
|
#define CH_PREFIX TEXT('&')
|
||
|
|
||
|
int FindMnemChar(LPTSTR lpstr, TCHAR ch, BOOL fFirst, BOOL fPrefix)
|
||
|
|
||
|
{
|
||
|
register TCHAR chc;
|
||
|
register TCHAR chnext;
|
||
|
TCHAR chFirst;
|
||
|
|
||
|
while (*lpstr == TEXT(' '))
|
||
|
lpstr++;
|
||
|
|
||
|
ch = (TCHAR)(DWORD)CharLower((LPTSTR)(DWORD)(BYTE)ch);
|
||
|
chFirst = (TCHAR)(DWORD)CharLower((LPTSTR)(DWORD)(BYTE)(*lpstr));
|
||
|
|
||
|
#ifndef DBCS
|
||
|
if (fPrefix)
|
||
|
{
|
||
|
while (chc = *lpstr++)
|
||
|
{
|
||
|
if (((TCHAR)(DWORD)CharLower((LPTSTR)(DWORD)(BYTE)chc) == CH_PREFIX))
|
||
|
{
|
||
|
chnext = (TCHAR)(DWORD)CharLower((LPTSTR)(DWORD)(BYTE)*lpstr);
|
||
|
|
||
|
if (chnext == CH_PREFIX)
|
||
|
lpstr++;
|
||
|
else
|
||
|
if (chnext == ch)
|
||
|
return(0x01);
|
||
|
else
|
||
|
{
|
||
|
return(0x00);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
#ifdef JAPAN
|
||
|
if (fPrefix)
|
||
|
{
|
||
|
WORD wvch, xvkey;
|
||
|
|
||
|
// get OEM-dependent virtual key code
|
||
|
if ((wvch = VkKeyScan((BYTE)ch)) != -1)
|
||
|
wvch &= 0xFF;
|
||
|
|
||
|
while (chc = *lpstr++)
|
||
|
{
|
||
|
if (IsDBCSLeadByte(chc))
|
||
|
{
|
||
|
lpstr++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( (chc == CH_PREFIX) ||
|
||
|
(KanjiMenuMode == KMM_ENGLISH && chc == CH_ENGLISHPREFIX) ||
|
||
|
(KanjiMenuMode == KMM_KANJI && chc == CH_KANJIPREFIX))
|
||
|
{
|
||
|
chnext = (TCHAR)CharLower((LPTSTR)(DWORD)(BYTE)*lpstr);
|
||
|
|
||
|
if (chnext == CH_PREFIX)
|
||
|
lpstr++;
|
||
|
else
|
||
|
if (chnext == ch)
|
||
|
return(0x01);
|
||
|
|
||
|
// Compare should be done with virtual key in Kanji menu mode
|
||
|
// in order to accept Digit shortcut key and save English
|
||
|
// windows applications!
|
||
|
xvkey = VkKeyScan((BYTE)chnext);
|
||
|
|
||
|
if (xvkey != 0xFFFF && (xvkey & 0xFF) == wvch)
|
||
|
return(0x01);
|
||
|
else
|
||
|
return(0x00);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
#ifdef KOREA
|
||
|
if( fPrefix )
|
||
|
{
|
||
|
WORD wHangeul;
|
||
|
register TCHAR chnext2;
|
||
|
|
||
|
if( KanjiMenuMode != KMM_KANJI )
|
||
|
{
|
||
|
while (chc = *lpstr++)
|
||
|
{
|
||
|
if (IsDBCSLeadByte(chc))
|
||
|
{
|
||
|
lpstr++;
|
||
|
continue;
|
||
|
}
|
||
|
if ( (chc == CH_PREFIX) ||
|
||
|
(KanjiMenuMode == KMM_ENGLISH && chc == CH_ENGLISHPREFIX))
|
||
|
{
|
||
|
chnext = (TCHAR)CharLower((LPTSTR)(DWORD)(BYTE)*lpstr);
|
||
|
|
||
|
if (chnext == CH_PREFIX)
|
||
|
lpstr++;
|
||
|
else
|
||
|
if (chnext == ch)
|
||
|
return(0x01);
|
||
|
else
|
||
|
return(0x00);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{ //KMM_KANJI
|
||
|
if( ch >= TEXT('0') && ch <= TEXT('9') )
|
||
|
wHangeul = 0x0a3b0 | ( (BYTE)ch & 0x0f ); // junja 0 + offset
|
||
|
else
|
||
|
if( ch >= TEXT('a') && ch <= TEXT('z') )
|
||
|
wHangeul = TranslateHangeul( ch );
|
||
|
else
|
||
|
return(0x00);
|
||
|
|
||
|
while (chc = *lpstr++)
|
||
|
{
|
||
|
if (IsDBCSLeadByte(chc))
|
||
|
{
|
||
|
lpstr++;
|
||
|
continue;
|
||
|
}
|
||
|
if(chc == CH_KANJIPREFIX)
|
||
|
{
|
||
|
chnext = *lpstr++;
|
||
|
chnext2 = *lpstr;
|
||
|
|
||
|
if(chnext == HIBYTE(wHangeul) && chnext2 == LOBYTE(wHangeul))
|
||
|
return(0x01);
|
||
|
else
|
||
|
return(0x00);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif //KOREA
|
||
|
#endif //JAPAN
|
||
|
#endif //!DBCS
|
||
|
|
||
|
if (fFirst && (ch == chFirst))
|
||
|
return(0x80);
|
||
|
|
||
|
return(0x00);
|
||
|
}
|
||
|
|
||
|
#endif
|