#include "stdafx.h" #include #include #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