/* Miranda IM: the free IM client for Microsoft* Windows* Copyright 2000-2008 Miranda ICQ/IM project, all portions of this codebase are copyrighted to the people listed in contributors.txt. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //Include #include "hdr/modern_commonheaders.h" #include #include "m_api/m_skin_eng.h" #include "hdr/modern_skinselector.h" #include "hdr/modern_cluiframes.h" #define _EFFECTENUM_FULL_H #include "hdr/modern_effectenum.h" #undef _EFFECTENUM_FULL_H #include "hdr/modern_skinengine.h" #include "hdr/modern_commonprototypes.h" #include #include "hdr/modern_sync.h" //Implementation /* Global variables */ SKINOBJECTSLIST g_SkinObjectList={0}; CURRWNDIMAGEDATA * g_pCachedWindow=NULL; BOOL (WINAPI *g_proc_UpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD); BOOL g_flag_bPostWasCanceled =FALSE; BOOL g_flag_bFullRepaint =FALSE; BOOL g_mutex_bLockUpdating =FALSE; SortedList * gl_plGlyphTexts=NULL; SortedList * gl_plSkinFonts =NULL; /* Private module variables */ static HANDLE hSkinLoadedEvent; static GLYPHIMAGE * pLoadedImages=NULL; static DWORD dwLoadedImagesCount=0; static DWORD dwLoadedImagesAlocated=0; static BOOL flag_bUpdateQueued=FALSE; static BOOL flag_bJustDrawNonFramedObjects=FALSE; static BOOL mutex_bLockUpdate=FALSE; static SortedList * pEffectStack=NULL; static SKINOBJECTSLIST * pCurrentSkin=NULL; static char ** pszSettingName=NULL; static int nArrayLen=0; static char * iniCurrentSection=NULL; static char * szFileName=NULL; static BYTE pbGammaWeight[256]={0}; static BYTE pbGammaWeightAdv[256]={0}; static BOOL bGammaWeightFilled=FALSE; static CRITICAL_SECTION cs_SkinChanging={0}; /* Private module procedures */ static BOOL ske_GetMaskBit(BYTE *line, int x); static INT_PTR ske_Service_AlphaTextOut(WPARAM wParam,LPARAM lParam); static INT_PTR ske_Service_DrawIconEx(WPARAM wParam,LPARAM lParam); static int ske_AlphaTextOut (HDC hDC, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, DWORD ARGBcolor); static void ske_AddParseTextGlyphObject(char * szGlyphTextID,char * szDefineString,SKINOBJECTSLIST *Skin); static void ske_AddParseSkinFont(char * szFontID,char * szDefineString,SKINOBJECTSLIST *Skin); static int ske_DeleteAllSettingInSection(char * SectionName); static int ske_GetSkinFromDB(char * szSection, SKINOBJECTSLIST * Skin); static LPSKINOBJECTDESCRIPTOR ske_FindObject(const char * szName, BYTE objType,SKINOBJECTSLIST* Skin); static HBITMAP ske_LoadGlyphImageByDecoders(char * szFileName); static int ske_LoadSkinFromResource(BOOL bOnlyObjects); static void ske_PreMultiplyChanells(HBITMAP hbmp,BYTE Mult); static int ske_ValidateSingleFrameImage(FRAMEWND * Frame, BOOL SkipBkgBlitting); static INT_PTR ske_Service_UpdateFrameImage(WPARAM wParam, LPARAM lParam); static INT_PTR ske_Service_InvalidateFrameImage(WPARAM wParam, LPARAM lParam); static INT_PTR ske_Service_DrawTextWithEffect( WPARAM wParam, LPARAM lParam ); //Decoders static HMODULE hImageDecoderModule; typedef DWORD (__stdcall *pfnImgNewDecoder)(void ** ppDecoder); static pfnImgNewDecoder ImgNewDecoder; typedef DWORD (__stdcall *pfnImgDeleteDecoder)(void * pDecoder); static pfnImgDeleteDecoder ImgDeleteDecoder; typedef DWORD (__stdcall *pfnImgNewDIBFromFile)(LPVOID /*in*/pDecoder, LPCSTR /*in*/pFileName, LPVOID /*out*/*pImg); static pfnImgNewDIBFromFile ImgNewDIBFromFile; typedef DWORD (__stdcall *pfnImgDeleteDIBSection)(LPVOID /*in*/pImg); static pfnImgDeleteDIBSection ImgDeleteDIBSection; typedef DWORD (__stdcall *pfnImgGetHandle)(LPVOID /*in*/pImg, HBITMAP /*out*/*pBitmap, LPVOID /*out*/*ppDIBBits); static pfnImgGetHandle ImgGetHandle; static MODERNEFFECT meCurrentEffect={-1,{0},0,0}; ////////////////////////////////////////////////////////////////////////// // Ini file parser ////////////////////////////////////////////////////////////////////////// IniParser::IniParser( TCHAR * tcsFileName, BYTE flags ) : _Flags( flags ) { _DoInit(); if ( !tcsFileName ) return; if ( tcsFileName[0] == _T('%')) { //TODO: Add parser of resource filename here _LoadResourceIni( g_hInst, MAKEINTRESOURCEA(IDR_MSF_DEFAULT_SKIN), "MSF"); return; } _hFile = _tfopen( tcsFileName, _T("r")); if ( _hFile != NULL ) { _eType = IT_FILE; _isValid = true; } } IniParser::IniParser( HINSTANCE hInst, const char * resourceName, const char * resourceType, BYTE flags ) : _Flags( flags ) { _DoInit(); _LoadResourceIni( hInst, resourceName, resourceType ); } IniParser::~IniParser() { if ( _szSection ) mir_free( _szSection ); if ( _hFile ) fclose( _hFile ); if ( _hGlobalRes ) { UnlockResource( _hGlobalRes ); FreeResource(_hGlobalRes); } _szSection = NULL; _hGlobalRes = NULL; _hFile = NULL; _isValid = false; _eType = IT_UNKNOWN; } HRESULT IniParser::Parse( ParserCallback_t pLineCallBackProc, LPARAM SecCheck ) { if ( _isValid && pLineCallBackProc ) { _pLineCallBackProc = pLineCallBackProc; _SecCheck = SecCheck; switch ( _eType ) { case IT_FILE: return _DoParseFile(); case IT_RESOURCE: return _DoParseResource(); } } return E_FAIL; } HRESULT IniParser::WriteStrToDb( const char * szSection, const char * szName, const char * szValue, IniParser * This ) { if ( This->_SecCheck) { //TODO check security here if ( wildcmp( szSection,"Skin_Description_Section",1 )) return S_OK; } if ( ( This->_Flags == IniParser::FLAG_ONLY_OBJECTS ) && !wildcmp( szSection, DEFAULTSKINSECTION,1 )) return S_OK; // skip not objects // if ( strlen(szValue)>0 && szValue[strlen(szValue)-1]=='\n' ) // szValue[strlen(szValue)-1]='\0'; //kill linefeed at the end switch(szValue[0]) { case 'b': { BYTE P; P=(BYTE)atoi(szValue+1); ModernWriteSettingByte(NULL,szSection,szName,P); } break; case 'w': { WORD P; P=(WORD)atoi(szValue+1); ModernWriteSettingWord(NULL,szSection,szName,P); } break; case 'd': { DWORD P; P=(DWORD)atoi(szValue+1); ModernWriteSettingDword(NULL,szSection,szName,P); } break; case 's': ModernWriteSettingString(NULL,szSection,szName,szValue+1); break; case 'f': if (szFileName) { char fn[MAX_PATH]={0}; char bb[MAX_PATH*2]={0}; int pp, i; pp=-1; CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)szFileName, (LPARAM)fn); { for (i=strlen(fn); i>=0; i--) if (fn[i]=='.') break; if (i>0) fn[i]='\0'; } _snprintf(bb,SIZEOF(bb),"%s\\%s",fn,szValue+1); ModernWriteSettingString(NULL,szSection,szName,bb); } break; } return S_OK; } int IniParser::GetSkinFolder( IN const TCHAR * szFileName, OUT TCHAR * pszFolderName ) { TCHAR *pszPos; TCHAR *szBuff; szBuff = mir_tstrdup( szFileName ); pszPos = szBuff + _tcslen( szBuff ); while ( pszPos > szBuff && *pszPos!= _T('.')) { pszPos--; } *pszPos=_T('\0'); _tcscpy( pszFolderName, szBuff ); TCHAR custom_folder[MAX_PATH]; TCHAR cus[MAX_PATH]; TCHAR *b3; _tcscpy( custom_folder, pszFolderName ); b3=custom_folder + _tcslen( custom_folder ); while ( b3 > custom_folder && *b3!= _T('\\')) { b3--; } *b3=_T('\0'); GetPrivateProfileString(_T("Skin_Description_Section"),_T("SkinFolder"),_T(""),cus,SIZEOF(custom_folder),szFileName); if ( cus && _tcslen(cus)>0) _sntprintf(pszFolderName,MAX_PATH,_T("%s\\%s"),custom_folder,cus); mir_free_and_nill(szBuff); CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)pszFolderName, (LPARAM)pszFolderName); return 0; } void IniParser::_DoInit() { _isValid = false; _eType = IT_UNKNOWN; _szSection = NULL; _hFile = NULL; _hGlobalRes = NULL; _dwSizeOfRes = 0; _pPosition = NULL; _pLineCallBackProc = NULL; _SecCheck = 0; } void IniParser::_LoadResourceIni( HINSTANCE hInst, const char * resourceName, const char * resourceType ) { if ( _eType != IT_UNKNOWN ) return; HRSRC hRSrc = FindResourceA( hInst, resourceName, resourceType ); if ( !hRSrc ) return; _hGlobalRes=LoadResource( hInst, hRSrc ); if ( !_hGlobalRes ) return; _dwSizeOfRes = SizeofResource( hInst, hRSrc ); _pPosition =(char*) LockResource( _hGlobalRes ); _isValid = true; _eType = IT_RESOURCE; } HRESULT IniParser::_DoParseFile() { char szLine[MAX_LINE_LEN]; _nLine = 0; while ( fgets( szLine, SIZEOF(szLine), _hFile ) != NULL ) { size_t len = 0; char * pLine = (char*)_RemoveTailings( szLine, len ); if ( len > 0 ) { pLine[len]='\0'; if ( !_DoParseLine( pLine )) return E_FAIL; } else _nLine++; }; return S_OK; } HRESULT IniParser::_DoParseResource() { _nLine = 0; char szLine[MAX_LINE_LEN]; char * pos = ( char* ) _pPosition; while ( pos < _pPosition + _dwSizeOfRes ) { int i=0; while ( pos < _pPosition + _dwSizeOfRes && *pos != '\n' && *pos!= '\0' && i < MAX_LINE_LEN - 1 ) { if ( (*pos) != '\r' ) szLine[ i++ ] = *pos; pos++; } szLine[ i ]='\0'; pos++; size_t len = 0; char * pLine = (char*) _RemoveTailings( szLine, len ); if ( len > 0 ) { pLine[len]='\0'; if ( !_DoParseLine( pLine )) return E_FAIL; } else _nLine++; } return S_OK; } const char * IniParser::_RemoveTailings( const char * szLine, size_t& len ) { const char * pStart = szLine; while( *pStart == ' ' || *pStart=='\t' ) pStart++; //skip spaces at begin const char * pEnd = pStart + strlen( pStart ); while( pEnd > pStart && ( *pEnd == ' ' || *pEnd == '\t' || *pEnd == '\n' || *pEnd == '\r' )) pEnd--; len = pEnd - pStart; return pStart; } BOOL IniParser::_DoParseLine( char * szLine ) { _nLine++; DWORD len = strlen( szLine ); if ( len == 0 ) return TRUE; switch( szLine[0] ) { case ';': return TRUE; // start of comment is found case '[': { //New section start here if ( _szSection ) mir_free( _szSection ); _szSection = NULL; char *tbuf = szLine + 1; // skip [ char *ebuf= tbuf; while ( *ebuf != ']' && *ebuf !='\0' ) ebuf++; if ( *ebuf == '\0' ) return FALSE; // no close bracket DWORD sectionLen = ebuf - tbuf; _szSection = (char*) mir_alloc( sectionLen + 1 ); strncpy( _szSection, tbuf, sectionLen ); _szSection[sectionLen]='\0'; } return TRUE; default: if ( !_szSection ) return TRUE; //param found out of section char *keyName=szLine; char *keyValue=szLine; DWORD eqPlace=0; DWORD len2=strlen(keyName); while ( eqPlace < len2 && keyName[ eqPlace ] != '=' ) eqPlace++; //find '=' if (eqPlace==0 || eqPlace==len2) return TRUE; //= not found or no key name //say false keyName[eqPlace] = '\0'; keyValue = keyName + eqPlace + 1; //remove tail spaces in Name { DWORD len3=strlen(keyName); int j=len3-1; while (j>0 && (keyName[j]==' ' || keyName[j]=='\t')) j--; if (j>=0) keyName[j+1]='\0'; } //remove start spaces in Value { DWORD len3=strlen(keyValue); DWORD j=0; while (j0 && (keyValue[j]==' ' || keyValue[j]=='\t' || keyValue[j]=='\n')) j--; if (j>=0) keyValue[j+1]='\0'; } _pLineCallBackProc( _szSection, keyName, keyValue, this ); } return TRUE; } ////////////////////////////////////////////////////////////////////////// // End of IniParser ////////////////////////////////////////////////////////////////////////// HRESULT SkinEngineLoadModule() { ModernSkinButtonLoadModule(); InitializeCriticalSection(&cs_SkinChanging); MainModernMaskList=(LISTMODERNMASK*)mir_calloc(sizeof(LISTMODERNMASK)); //init variables g_SkinObjectList.dwObjLPAlocated=0; g_SkinObjectList.dwObjLPReserved=0; g_SkinObjectList.pObjects=NULL; // Initialize GDI+ InitGdiPlus(); AniAva_InitModule(); //load decoder hImageDecoderModule=NULL; if (g_CluiData.fGDIPlusFail) { hImageDecoderModule = LoadLibrary(TEXT("ImgDecoder.dll")); if (hImageDecoderModule==NULL) { char tDllPath[ MAX_PATH ]; GetModuleFileNameA( g_hInst, tDllPath, sizeof( tDllPath )); { char* p = strrchr( tDllPath, '\\' ); if ( p != NULL ) strcpy( p+1, "ImgDecoder.dll" ); else { strcpy( tDllPath, "ImgDecoder.dll" ); } } hImageDecoderModule = LoadLibraryA(tDllPath); } if (hImageDecoderModule!=NULL) { ImgNewDecoder=(pfnImgNewDecoder )GetProcAddress( hImageDecoderModule, "ImgNewDecoder"); ImgDeleteDecoder=(pfnImgDeleteDecoder )GetProcAddress( hImageDecoderModule, "ImgDeleteDecoder"); ImgNewDIBFromFile=(pfnImgNewDIBFromFile)GetProcAddress( hImageDecoderModule, "ImgNewDIBFromFile"); ImgDeleteDIBSection=(pfnImgDeleteDIBSection)GetProcAddress( hImageDecoderModule, "ImgDeleteDIBSection"); ImgGetHandle=(pfnImgGetHandle)GetProcAddress( hImageDecoderModule, "ImgGetHandle"); } } //create services CreateServiceFunction(MS_SKIN_DRAWGLYPH,ske_Service_DrawGlyph); CreateServiceFunction(MS_SKINENG_UPTATEFRAMEIMAGE,ske_Service_UpdateFrameImage); CreateServiceFunction(MS_SKINENG_INVALIDATEFRAMEIMAGE,ske_Service_InvalidateFrameImage); CreateServiceFunction(MS_SKINENG_ALPHATEXTOUT,ske_Service_AlphaTextOut); CreateServiceFunction(MS_SKINENG_DRAWICONEXFIX,ske_Service_DrawIconEx); CreateServiceFunction(MS_DRAW_TEXT_WITH_EFFECT,ske_Service_DrawTextWithEffect); //create event handle hSkinLoadedEvent=ModernHookEvent(ME_SKIN_SERVICESCREATED,CLUI_OnSkinLoad); NotifyEventHooks(g_CluiData.hEventSkinServicesCreated,0,0); return S_OK; } int SkinEngineUnloadModule() { //unload services ModernUnhookEvent(hSkinLoadedEvent); ModernSkinButtonUnloadModule(0,0); ske_UnloadSkin(&g_SkinObjectList); if (g_SkinObjectList.pObjects) mir_free_and_nill(g_SkinObjectList.pObjects); if (g_SkinObjectList.pMaskList) mir_free_and_nill(g_SkinObjectList.pMaskList); if (MainModernMaskList) mir_free_and_nill(MainModernMaskList); if (pEffectStack) { int i; for (i=0; irealCount; i++) if (pEffectStack->items[i]) { EFFECTSSTACKITEM * effect=(EFFECTSSTACKITEM*)(pEffectStack->items[i]); mir_free_and_nill(effect); } List_Destroy(pEffectStack); mir_free_and_nill(pEffectStack); } if (g_pCachedWindow) { SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackOld); SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageOld); DeleteObject(g_pCachedWindow->hBackDIB); DeleteObject(g_pCachedWindow->hImageDIB); mod_DeleteDC(g_pCachedWindow->hBackDC); mod_DeleteDC(g_pCachedWindow->hImageDC); ReleaseDC(NULL,g_pCachedWindow->hScreenDC); mir_free_and_nill(g_pCachedWindow); g_pCachedWindow=NULL; } DeleteCriticalSection(&cs_SkinChanging); GdiFlush(); DestroyServiceFunction((HANDLE)MS_SKIN_REGISTEROBJECT); DestroyServiceFunction((HANDLE)MS_SKIN_DRAWGLYPH); DestroyHookableEvent(g_CluiData.hEventSkinServicesCreated); if (hImageDecoderModule) FreeLibrary(hImageDecoderModule); AniAva_UnloadModule(); ShutdownGdiPlus(); //free variables return 1; } BOOL ske_AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,BLENDFUNCTION blendFunction) { if (g_CluiData.fDisableSkinEngine && !(!g_CluiData.fGDIPlusFail && blendFunction.BlendFlags&128)) { if (nWidthDest!=nWidthSrc || nHeightDest!=nHeightSrc) return StretchBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc, SRCCOPY); else return BitBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc, SRCCOPY); } if (!g_CluiData.fGDIPlusFail && blendFunction.BlendFlags&128 ) //Use gdi+ engine { return GDIPlus_AlphaBlend( hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest, hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc, &blendFunction); } blendFunction.BlendFlags&=~128; return AlphaBlend(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc,blendFunction); } static int ske_LockSkin() { EnterCriticalSection(&cs_SkinChanging); return 0; } static int ske_UnlockSkin() { LeaveCriticalSection(&cs_SkinChanging); return 0; } typedef struct _tagDCBuffer { HDC hdcOwnedBy; int nUsageID; int width; int height; void* pImage; HDC hDC; HBITMAP oldBitmap; HBITMAP hBitmap; DWORD dwDestroyAfterTime; }DCBUFFER; CRITICAL_SECTION BufferListCS={0}; SortedList * BufferList=NULL; enum { BUFFER_DRAWICON=0, BUFFER_DRAWIMAGE }; int SortBufferList(void* it1, void * it2) { DCBUFFER * buf1=(DCBUFFER *)it1; DCBUFFER * buf2=(DCBUFFER *)it2; if (buf1->hdcOwnedBy!=buf2->hdcOwnedBy) return (int)(buf1->hdcOwnedBy < buf2->hdcOwnedBy); else if (buf1->nUsageID!=buf2->nUsageID) return (int) (buf1->nUsageID < buf2->nUsageID); else return (int) (buf1->hDC < buf2->hDC); } HDC ske_RequestBufferDC(HDC hdcOwner, int dcID, int width, int height, BOOL fClear) { DCBUFFER buf; DCBUFFER * pBuf; if (BufferList==NULL) { BufferList=List_Create(0,2); BufferList->sortFunc=SortBufferList; InitializeCriticalSection(&BufferListCS); } EnterCriticalSection(&BufferListCS); //Try to find DC in buffer list buf.hdcOwnedBy=hdcOwner; buf.nUsageID=dcID; buf.hDC=NULL; pBuf=(DCBUFFER*)List_Find(BufferList,(void*)&buf); if (!pBuf) { //if not found - allocate it pBuf=(DCBUFFER *)mir_alloc(sizeof(DCBUFFER)); *pBuf=buf; pBuf->width=width; pBuf->height=height; pBuf->hBitmap=ske_CreateDIB32Point(width,height,&(pBuf->pImage)); pBuf->hDC=CreateCompatibleDC(hdcOwner); pBuf->oldBitmap=(HBITMAP)SelectObject(pBuf->hDC,pBuf->hBitmap); pBuf->dwDestroyAfterTime=0; List_InsertPtr(BufferList,pBuf); } else { if (pBuf->width!=width || pBuf->height!=height) { //resize SelectObject(pBuf->hDC,pBuf->oldBitmap); DeleteObject(pBuf->hBitmap); pBuf->width=width; pBuf->height=height; pBuf->hBitmap=ske_CreateDIB32Point(width,height,&(pBuf->pImage)); pBuf->oldBitmap=(HBITMAP)SelectObject(pBuf->hDC,pBuf->hBitmap); } else if (fClear) memset(pBuf->pImage,0,width*height*sizeof(DWORD)); } pBuf->dwDestroyAfterTime=0; LeaveCriticalSection(&BufferListCS); return pBuf->hDC; } int ske_ReleaseBufferDC(HDC hDC, int keepTime) { DWORD dwCurrentTime=GetTickCount(); DCBUFFER * pBuf=NULL; //Try to find DC in buffer list - set flag to be release after time; int i=0; EnterCriticalSection(&BufferListCS); for (i=0; irealCount; i++) { pBuf=(DCBUFFER *)BufferList->items[i]; if (pBuf) { if (hDC!=NULL && pBuf->hDC==hDC) { pBuf->dwDestroyAfterTime=dwCurrentTime+keepTime; break; } else { if ((pBuf->dwDestroyAfterTime && pBuf->dwDestroyAfterTime < dwCurrentTime) || keepTime==-1) { SelectObject(pBuf->hDC,pBuf->oldBitmap); DeleteObject(pBuf->hBitmap); DeleteDC(pBuf->hDC); mir_free(pBuf); List_Remove(BufferList,i); i--; } } } } LeaveCriticalSection(&BufferListCS); return 0; } BOOL ske_SetRgnOpaque(HDC memdc,HRGN hrgn, BOOL force) { RGNDATA * rdata; DWORD rgnsz; DWORD d; RECT * rect; if (g_CluiData.fDisableSkinEngine && !force) return TRUE; rgnsz=GetRegionData(hrgn,0,NULL); rdata=(RGNDATA *) mir_alloc(rgnsz); GetRegionData(hrgn,rgnsz,rdata); rect=(RECT *)rdata->Buffer; for (d=0; drdh.nCount; d++) { ske_SetRectOpaque(memdc,&rect[d], force); } mir_free_and_nill(rdata); return TRUE; } BOOL ske_SetRectOpaque(HDC memdc,RECT *fr, BOOL force) { int f=0; BYTE * bits; BITMAP bmp; HBITMAP hbmp; if ( g_CluiData.fDisableSkinEngine && !force ) return TRUE; hbmp=(HBITMAP)GetCurrentObject( memdc,OBJ_BITMAP ); GetObject( hbmp, sizeof(bmp), &bmp ); if ( bmp.bmPlanes != 1 ) return FALSE; if (!bmp.bmBits) { f=1; bits=(BYTE*)malloc(bmp.bmWidthBytes*bmp.bmHeight); GetBitmapBits(hbmp,bmp.bmWidthBytes*bmp.bmHeight,bits); } else bits=(BYTE*)bmp.bmBits; int sx =( fr->left > 0 ) ? fr->left : 0; int sy =( fr->top > 0 ) ? fr->top : 0; int ex =( fr->right < bmp.bmWidth ) ? fr->right : bmp.bmWidth; int ey =( fr->bottombottom : bmp.bmHeight; int width=ex-sx; BYTE* pLine = ((BYTE*)bits) + (bmp.bmHeight-sy-1)*bmp.bmWidthBytes + (sx << 2) + 3; for ( int y = 0; y < (ey - sy); y++ ) { BYTE * pColumn = pLine; for ( int x = 0; x < width; x++ ) { *pColumn = 255; pColumn += 4; } pLine -= bmp.bmWidthBytes; } if (f) { SetBitmapBits(hbmp,bmp.bmWidthBytes*bmp.bmHeight,bits); free(bits); } // DeleteObject(hbmp); return 1; } static BOOL ske_SkinFillRectByGlyph(HDC hDest, HDC hSource, RECT * rFill, RECT * rGlyph, RECT * rClip, BYTE mode, BYTE drawMode, int depth) { int destw=0, desth=0; int xstart=0, xmax=0; int ystart=0, ymax=0; BLENDFUNCTION bfa={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; //initializations if (mode==FM_STRETCH) { HDC mem2dc; HBITMAP mem2bmp, oldbmp; RECT wr; IntersectRect(&wr,rClip,rFill); if ((wr.bottom-wr.top)*(wr.right-wr.left)==0) return 0; if (drawMode!=2) { mem2dc=CreateCompatibleDC(hDest); mem2bmp=ske_CreateDIB32(wr.right-wr.left,wr.bottom-wr.top); oldbmp=(HBITMAP)SelectObject(mem2dc,mem2bmp); } if (drawMode==0 || drawMode==2) { if (drawMode==0) { ske_AlphaBlend(mem2dc,rFill->left-wr.left,rFill->top-wr.top,rFill->right-rFill->left,rFill->bottom-rFill->top, hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,rGlyph->bottom-rGlyph->top,bf); ske_AlphaBlend(hDest,wr.left,wr.top,wr.right-wr.left, wr.bottom -wr.top,mem2dc,0,0,wr.right-wr.left, wr.bottom -wr.top,bf); } else { ske_AlphaBlend(hDest,rFill->left,rFill->top,rFill->right-rFill->left,rFill->bottom-rFill->top, hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,rGlyph->bottom-rGlyph->top,bf); } } else { // BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, 0 }; ske_AlphaBlend(mem2dc,rFill->left-wr.left,rFill->top-wr.top,rFill->right-rFill->left,rFill->bottom-rFill->top, hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,rGlyph->bottom-rGlyph->top,bf); ske_AlphaBlend(hDest,wr.left,wr.top,wr.right-wr.left, wr.bottom -wr.top,mem2dc,0,0,wr.right-wr.left, wr.bottom -wr.top,bf); } if (drawMode!=2) { SelectObject(mem2dc,oldbmp); DeleteObject(mem2bmp); mod_DeleteDC(mem2dc); } return 1; } else if (mode==FM_TILE_VERT && (rGlyph->bottom-rGlyph->top>0)&& (rGlyph->right-rGlyph->left>0)) { HDC mem2dc; HBITMAP mem2bmp,oldbmp; RECT wr; IntersectRect(&wr,rClip,rFill); if ((wr.bottom-wr.top)*(wr.right-wr.left)==0) return 0; mem2dc=CreateCompatibleDC(hDest); //SetStretchBltMode(mem2dc, HALFTONE); mem2bmp=ske_CreateDIB32(wr.right-wr.left, rGlyph->bottom-rGlyph->top); oldbmp=(HBITMAP)SelectObject(mem2dc,mem2bmp); if (!oldbmp) return 0; /// draw here { int y=0, sy=0, maxy=0; int w=rFill->right-rFill->left; int h=rGlyph->bottom-rGlyph->top; if (h>0 && (wr.bottom-wr.top)*(wr.right-wr.left)!=0) { w=wr.right-wr.left; { // BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, 0 }; ske_AlphaBlend(mem2dc,-(wr.left-rFill->left),0,rFill->right-rFill->left,h,hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,h,bf); //StretchBlt(mem2dc,-(wr.left-rFill->left),0,rFill->right-rFill->left,h,hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,h,SRCCOPY); } if (drawMode==0 || drawMode==2) { if (drawMode==0 ) { int dy; dy=(wr.top-rFill->top)%h; if (dy>=0) { int ht; y=wr.top; ht=(y+h-dy<=wr.bottom)?(h-dy):(wr.bottom-wr.top); BitBlt(hDest,wr.left,y,w,ht,mem2dc,0,dy,SRCCOPY); } y=wr.top+h-dy; while (ytop)%h; if (dy>=0) { int ht; y=wr.top; ht=(y+h-dy<=wr.bottom)?(h-dy):(wr.bottom-wr.top); ske_AlphaBlend(hDest,wr.left,y,w,ht,mem2dc,0,dy,w,ht,bf); } y=wr.top+h-dy; while (yright-rGlyph->left>0)&& (rGlyph->bottom-rGlyph->top>0)&&(rFill->bottom-rFill->top)>0 && (rFill->right-rFill->left)>0) { HDC mem2dc; RECT wr; HBITMAP mem2bmp,oldbmp; int w=rGlyph->right-rGlyph->left; int h=rFill->bottom-rFill->top; IntersectRect(&wr,rClip,rFill); if ((wr.bottom-wr.top)*(wr.right-wr.left)==0) return 0; h=wr.bottom-wr.top; mem2dc=CreateCompatibleDC(hDest); mem2bmp=ske_CreateDIB32(w,h); oldbmp=(HBITMAP)SelectObject(mem2dc,mem2bmp); if (!oldbmp) return 0; /// draw here { int x=0, sy=0, maxy=0; { //SetStretchBltMode(mem2dc, HALFTONE); //StretchBlt(mem2dc,0,0,w,h,hSource,rGlyph->left+(wr.left-rFill->left),rGlyph->top,w,h,SRCCOPY); // BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, 0 }; ske_AlphaBlend(mem2dc,0,-(wr.top-rFill->top),w,rFill->bottom-rFill->top,hSource,rGlyph->left,rGlyph->top,w,rGlyph->bottom-rGlyph->top,bf); if (drawMode==0 || drawMode==2) { if (drawMode==0) { int dx; dx=(wr.left-rFill->left)%w; if (dx>=0) { int wt; x=wr.left; wt=(x+w-dx<=wr.right)?(w-dx):(wr.right-wr.left); BitBlt(hDest,x,wr.top,wt,h,mem2dc,dx,0,SRCCOPY); } x=wr.left+w-dx; while (xleft)%w; x=wr.left-dx; while (xleft)%w; if (dx>=0) { int wt; x=wr.left; wt=(x+w-dx<=wr.right)?(w-dx):(wr.right-wr.left); ske_AlphaBlend(hDest,x,wr.top,wt,h,mem2dc,dx,0,wt,h,bf); } x=wr.left+w-dx; while (xright-rGlyph->left>0) && (rGlyph->bottom-rGlyph->top>0)) { HDC mem2dc; int w=rGlyph->right-rGlyph->left; int x=0, sy=0, maxy=0; int h=rFill->bottom-rFill->top; HBITMAP mem2bmp,oldbmp; RECT wr; IntersectRect(&wr,rClip,rFill); if ((wr.bottom-wr.top)*(wr.right-wr.left)==0) return 0; mem2dc=CreateCompatibleDC(hDest); mem2bmp=ske_CreateDIB32(w,wr.bottom-wr.top); h=wr.bottom-wr.top; oldbmp=(HBITMAP)SelectObject(mem2dc,mem2bmp); #ifdef _DEBUG if (!oldbmp) (NULL,"Tile bitmap not selected","ERROR", MB_OK); #endif /// draw here { //fill temp bitmap { int y; int dy; dy=(wr.top-rFill->top)%(rGlyph->bottom-rGlyph->top); y=-dy; while (ybottom-rGlyph->top, hSource,rGlyph->left,rGlyph->top,w,rGlyph->bottom-rGlyph->top,bf); y+=rGlyph->bottom-rGlyph->top; } //-- //end temp bitmap if (drawMode==0 || drawMode==2) { if (drawMode==0) { int dx; dx=(wr.left-rFill->left)%w; if (dx>=0) { int wt; x=wr.left; wt=(x+w-dx<=wr.right)?(w-dx):(wr.right-wr.left); BitBlt(hDest,x,wr.top,wt,h,mem2dc,dx,0,SRCCOPY); } x=wr.left+w-dx; while (xleft)%w; x=wr.left-dx; while (xleft)%w; if (dx>=0) { int wt; x=wr.left; wt=(x+w-dx<=wr.right)?(w-dx):(wr.right-wr.left); ske_AlphaBlend(hDest,x,wr.top,wt,h,mem2dc,dx,0,wt,h,bf); } x=wr.left+w-dx; while (xhImageDIBByte; int x,y; unsigned int cRect = 64; PRGNDATA pRgnData = (PRGNDATA)malloc(sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT)); memset(pRgnData, 0, sizeof(RGNDATAHEADER)); pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER); pRgnData->rdh.iType = RDH_RECTANGLES; for (y = 0; y < g_pCachedWindow->Height; ++y) { bool inside = false; bool lastin = false; unsigned int entry = 0; for (x = 0; x < g_pCachedWindow->Width; ++x) { inside = Opaque ? (buf->rgbReserved > Level) : (buf->rgbReserved < Level); ++buf; if (inside != lastin) { if (inside) { lastin = true; entry = x; } else { if (pRgnData->rdh.nCount == cRect) { cRect = cRect + 64; pRgnData = (PRGNDATA)realloc(pRgnData, sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT)); } SetRect(((LPRECT)pRgnData->Buffer) + pRgnData->rdh.nCount, entry, g_pCachedWindow->Height - y, x, g_pCachedWindow->Height - y + 1); pRgnData->rdh.nCount++; lastin = false; } } } if (lastin) { if (pRgnData->rdh.nCount == cRect) { cRect = cRect + 64; pRgnData = (PRGNDATA)realloc(pRgnData, sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT)); } SetRect(((LPRECT)pRgnData->Buffer) + pRgnData->rdh.nCount, entry, g_pCachedWindow->Height - y, x, g_pCachedWindow->Height - y + 1); pRgnData->rdh.nCount++; } } HRGN hRgn = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount*sizeof(RECT), (LPRGNDATA)pRgnData); free(pRgnData); return hRgn; } static int ske_DrawSkinObject(SKINDRAWREQUEST * preq, GLYPHOBJECT * pobj) { HDC memdc=NULL, glyphdc=NULL; int k=0; //BITMAP bmp={0}; HBITMAP membmp=0,oldbmp=0,oldglyph=0; BYTE Is32Bit=0; RECT PRect; POINT mode2offset={0}; int depth=0; int mode=0; //0-FastDraw, 1-DirectAlphaDraw, 2-BufferedAlphaDraw if (!(preq && pobj)) return -1; if ((!pobj->hGlyph || pobj->hGlyph==(HBITMAP)-1) && ((pobj->Style&7) ==ST_IMAGE ||(pobj->Style&7) ==ST_FRAGMENT|| (pobj->Style&7) ==ST_SOLARIZE)) return 0; // Determine painting mode depth=GetDeviceCaps(preq->hDC,BITSPIXEL); depth=depth<16?16:depth; Is32Bit=pobj->bmBitsPixel==32; if ((!Is32Bit && pobj->dwAlpha==255)&& pobj->Style!=ST_BRUSH) mode=0; else if (pobj->dwAlpha==255 && pobj->Style!=ST_BRUSH) mode=1; else mode=2; // End painting mode //force mode if(preq->rcClipRect.bottom-preq->rcClipRect.top*preq->rcClipRect.right-preq->rcClipRect.left==0) preq->rcClipRect=preq->rcDestRect; IntersectRect(&PRect,&preq->rcDestRect,&preq->rcClipRect); if (IsRectEmpty(&PRect)) { return 0; } if (mode==2) { memdc=CreateCompatibleDC(preq->hDC); membmp=ske_CreateDIB32(PRect.right-PRect.left,PRect.bottom-PRect.top); oldbmp=(HBITMAP)SelectObject(memdc,membmp); if (oldbmp==NULL) { if (mode==2) { SelectObject(memdc,oldbmp); mod_DeleteDC(memdc); DeleteObject(membmp); } return 0; } } if (mode!=2) memdc=preq->hDC; { if (pobj->hGlyph && pobj->hGlyph!=(HBITMAP)-1) { glyphdc=CreateCompatibleDC(preq->hDC); if (!oldglyph) oldglyph=(HBITMAP)SelectObject(glyphdc,pobj->hGlyph); else SelectObject(glyphdc,pobj->hGlyph); } // Drawing { RECT rFill, rGlyph, rClip; if ((pobj->Style&7) ==ST_BRUSH) { HBRUSH br=CreateSolidBrush(pobj->dwColor); RECT fr; if (mode==2) { SetRect(&fr,0,0,PRect.right-PRect.left,PRect.bottom-PRect.top); FillRect(memdc,&fr,br); ske_SetRectOpaque(memdc,&fr); // FillRectAlpha(memdc,&fr,pobj->dwColor|0xFF000000); } else { fr=PRect; // SetRect(&fr,0,0,PRect.right-PRect.left,PRect.bottom-PRect.top); FillRect(preq->hDC,&fr,br); } DeleteObject(br); k=-1; } else { if (mode==2) { mode2offset.x=PRect.left; mode2offset.y=PRect.top; OffsetRect(&PRect,-mode2offset.x,-mode2offset.y); } rClip=(preq->rcClipRect); { int lft=0; int top=0; int rgh=pobj->bmWidth; int btm=pobj->bmHeight; if ((pobj->Style&7) ==ST_FRAGMENT) { lft=pobj->clipArea.x; top=pobj->clipArea.y; rgh=min(rgh,lft+pobj->szclipArea.cx); btm=min(btm,top+pobj->szclipArea.cy); } // Draw center... if (1) { rFill.top=preq->rcDestRect.top+pobj->dwTop; rFill.bottom=preq->rcDestRect.bottom-pobj->dwBottom; rFill.left=preq->rcDestRect.left+pobj->dwLeft; rFill.right=preq->rcDestRect.right-pobj->dwRight; if (mode==2) OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); rGlyph.top=top+pobj->dwTop; rGlyph.left=lft+pobj->dwLeft; rGlyph.right=rgh-pobj->dwRight; rGlyph.bottom=btm-pobj->dwBottom; k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode,mode,depth); } // Draw top side... if(1) { rFill.top=preq->rcDestRect.top; rFill.bottom=preq->rcDestRect.top+pobj->dwTop; rFill.left=preq->rcDestRect.left+pobj->dwLeft; rFill.right=preq->rcDestRect.right-pobj->dwRight; if (mode==2) OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); rGlyph.top=top+0; rGlyph.left=lft+pobj->dwLeft; rGlyph.right=rgh-pobj->dwRight; rGlyph.bottom=top+pobj->dwTop; k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_HORZ,mode,depth); } // Draw bottom side... if(1) { rFill.top=preq->rcDestRect.bottom-pobj->dwBottom; rFill.bottom=preq->rcDestRect.bottom; rFill.left=preq->rcDestRect.left+pobj->dwLeft; rFill.right=preq->rcDestRect.right-pobj->dwRight; if (mode==2) OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); rGlyph.top=btm-pobj->dwBottom; rGlyph.left=lft+pobj->dwLeft; rGlyph.right=rgh-pobj->dwRight; rGlyph.bottom=btm; k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_HORZ,mode,depth); } // Draw left side... if(1) { rFill.top=preq->rcDestRect.top+pobj->dwTop; rFill.bottom=preq->rcDestRect.bottom-pobj->dwBottom; rFill.left=preq->rcDestRect.left; rFill.right=preq->rcDestRect.left+pobj->dwLeft; if (mode==2) OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); rGlyph.top=top+pobj->dwTop; rGlyph.left=lft; rGlyph.right=lft+pobj->dwLeft; rGlyph.bottom=btm-pobj->dwBottom; k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_VERT,mode,depth); } // Draw right side... if(1) { rFill.top=preq->rcDestRect.top+pobj->dwTop; rFill.bottom=preq->rcDestRect.bottom-pobj->dwBottom; rFill.left=preq->rcDestRect.right-pobj->dwRight; rFill.right=preq->rcDestRect.right; if (mode==2) OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); rGlyph.top=top+pobj->dwTop; rGlyph.left=rgh-pobj->dwRight; rGlyph.right=rgh; rGlyph.bottom=btm-pobj->dwBottom; k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_VERT,mode,depth); } // Draw Top-Left corner... if(1) { rFill.top=preq->rcDestRect.top; rFill.bottom=preq->rcDestRect.top+pobj->dwTop; rFill.left=preq->rcDestRect.left; rFill.right=preq->rcDestRect.left+pobj->dwLeft; if (mode==2) OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); rGlyph.top=top; rGlyph.left=lft; rGlyph.right=lft+pobj->dwLeft; rGlyph.bottom=top+pobj->dwTop; k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth); } // Draw Top-Right corner... if(1) { rFill.top=preq->rcDestRect.top; rFill.bottom=preq->rcDestRect.top+pobj->dwTop; rFill.left=preq->rcDestRect.right-pobj->dwRight; rFill.right=preq->rcDestRect.right; if (mode==2) OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); rGlyph.top=top; rGlyph.left=rgh-pobj->dwRight; rGlyph.right=rgh; rGlyph.bottom=top+pobj->dwTop; k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth); } // Draw Bottom-Left corner... if(1) { rFill.top=preq->rcDestRect.bottom-pobj->dwBottom; rFill.bottom=preq->rcDestRect.bottom; rFill.left=preq->rcDestRect.left; rFill.right=preq->rcDestRect.left+pobj->dwLeft; if (mode==2) OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); rGlyph.left=lft; rGlyph.right=lft+pobj->dwLeft; rGlyph.top=btm-pobj->dwBottom; rGlyph.bottom=btm; k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth); } // Draw Bottom-Right corner... if(1) { rFill.top=preq->rcDestRect.bottom-pobj->dwBottom; rFill.bottom=preq->rcDestRect.bottom; rFill.left=preq->rcDestRect.right-pobj->dwRight; rFill.right=preq->rcDestRect.right; if (mode==2) OffsetRect(&rFill,-mode2offset.x,-mode2offset.y); rGlyph.left=rgh-pobj->dwRight; rGlyph.right=rgh; rGlyph.top=btm-pobj->dwBottom; rGlyph.bottom=btm; k+=ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth); } } } if ((k>0 || k==-1) && mode==2) { { BLENDFUNCTION bf={AC_SRC_OVER, 0, /*(bm.bmBitsPixel==32)?255:*/pobj->dwAlpha, (pobj->bmBitsPixel==32 && pobj->Style!=ST_BRUSH)?AC_SRC_ALPHA:0}; if (mode==2) OffsetRect(&PRect,mode2offset.x,mode2offset.y); ske_AlphaBlend( preq->hDC,PRect.left,PRect.top,PRect.right-PRect.left,PRect.bottom-PRect.top, memdc,0,0,PRect.right-PRect.left,PRect.bottom-PRect.top,bf); } } } //free GDI resources //--++-- //free GDI resources { if (oldglyph) SelectObject(glyphdc,oldglyph); if (glyphdc) mod_DeleteDC(glyphdc); } if (mode==2) { SelectObject(memdc,oldbmp); mod_DeleteDC(memdc); DeleteObject(membmp); } } if (pobj->plTextList && pobj->plTextList->realCount>0) { int i; HFONT hOldFont; for (i=0; iplTextList->realCount; i++) { GLYPHTEXT * gt=(GLYPHTEXT *)pobj->plTextList->items[i]; if (!gt->hFont) { if (gl_plSkinFonts && gl_plSkinFonts->realCount>0) { int j=0; for (j=0; jrealCount; j++) { SKINFONT * sf; sf=(SKINFONT*)gl_plSkinFonts->items[j]; if (sf->szFontID && !strcmp(sf->szFontID,gt->szFontID)) { gt->hFont=sf->hFont; break; } } } if (!gt->hFont) gt->hFont=(HFONT)-1; } if (gt->hFont!=(HFONT)-1) { RECT rc={0}; hOldFont=(HFONT)SelectObject(preq->hDC,gt->hFont); if (gt->RelativeFlags&2) rc.left=preq->rcDestRect.right+gt->iLeft; else if (gt->RelativeFlags&1) rc.left=((preq->rcDestRect.right-preq->rcDestRect.left)>>1)+gt->iLeft; else rc.left=preq->rcDestRect.left+gt->iLeft; if (gt->RelativeFlags&8) rc.top=preq->rcDestRect.bottom+gt->iTop; else if (gt->RelativeFlags&4) rc.top=((preq->rcDestRect.bottom-preq->rcDestRect.top)>>1)+gt->iTop; else rc.top=preq->rcDestRect.top+gt->iTop; if (gt->RelativeFlags&32) rc.right=preq->rcDestRect.right+gt->iRight; else if (gt->RelativeFlags&16) rc.right=((preq->rcDestRect.right-preq->rcDestRect.left)>>1)+gt->iRight; else rc.right=preq->rcDestRect.left+gt->iRight; if (gt->RelativeFlags&128) rc.bottom=preq->rcDestRect.bottom+gt->iBottom; else if (gt->RelativeFlags&64) rc.bottom=((preq->rcDestRect.bottom-preq->rcDestRect.top)>>1)+gt->iBottom; else rc.bottom=preq->rcDestRect.top+gt->iBottom; ske_AlphaTextOut(preq->hDC, gt->stText, -1, &rc,gt->dwFlags, gt->dwColor); SelectObject(preq->hDC,hOldFont); } } } return 0; } int ske_AddDescriptorToSkinObjectList (LPSKINOBJECTDESCRIPTOR lpDescr, SKINOBJECTSLIST* Skin) { SKINOBJECTSLIST *sk; if (Skin) sk=Skin; else sk=&g_SkinObjectList; if (!sk) return 0; if (mir_bool_strcmpi(lpDescr->szObjectID,"_HEADER_")) return 0; {//check if new object allready presents. DWORD i=0; for (i=0; idwObjLPAlocated;i++) if (!mir_strcmp(sk->pObjects[i].szObjectID,lpDescr->szObjectID)) return 0; } if (sk->dwObjLPAlocated+1>sk->dwObjLPReserved) { // Realocated list to add space for new object sk->pObjects=(SKINOBJECTDESCRIPTOR*)mir_realloc(sk->pObjects,sizeof(SKINOBJECTDESCRIPTOR)*(sk->dwObjLPReserved+1)/*alloc step*/); sk->dwObjLPReserved++; } { //filling new objects field sk->pObjects[sk->dwObjLPAlocated].bType=lpDescr->bType; sk->pObjects[sk->dwObjLPAlocated].Data=NULL; sk->pObjects[sk->dwObjLPAlocated].szObjectID=mir_strdup(lpDescr->szObjectID); // sk->Objects[sk->dwObjLPAlocated].szObjectName=mir_strdup(lpDescr->szObjectName); if (lpDescr->Data!=NULL) { //Copy defaults values switch (lpDescr->bType) { case OT_GLYPHOBJECT: { GLYPHOBJECT * obdat; GLYPHOBJECT * gl=(GLYPHOBJECT*)lpDescr->Data; sk->pObjects[sk->dwObjLPAlocated].Data=mir_alloc(sizeof(GLYPHOBJECT)); obdat=(GLYPHOBJECT*)sk->pObjects[sk->dwObjLPAlocated].Data; memmove(obdat,gl,sizeof(GLYPHOBJECT)); if (gl->szFileName!=NULL) { obdat->szFileName=mir_strdup(gl->szFileName); mir_free_and_nill(gl->szFileName); } else obdat->szFileName=NULL; obdat->hGlyph=NULL; break; } } } } sk->dwObjLPAlocated++; return 1; } static LPSKINOBJECTDESCRIPTOR ske_FindObject(const char * szName, BYTE objType, SKINOBJECTSLIST* Skin) { // DWORD i; SKINOBJECTSLIST* sk; sk=(Skin==NULL)?(&g_SkinObjectList):Skin; return skin_FindObjectByRequest((char *)szName,sk->pMaskList); } static LPSKINOBJECTDESCRIPTOR ske_FindObjectByMask(MODERNMASK * pModernMask, BYTE objType, SKINOBJECTSLIST* Skin) { // DWORD i; SKINOBJECTSLIST* sk; sk=(Skin==NULL)?(&g_SkinObjectList):Skin; if (!sk->pMaskList) return NULL; return skin_FindObjectByMask(pModernMask,sk->pMaskList); } LPSKINOBJECTDESCRIPTOR ske_FindObjectByName(const char * szName, BYTE objType, SKINOBJECTSLIST* Skin) { DWORD i; SKINOBJECTSLIST* sk; sk=(Skin==NULL)?(&g_SkinObjectList):Skin; for (i=0; idwObjLPAlocated; i++) { if (sk->pObjects[i].bType==objType || objType==OT_ANY) { if (!mir_strcmp(sk->pObjects[i].szObjectID,szName)) return &(sk->pObjects[i]); } } return NULL; } ////////////////////////////////////////////////////////////////////////// // Paint glyph // wParam - LPSKINDRAWREQUEST // lParam - possible direct pointer to modern mask ////////////////////////////////////////////////////////////////////////// INT_PTR ske_Service_DrawGlyph(WPARAM wParam,LPARAM lParam) { LPSKINDRAWREQUEST preq; LPSKINOBJECTDESCRIPTOR pgl; LPGLYPHOBJECT gl; if (!wParam) return -1; ske_LockSkin(); __try { preq=(LPSKINDRAWREQUEST)wParam; if (lParam) pgl=ske_FindObjectByMask((MODERNMASK*)lParam, OT_GLYPHOBJECT,NULL); else pgl=ske_FindObject(preq->szObjectID, OT_GLYPHOBJECT,NULL); if (pgl==NULL) return -1; if (pgl->Data==NULL) return -1; gl= (LPGLYPHOBJECT)pgl->Data; if ((gl->Style&7) ==ST_SKIP) return ST_SKIP; if (gl->hGlyph==NULL && gl->hGlyph!=(HBITMAP)-1 && ( (gl->Style&7)==ST_IMAGE ||(gl->Style&7)==ST_FRAGMENT ||(gl->Style&7)==ST_SOLARIZE )) if (gl->szFileName) { gl->hGlyph=ske_LoadGlyphImage(gl->szFileName); if (gl->hGlyph) { BITMAP bmp={0}; GetObject(gl->hGlyph,sizeof(BITMAP),&bmp); gl->bmBitsPixel=(BYTE)bmp.bmBitsPixel; gl->bmHeight=bmp.bmHeight; gl->bmWidth=bmp.bmWidth; } else gl->hGlyph=(HBITMAP)-1; //invalid } return ske_DrawSkinObject(preq,gl); } __finally { ske_UnlockSkin(); } return -1; } void ske_PreMultiplyChanells(HBITMAP hbmp,BYTE Mult) { BITMAP bmp; BOOL flag=FALSE; BYTE * pBitmapBits; DWORD Len; int bh,bw,y,x; GetObject(hbmp, sizeof(BITMAP), (LPSTR)&bmp); bh=bmp.bmHeight; bw=bmp.bmWidth; Len=bh*bw*4; flag=(bmp.bmBits==NULL); if (flag) { pBitmapBits=(LPBYTE)malloc(Len); GetBitmapBits(hbmp,Len,pBitmapBits); } else pBitmapBits=(BYTE*)bmp.bmBits; for (y=0; ybufSize) break; if (from) if (fromCountsizeof(header)) { tga_header_t * header=(tga_header_t *)mem; if (header->pixel_depth==32&& (header->image_type==2 ||header->image_type==10)) { colormap=(BYTE*)malloc(header->width*header->height*4); cx=header->width; cy=header->height; ske_ReadTGAImageData((void*)(mem+sizeof(tga_header_t)+header->id_lenght+header->cm_length), size-(sizeof(tga_header_t)+header->id_lenght+header->cm_length), colormap, cx*cy*4,header->image_type==10); } } FreeResource(hRes); } if (colormap) //create dib section { BYTE * pt; HBITMAP hbmp=ske_CreateDIB32Point(cx,cy,(void**)&pt); if (hbmp) memcpy(pt,colormap,cx*cy*4); free(colormap); return hbmp; } return NULL; } //this function is required to load PNG to dib buffer myself HBITMAP ske_LoadGlyphImage_Png2Dib(char * szFilename) { { HANDLE hFile, hMap = NULL; BYTE* ppMap = NULL; long cbFileSize = 0; BITMAPINFOHEADER* pDib; BYTE* pDibBits; if ( !ServiceExists( MS_PNG2DIB )) { MessageBox( NULL, TranslateT( "You need an image services plugin to process PNG images." ), TranslateT( "Error" ), MB_OK ); return (HBITMAP)NULL; } if (( hFile = CreateFileA( szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL )) != INVALID_HANDLE_VALUE ) if (( hMap = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL )) != NULL ) if (( ppMap = ( BYTE* )MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, 0 )) != NULL ) cbFileSize = GetFileSize( hFile, NULL ); if ( cbFileSize != 0 ) { PNG2DIB param; param.pSource = ppMap; param.cbSourceSize = cbFileSize; param.pResult = &pDib; if ( CallService( MS_PNG2DIB, 0, ( LPARAM )¶m )) pDibBits = ( BYTE* )( pDib+1 ); else cbFileSize = 0; } if ( ppMap != NULL ) UnmapViewOfFile( ppMap ); if ( hMap != NULL ) CloseHandle( hMap ); if ( hFile != NULL ) CloseHandle( hFile ); if ( cbFileSize == 0 ) return (HBITMAP)NULL; { BITMAPINFO* bi=( BITMAPINFO* )pDib; BYTE *pt=(BYTE*)bi; pt+=bi->bmiHeader.biSize; if (bi->bmiHeader.biBitCount!=32) { HDC sDC = GetDC( NULL ); HBITMAP hBitmap = CreateDIBitmap( sDC, pDib, CBM_INIT, pDibBits, bi, DIB_PAL_COLORS ); SelectObject( sDC, hBitmap ); DeleteDC( sDC ); GlobalFree( pDib ); return hBitmap; } else { BYTE * ptPixels=pt; HBITMAP hBitmap=CreateDIBSection(NULL,bi, DIB_RGB_COLORS, (void **)&ptPixels, NULL, 0); memcpy(ptPixels,pt,bi->bmiHeader.biSizeImage); GlobalFree( pDib ); return hBitmap; } } } } static HBITMAP ske_LoadGlyphImageByDecoders(char * szFileName) { // Loading image from file by imgdecoder... HBITMAP hBitmap=NULL; char ext[5]; BYTE f=0; LPBYTE pBitmapBits; LPVOID pImg= NULL; LPVOID m_pImgDecoder; BITMAP bmpInfo; { int l; l=mir_strlen(szFileName); memmove(ext,szFileName +(l-4),5); } if (!strchr(szFileName,'%') && !PathFileExistsA(szFileName)) return NULL; if (mir_bool_strcmpi(ext,".tga")) { hBitmap=ske_LoadGlyphImage_TGA(szFileName); f=1; } else if (ServiceExists("Image/Png2Dib") && mir_bool_strcmpi(ext,".png")) { hBitmap=ske_LoadGlyphImage_Png2Dib(szFileName); GetObject(hBitmap, sizeof(BITMAP), &bmpInfo); f=(bmpInfo.bmBits!=NULL); // hBitmap=(HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)szFileName); // f=1; } else if (hImageDecoderModule==NULL || !mir_bool_strcmpi(ext,".png")) hBitmap=(HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)szFileName); else { f=1; ImgNewDecoder(&m_pImgDecoder); if (!ImgNewDIBFromFile(m_pImgDecoder, szFileName, &pImg)) { ImgGetHandle(pImg, &hBitmap, (LPVOID *)&pBitmapBits); ImgDeleteDecoder(m_pImgDecoder); } } if (hBitmap) { GetObject(hBitmap, sizeof(BITMAP), &bmpInfo); if (bmpInfo.bmBitsPixel == 32) ske_PreMultiplyChanells(hBitmap,f); else { HDC dc24,dc32; HBITMAP hBitmap32,obmp24,obmp32; dc32=CreateCompatibleDC(NULL); dc24=CreateCompatibleDC(NULL); hBitmap32=ske_CreateDIB32(bmpInfo.bmWidth,bmpInfo.bmHeight); obmp24=(HBITMAP)SelectObject(dc24,hBitmap); obmp32=(HBITMAP)SelectObject(dc32,hBitmap32); BitBlt(dc32,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,dc24,0,0,SRCCOPY); SelectObject(dc24,obmp24); SelectObject(dc32,obmp32); mod_DeleteDC(dc24); mod_DeleteDC(dc32); DeleteObject(hBitmap); hBitmap=hBitmap32; ske_PreMultiplyChanells(hBitmap,0); } } return hBitmap; } HBITMAP ske_LoadGlyphImage(char * szFileName) { // try to find image in loaded DWORD i; HBITMAP hbmp; char szFile [MAX_PATH]={0}; ske_GetFullFilename(szFile,szFileName,g_SkinObjectList.szSkinPlace,TRUE); ske_LockSkin(); if (pLoadedImages) { for (i=0; idwLoadedImagesAlocated) { pLoadedImages=(GLYPHIMAGE*)mir_realloc(pLoadedImages,sizeof(GLYPHIMAGE)*(dwLoadedImagesCount+1)); if (pLoadedImages) dwLoadedImagesAlocated++; else { ske_UnlockSkin(); return NULL; } } pLoadedImages[dwLoadedImagesCount].dwLoadedTimes=1; pLoadedImages[dwLoadedImagesCount].hGlyph=hbmp; pLoadedImages[dwLoadedImagesCount].szFileName=mir_strdup(szFile); dwLoadedImagesCount++; ske_UnlockSkin(); return hbmp; } int ske_UnloadGlyphImage(HBITMAP hbmp) { DWORD i; for (i=0; iszFileName) mir_free_and_nill(gl->szFileName); memmove(&(pLoadedImages[i]),&(pLoadedImages[i+1]),sizeof(GLYPHIMAGE)*(dwLoadedImagesCount-i-1)); dwLoadedImagesCount--; DeleteObject(hbmp); if (pLoadedImages && dwLoadedImagesCount==0) { dwLoadedImagesAlocated=0; mir_free_and_nill(pLoadedImages); } } return 0; } } DeleteObject(hbmp); return 0; } int ske_UnloadSkin(SKINOBJECTSLIST * Skin) { DWORD i; ske_LockSkin(); ClearMaskList(Skin->pMaskList); {//clear font list int i; if (gl_plSkinFonts && gl_plSkinFonts->realCount>0) { for (i=0; irealCount; i++) { SKINFONT * sf=(SKINFONT *)gl_plSkinFonts->items[i]; if (sf) { if (sf->szFontID) mir_free_and_nill(sf->szFontID); DeleteObject(sf->hFont); mir_free_and_nill(sf); } } List_Destroy(gl_plSkinFonts); mir_free_and_nill(gl_plSkinFonts); } } if (Skin->szSkinPlace) mir_free_and_nill(Skin->szSkinPlace); if (Skin->pTextList) List_Destroy(Skin->pTextList); mir_free_and_nill(Skin->pTextList); ModernSkinButtonDeleteAll(); if (Skin->dwObjLPAlocated==0) { ske_UnlockSkin(); return 0;} for (i=0; idwObjLPAlocated; i++) { switch(Skin->pObjects[i].bType) { case OT_GLYPHOBJECT: { GLYPHOBJECT * dt; dt=(GLYPHOBJECT*)Skin->pObjects[i].Data; if (dt->hGlyph && dt->hGlyph!=(HBITMAP)-1) ske_UnloadGlyphImage(dt->hGlyph); dt->hGlyph=NULL; if (dt->szFileName) mir_free_and_nill(dt->szFileName); {// delete texts int i; if (dt->plTextList && dt->plTextList->realCount>0) { for (i=0; iplTextList->realCount; i++) { GLYPHTEXT * gt=(GLYPHTEXT *)dt->plTextList->items[i]; if (gt) { if (gt->stText) mir_free_and_nill(gt->stText); if (gt->stValueText) mir_free_and_nill(gt->stValueText); if (gt->szFontID) mir_free_and_nill(gt->szFontID); if (gt->szGlyphTextID)mir_free_and_nill(gt->szGlyphTextID); mir_free_and_nill(gt); } } List_Destroy(dt->plTextList); mir_free_and_nill(dt->plTextList); } } mir_free_and_nill(dt); } break; } if (Skin->pObjects[i].szObjectID) mir_free_and_nill(Skin->pObjects[i].szObjectID); } mir_free_and_nill(Skin->pObjects); Skin->pTextList=NULL; Skin->dwObjLPAlocated=0; Skin->dwObjLPReserved=0; ske_UnlockSkin(); return 0; } static void RegisterMaskByParce(const char * szSetting, char * szValue, SKINOBJECTSLIST * pSkin) { int i; DWORD ID=atoi(szSetting+1); for (i=0; ipMaskList,pSkin); mir_free_and_nill(Obj); } } static int ske_ProcessLoadindString(const char * szSetting, char *szValue) { if (!pCurrentSkin) return 0; if (szSetting[0]=='$') RegisterObjectByParce((char *)szSetting, szValue); else if (szSetting[0]=='#') RegisterButtonByParce((char *)szSetting,szValue); else if (szSetting[0]=='@') RegisterMaskByParce((char *)szSetting, szValue, pCurrentSkin); /// else if (szSetting[0]=='t') ske_AddParseTextGlyphObject((char*)szSetting,szValue,pCurrentSkin); else if (szSetting[0]=='f') ske_AddParseSkinFont((char*)szSetting,szValue,pCurrentSkin); else return 0; return 1; } static int ske_enumdb_SkinObjectsProc (const char *szSetting,LPARAM lParam) { char *value; value= ModernGetStringA(NULL,SKIN,szSetting); ske_ProcessLoadindString(szSetting,value); mir_free_and_nill(value); return 0; } static int ske_SortTextGlyphObjectFunc(void * first, void * second) { return strcmp(((GLYPHTEXT*)(((int*)first)[0]))->szGlyphTextID,((GLYPHTEXT*)(((int*)second)[0]))->szGlyphTextID); } static void ske_LinkSkinObjects(SKINOBJECTSLIST * pObjectList) { DWORD i; // LINK Mask with objects for (i=0; ipMaskList->dwMaskCnt; i++) { MODERNMASK *mm=&(pObjectList->pMaskList->pl_Masks[i]); void * pObject=(void*) ske_FindObjectByName(mm->szObjectName, OT_ANY, (SKINOBJECTSLIST*) pObjectList); mir_free_and_nill(mm->szObjectName); mm->bObjectFound=TRUE; mm->pObject=pObject; } if (pObjectList->pTextList) { int i; // LINK Text with objects for (i=0; ipTextList->realCount; i++) { GLYPHTEXT * glText; GLYPHOBJECT *globj=NULL; SKINOBJECTDESCRIPTOR * lpobj; glText=(GLYPHTEXT *)pObjectList->pTextList->items[i]; lpobj=ske_FindObjectByName(glText->szObjectName,OT_GLYPHOBJECT, pObjectList); mir_free_and_nill(glText->szObjectName); if (lpobj) globj=(GLYPHOBJECT*)lpobj->Data; if (globj) { if (!globj->plTextList) { globj->plTextList=List_Create(0,1); globj->plTextList->sortFunc=ske_SortTextGlyphObjectFunc; } List_Insert(globj->plTextList,(void*)glText,globj->plTextList->realCount); qsort(globj->plTextList->items,globj->plTextList->realCount,sizeof(void*),(int(*)(const void*, const void*))globj->plTextList->sortFunc); pObjectList->pTextList->items[i]=NULL; } else { GLYPHTEXT * gt=glText; if (gt) { if (gt->stText) mir_free_and_nill(gt->stText); if (gt->stValueText) mir_free_and_nill(gt->stValueText); if (gt->szFontID) mir_free_and_nill(gt->szFontID); if (gt->szGlyphTextID)mir_free_and_nill(gt->szGlyphTextID); mir_free_and_nill(gt); } } } List_Destroy(pObjectList->pTextList); mir_free_and_nill(pObjectList->pTextList); } } // Getting skin objects and masks from DB static int ske_GetSkinFromDB(char * szSection, SKINOBJECTSLIST * Skin) { if (Skin==NULL) return 0; ske_UnloadSkin(Skin); g_CluiData.fDisableSkinEngine=ModernGetSettingByte(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT); //window borders if (g_CluiData.fDisableSkinEngine) { g_CluiData.LeftClientMargin=0; g_CluiData.RightClientMargin=0; g_CluiData.TopClientMargin=0; g_CluiData.BottomClientMargin=0; } else { //window borders g_CluiData.LeftClientMargin=(int)ModernGetSettingByte(NULL,"CLUI","LeftClientMargin",SETTING_LEFTCLIENTMARIGN_DEFAULT); g_CluiData.RightClientMargin=(int)ModernGetSettingByte(NULL,"CLUI","RightClientMargin",SETTING_RIGHTCLIENTMARIGN_DEFAULT); g_CluiData.TopClientMargin=(int)ModernGetSettingByte(NULL,"CLUI","TopClientMargin",SETTING_TOPCLIENTMARIGN_DEFAULT); g_CluiData.BottomClientMargin=(int)ModernGetSettingByte(NULL,"CLUI","BottomClientMargin",SETTING_BOTTOMCLIENTMARIGN_DEFAULT); } if (g_CluiData.fDisableSkinEngine) return 0; Skin->pMaskList=(LISTMODERNMASK*)mir_alloc(sizeof(LISTMODERNMASK)); memset(Skin->pMaskList,0,sizeof(LISTMODERNMASK)); Skin->szSkinPlace= ModernGetStringA(NULL,SKIN,"SkinFolder"); if (!Skin->szSkinPlace || (strchr(Skin->szSkinPlace, '%') && !ModernGetSettingByte(NULL,SKIN,"Modified",0))) { BOOL bOnlyObjects=FALSE; if (Skin->szSkinPlace && strchr(Skin->szSkinPlace, '%')) bOnlyObjects=TRUE; mir_free(Skin->szSkinPlace); Skin->szSkinPlace=mir_strdup("%Default%"); ske_LoadSkinFromResource( bOnlyObjects ); } //Load objects { DBCONTACTENUMSETTINGS dbces; pCurrentSkin=Skin; dbces.pfnEnumProc=ske_enumdb_SkinObjectsProc; dbces.szModule=SKIN; dbces.ofsSettings=0; CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces); SortMaskList(pCurrentSkin->pMaskList); ske_LinkSkinObjects(pCurrentSkin); } //Load Masks return 0; } //surrogate to be called from outside void ske_LoadSkinFromDB(void) { ske_GetSkinFromDB(SKIN,&g_SkinObjectList); g_CluiData.dwKeyColor=ModernGetSettingDword(NULL,"ModernSettings","KeyColor",(DWORD)SETTING_KEYCOLOR_DEFAULT); } // /* static BOOL ske_ParseLineOfIniFile(char * Line, BOOL bOnlyObjects) { DWORD i=0; DWORD len=strlen(Line); while (i=len) return FALSE; //only spaces (or tabs) if (len>0 && Line[len-1]==10) Line[len-1]='\0'; switch(Line[i]) { case ';': return FALSE; // start of comment is found case '[': //New section start here if (iniCurrentSection) mir_free_and_nill(iniCurrentSection); { char *tbuf=Line+i+1; DWORD len2=strlen(tbuf); DWORD k=len2; while (k>0 && tbuf[k]!=']') k--; //searching close bracket tbuf[k]='\0'; //closing string if (k==0) return FALSE; iniCurrentSection=mir_strdup(tbuf); } return TRUE; default: if (!iniCurrentSection) return FALSE; //param found out of section { char *keyName=Line+i; char *keyValue=Line+i; DWORD eqPlace=0; DWORD len2=strlen(keyName); while (eqPlace0 && (keyName[j]==' ' || keyName[j]=='\t')) j--; if (j>=0) keyName[j+1]='\0'; } //remove start spaces in Value { DWORD len3=strlen(keyValue); DWORD j=0; while (j0 && (keyValue[j]==' ' || keyValue[j]=='\t')) j--; if (j>=0) keyValue[j+1]='\0'; } ske_WriteParamToDatabase(iniCurrentSection,keyName,keyValue,TRUE); } } return FALSE; } */ //Load data from ini file //int ske_OldLoadSkinFromIniFile(char * szFileName) //{ // char bsn[MAXSN_BUFF_SIZE]; // char * Buff; // // int i=0; // int f=0; // int ReadingSection=0; // char AllowedSection[260]; // int AllowedAll=0; // char t2[MAX_PATH]; // char t3[MAX_PATH]; // // DWORD retu=GetPrivateProfileSectionNamesA(bsn,MAXSN_BUFF_SIZE,szFileName); // ske_DeleteAllSettingInSection("ModernSkin"); // ske_GetSkinFolder(szFileName,t2); // ModernWriteSettingString(NULL,SKIN,"SkinFolder",t2); // CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)szFileName, (LPARAM)t3); // ModernWriteSettingString(NULL,SKIN,"SkinFile",t3); // Buff=bsn; // AllowedSection[0]=0; // do // { // f=mir_strlen(Buff); // if (f>0 && !mir_bool_strcmpi(Buff,"Skin_Description_Section")) // { // char b3[MAX_BUFF_SIZE]; // DWORD ret=0; // ret=GetPrivateProfileSectionA(Buff,b3,MAX_BUFF_SIZE,szFileName); // if (ret>MAX_BUFF_SIZE-3) continue; // if (ret==0) continue; // { // DWORD p=0; // char *s1; // char *s2; // char *s3; // { // DWORD t; // BOOL LOCK=FALSE; // for (t=0; tMAXPREDEFINEDEFFECTS) return; if (EffectID==-1) meCurrentEffect.EffectID=-1; else { meCurrentEffect.EffectID=EffectID; meCurrentEffect.EffectMatrix=ModernEffectsEnum[EffectID]; meCurrentEffect.EffectColor1=FirstColor; meCurrentEffect.EffectColor2=SecondColor; } } BOOL ske_ResetTextEffect(HDC hdc) { int i; if (!pEffectStack || !pEffectStack->realCount) return TRUE; for (i=0; irealCount; i++) if (pEffectStack->items[i] && ((EFFECTSSTACKITEM*)(pEffectStack->items[i]))->hdc==hdc) { EFFECTSSTACKITEM * effect=(EFFECTSSTACKITEM*)(pEffectStack->items[i]); mir_free_and_nill(effect); List_Remove(pEffectStack,i); return TRUE; } return FALSE; }; BOOL ske_SelectTextEffect(HDC hdc, BYTE EffectID, DWORD FirstColor, DWORD SecondColor) { if (EffectID>MAXPREDEFINEDEFFECTS) return 0; if (EffectID==-1) return ske_ResetTextEffect(hdc); if (!pEffectStack) { pEffectStack=List_Create(0,1); } { int i; for (i=0; irealCount; i++) if (pEffectStack->items[i] && ((EFFECTSSTACKITEM*)(pEffectStack->items[i]))->hdc==hdc) { EFFECTSSTACKITEM * effect=(EFFECTSSTACKITEM*)(pEffectStack->items[i]); effect->EffectID=EffectID; effect->FirstColor=FirstColor; effect->SecondColor=SecondColor; return TRUE; } } { EFFECTSSTACKITEM * effect=(EFFECTSSTACKITEM *) mir_alloc(sizeof(EFFECTSSTACKITEM)); effect->hdc=hdc; effect->EffectID=EffectID; effect->FirstColor=FirstColor; effect->SecondColor=SecondColor; List_Insert(pEffectStack, effect, 0); return TRUE; } return FALSE; } static BOOL ske_GetTextEffect(HDC hdc, MODERNEFFECT * modernEffect) { int i=0; if (!pEffectStack || !pEffectStack->realCount) return FALSE; if (!modernEffect) return FALSE; for (i=0; irealCount; i++) if (pEffectStack->items[i] && ((EFFECTSSTACKITEM*)(pEffectStack->items[i]))->hdc==hdc) { EFFECTSSTACKITEM * effect=(EFFECTSSTACKITEM*)(pEffectStack->items[i]); modernEffect->EffectID=effect->EffectID; modernEffect->EffectColor1=effect->FirstColor; modernEffect->EffectColor2=effect->SecondColor; modernEffect->EffectMatrix=ModernEffectsEnum[effect->EffectID]; return TRUE; } return FALSE; } static BOOL ske_DrawTextEffect(BYTE* destPt,BYTE* maskPt, DWORD width, DWORD height, MODERNEFFECT *effect) { sbyte *buf; sbyte *outbuf; sbyte *bufline, *buflineTop, *buflineMid; int sign=0; BYTE *maskline,*destline; BYTE al,rl,gl,bl,ad,rd,gd,bd; int k=0; DWORD x,y; sbyte *matrix; BYTE mcTopStart; BYTE mcBottomEnd; BYTE mcLeftStart; BYTE mcRightEnd; BYTE effectCount; int minX=width; int maxX=0; int minY=height; int maxY=0; if (effect->EffectID==0xFF) return FALSE; if (!width || ! height) return FALSE; if (!destPt) return FALSE; buf=(sbyte*)malloc(width*height*sizeof(BYTE)); { matrix=effect->EffectMatrix.matrix; mcTopStart=2-effect->EffectMatrix.topEffect; mcBottomEnd=3+effect->EffectMatrix.bottomEffect; mcLeftStart=2-effect->EffectMatrix.leftEffect; mcRightEnd=3+effect->EffectMatrix.rightEffect; effectCount=effect->EffectMatrix.cycleCount; } al=255-((BYTE)(effect->EffectColor1>>24)); rl=GetRValue(effect->EffectColor1); gl=GetGValue(effect->EffectColor1); bl=GetBValue(effect->EffectColor1); rd=GetRValue(effect->EffectColor2); gd=GetGValue(effect->EffectColor2); bd=GetBValue(effect->EffectColor2); ad=255-((BYTE)(effect->EffectColor2>>24)); rd=GetRValue(effect->EffectColor2); gd=GetGValue(effect->EffectColor2); bd=GetBValue(effect->EffectColor2); //Fill buffer by mid values of image for (y=0; y>4); *bufline=a; if (a!=0) { minX=min((int)x,minX); minY=min((int)y,minY); maxX=max((int)x,maxX); maxY=max((int)y,maxY); } bufline++; maskline+=4; } } //Here perform effect on buffer and place results to outbuf for (k=0; k<(effectCount&0x7F); k++) { minX = max( 0, minX + mcLeftStart - 2 ); minY = max( 0, minY + mcTopStart - 2 ); maxX = min( (int)width, maxX + mcRightEnd - 1 ); maxY = min( (int)height, maxY + mcBottomEnd - 1 ); outbuf=(sbyte*)malloc(width*height*sizeof(sbyte)); memset(outbuf,0,width*height*sizeof(sbyte)); for (y=(DWORD)minY; y<(DWORD)maxY; y++) { int val; bufline=outbuf+y*width+minX; buflineMid=buf+y*width+minX; for (x=(DWORD)minX; x<(DWORD)maxX; x++) { int matrixHor,matrixVer; val=0; for (matrixVer=mcTopStart; matrixVer=0 && (DWORD)as=0 && (DWORD)a>5; *bufline=(sbyte)((val>127)?127:(val<-125)?-125:val); bufline++; buflineMid++; } } free(buf); buf=outbuf; } { BYTE r1,b1,g1,a1; b1=bl; r1=rl; g1=gl; a1=al; sign=1; //perform out to dest for (y=0; y0 && sign<0) { b1=bl; r1=rl; g1=gl; a1=al; sign=1;} else if (val<0 && sign>0) { b1=bd; r1=rd; g1=gd; a1=ad; sign=-1;} absVal=absVal*a1/255; destline[0]=((destline[0]*(128-absVal))+absVal*b1)>>7; destline[1]=((destline[1]*(128-absVal))+absVal*g1)>>7; destline[2]=((destline[2]*(128-absVal))+absVal*r1)>>7; destline[3]+=((255-destline[3])*(a1*absVal))/32640; } bufline++; destline+=4; } } free(buf); } return FALSE; } static int ske_AlphaTextOut (HDC hDC, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, DWORD ARGBcolor) { if ( !( lpString && lpRect )) { DebugBreak(); return 0; } // Step first fill fast calc correction tables: static bool _tables_empty = true; static BYTE gammaTbl[256]; // Gamma correction table static WORD blueMulTbl[256]; // blue coefficient multiplication table static WORD greenMulTbl[256]; // green coefficient multiplication table static WORD redMulTbl[256]; // red coefficient multiplication table if ( _tables_empty ) { // fill tables double gammaCfPw = 1000 / (double)ModernGetSettingRangedWord(NULL,"ModernData","AlphaTextOutGamma", 700, 1, 5000 ); BYTE blueCf = ModernGetSettingByte(NULL,"ModernData","AlphaTextOutBlueCorrection", 28 ); BYTE redCf = ModernGetSettingByte(NULL,"ModernData","AlphaTextOutRed Correction", 77 ); BYTE greenCf = ModernGetSettingByte(NULL,"ModernData","AlphaTextOutGreen Correction", 151 ); for ( int i = 0; i < 256; i++ ) { gammaTbl[i]= (BYTE)( 255 * pow( (double)i / 255, gammaCfPw )); blueMulTbl[i] = i * blueCf; redMulTbl[i] = i * redCf; greenMulTbl[i] = i * greenCf; } } // Calc len of input string if ( nCount == -1 ) nCount = lstrlen( lpString ); // retrieve destination bitmap bits HBITMAP hDestBitmap = (HBITMAP) GetCurrentObject( hDC, OBJ_BITMAP ); BITMAP bmpDest; GetObject( hDestBitmap, sizeof(BITMAP), &bmpDest ); BOOL destHasNotDIB = FALSE; BYTE * pDestBits = NULL; if ( bmpDest.bmBits == NULL ) { destHasNotDIB = TRUE; pDestBits = (BYTE*) malloc ( bmpDest.bmHeight * bmpDest.bmWidthBytes ); GetBitmapBits( hDestBitmap, bmpDest.bmHeight*bmpDest.bmWidthBytes, pDestBits ); } else pDestBits=(BYTE*)bmpDest.bmBits; BOOL isDest16bit=( bmpDest.bmBitsPixel ) != 32; // Creating offscreen buffer HDC hOffscreenDC = CreateCompatibleDC( hDC ); // Font to be used to draw text HFONT hFont = (HFONT)GetCurrentObject( hDC, OBJ_FONT); HFONT hOldOffscreenFont = (HFONT)SelectObject( hOffscreenDC, hFont ); // Calculating text geometric size RECT workRect = *lpRect; int workRectWidth = workRect.right - workRect.left; int workRectHeight = workRect.bottom - workRect.top; if ( workRectWidth <= 0 || workRectHeight <= 0 ) return 0; SIZE textSize; GetTextExtentPoint32( hOffscreenDC, lpString, nCount, &textSize ); LPCTSTR lpWorkString = lpString; BOOL bNeedFreeWorkString = FALSE; // if we need to cut the text with ellipsis if ( ( format&DT_END_ELLIPSIS ) && textSize.cx > workRectWidth ) { // Calc geometric width of ellipsis SIZE szEllipsis; GetTextExtentPoint32A(hOffscreenDC,"...",3,&szEllipsis); szEllipsis.cx++; // CORRECTION: some width correction // Calc count of visible chars int visibleCharCount = nCount; if ( workRectWidth > szEllipsis.cx) { GetTextExtentExPoint( hOffscreenDC, lpString, nCount, workRectWidth - szEllipsis.cx, &visibleCharCount, NULL, &textSize ); } else { GetTextExtentExPoint( hOffscreenDC, lpString, nCount, 0, &visibleCharCount, NULL, &textSize); } // replace end of string by elipsis bNeedFreeWorkString = TRUE; lpWorkString = (TCHAR*) malloc( ( visibleCharCount + 4) * sizeof(TCHAR)); memcpy( (void*) lpWorkString, lpString, visibleCharCount * sizeof(TCHAR)); memcpy( (void*) ( lpWorkString + visibleCharCount ), _T("..."), 4 * sizeof(TCHAR)); // 3 + 1 nCount = visibleCharCount + 3; } // Calc sizes and offsets textSize.cx += 2; // CORRECTION: for italic int drx = 0; // x-axis offset of draw point if ( workRectWidth > textSize.cx ) { if ( format & ( DT_RIGHT | DT_RTLREADING )) { drx = workRectWidth - textSize.cx; } else if ( format & DT_CENTER ) { drx = ( workRectWidth - textSize.cx ) >> 1; } } else { textSize.cx = workRectWidth; } int dry = 0; // y-axis offset of draw point if ( workRectHeight > textSize.cy ) { if ( format & DT_BOTTOM ) { dry = workRectHeight - textSize.cy; } else if ( format & DT_VCENTER ) { dry = ( workRectHeight - textSize.cy ) >> 1; } } else { textSize.cy = workRectHeight; } textSize.cx += 4; // CORRECTION: for effects ??? textSize.cy += 4; // CORRECTION: for effects ??? if ( textSize.cx > 0 && textSize.cy > 0 ) // Ok we need to paint { // probably here are mess ofscreen and temp buff dc //Create bitmap image for offscreen BYTE * bits = NULL; HBITMAP hbmp = ske_CreateDIB32Point( textSize.cx, textSize.cy, (void**)&bits ); if ( bits != NULL ) { HBITMAP holdbmp = (HBITMAP)SelectObject( hOffscreenDC, hbmp ); //Create buffer bitmap image for temp text BYTE * bufbits = NULL; HBITMAP bufbmp = ske_CreateDIB32Point( textSize.cx, textSize.cy, (void**)&bufbits ); if ( bufbits != NULL ) { HDC bufDC = CreateCompatibleDC( hDC ); HBITMAP bufoldbmp = (HBITMAP)SelectObject( bufDC, bufbmp ); HFONT hOldBufFont = (HFONT)SelectObject( bufDC, hFont ); SetBkColor( bufDC, RGB( 0, 0, 0 )); SetTextColor( bufDC,RGB(255,255,255)); // Copy from destination to temp buffer BitBlt( hOffscreenDC, 0, 0, textSize.cx, textSize.cy, hDC, workRect.left + drx - 2, workRect.top + dry - 2, SRCCOPY ); //Draw text on offscreen bitmap TextOut( bufDC, 2, 2, lpWorkString, nCount); MODERNEFFECT effect; if (ske_GetTextEffect( hDC, &effect )) ske_DrawTextEffect( bits, bufbits, textSize.cx, textSize.cy, &effect ); //RenderText RECT drawRect; drawRect.left = 0; drawRect.top = 0; drawRect.right = textSize.cx; drawRect.bottom = textSize.cy; DWORD x,y; DWORD width=textSize.cx; DWORD heigh=textSize.cy; BYTE * pDestScanLine; BYTE * pBufScanLine; BYTE * pix; BYTE * bufpix; BYTE al = 255 - ((BYTE)( ARGBcolor >> 24 )); BYTE r = GetRValue( ARGBcolor ); BYTE g = GetGValue( ARGBcolor ); BYTE b = GetBValue( ARGBcolor ); for ( y = 2; y < heigh - 2; y++ ) { int lineBytes = y * (width<<2); pDestScanLine = bits + lineBytes; pBufScanLine = bufbits + lineBytes; for ( x = 2; x < width - 2; x++) { pix = pDestScanLine + ( x<<2 ); bufpix = pBufScanLine + ( x<<2 ); // Monochromatic BYTE bx = gammaTbl[ bufpix[0] ]; BYTE gx = gammaTbl[ bufpix[1] ]; BYTE rx = gammaTbl[ bufpix[2] ]; if ( al != 255 ) { bx*=al/255; gx*=al/255; rx*=al/255; } BYTE ax = (BYTE)( ( (DWORD)rx*77 + (DWORD)gx * 151 + (DWORD)bx *28 + 128 ) / 256 ); if (ax) { //Normalize components to gray BYTE axx = 255 - ( ( r + g + b ) >> 2 ) ; // Coefficient of grayance, more white font - more gray edges WORD atx = ax * (255 - axx); bx=( atx + bx * axx )/255; gx=( atx + gx * axx )/255; rx=( atx + rx * axx )/255; short rrx, grx, brx; brx=(short)((b-pix[0])*bx/255); grx=(short)((g-pix[1])*gx/255); rrx=(short)((r-pix[2])*rx/255); pix[0]+=brx; pix[1]+=grx; pix[2]+=rrx; pix[3]=(BYTE)(ax+(BYTE)(255-ax)*pix[3]/255); } } } //Blit to destination BitBlt( hDC, workRect.left + drx - 2, workRect.top + dry - 2, textSize.cx, textSize.cy, hOffscreenDC, 0, 0, SRCCOPY ); //free resources SelectObject(bufDC,bufoldbmp); DeleteObject(bufbmp); SelectObject(bufDC, hOldBufFont ); mod_DeleteDC(bufDC); } SelectObject(hOffscreenDC,holdbmp); DeleteObject(hbmp); } } // Final cleanup SelectObject( hOffscreenDC, hOldOffscreenFont ); DeleteDC( hOffscreenDC ); if ( destHasNotDIB ) free( pDestBits ); if ( bNeedFreeWorkString ) free( (void*)lpWorkString ); return 0; } static int ske_DrawTextWithEffectWorker( HDC hdc, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, MODERNFONTEFFECT * effect ) { if (format&DT_CALCRECT) return DrawText(hdc,lpString,nCount,lpRect,format); if (format&DT_RTLREADING) SetTextAlign(hdc,TA_RTLREADING); DWORD color=GetTextColor(hdc); RECT r=*lpRect; OffsetRect(&r,1,1); DWORD form = format; if ( effect && effect->effectIndex ) ske_SelectTextEffect( hdc, effect->effectIndex - 1, effect->baseColour, effect->secondaryColour ); int res = ske_AlphaTextOut(hdc, lpString, nCount, lpRect, form, color ); if ( effect && effect->effectIndex ) ske_ResetTextEffect( hdc ); return res; } INT_PTR ske_Service_DrawTextWithEffect( WPARAM wParam, LPARAM lParam ) { DrawTextWithEffectParam * p = ( DrawTextWithEffectParam * ) wParam; if ( p->cbSize != sizeof(DrawTextWithEffectParam)) return FALSE; return ske_DrawTextWithEffectWorker( p->hdc, p->lpchText, p->cchText, p->lprc, p->dwDTFormat, p->pEffect ); } BOOL ske_DrawTextA(HDC hdc, char * lpString, int nCount, RECT * lpRect, UINT format) { TCHAR *buf=mir_a2u(lpString); BOOL res; res=ske_DrawText(hdc,buf,nCount,lpRect,format); mir_free(buf); return res; } BOOL ske_DrawText(HDC hdc, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format) { DWORD form=0, color=0; RECT r=*lpRect; OffsetRect(&r,1,1); if (format&DT_RTLREADING) SetTextAlign(hdc,TA_RTLREADING); if (format&DT_CALCRECT) return DrawText(hdc,lpString,nCount,lpRect,format); if (format&DT_FORCENATIVERENDER || g_CluiData.fDisableSkinEngine) return DrawText(hdc,lpString,nCount,lpRect,format&~DT_FORCENATIVERENDER); form=format; color=GetTextColor(hdc); if (!g_CluiData.fGDIPlusFail &&0) ///text via gdi+ { TextOutWithGDIp(hdc,lpRect->left,lpRect->top,lpString,nCount); return 0; } return ske_AlphaTextOut(hdc,lpString,nCount,lpRect,form,color); } HICON ske_ImageList_GetIcon(HIMAGELIST himl, int i, UINT fStyle) { IMAGEINFO imi={0}; BITMAP bm={0}; if ( IsWinVerXPPlus() && i!=-1 ) { ImageList_GetImageInfo(himl,i,&imi); GetObject(imi.hbmImage,sizeof(bm),&bm); if (bm.bmBitsPixel==32) //stupid bug of Microsoft // Icons bitmaps are not premultiplied // So Imagelist_AddIcon - premultiply alpha // But incorrect - it is possible that alpha will // be less than color and // ImageList_GetIcon will return overflowed colors // TODO: Direct draw Icon from imagelist without // extracting of icon { BYTE * bits=NULL; bits=(BYTE*)bm.bmBits; if (!bits) { bits=(BYTE*)malloc(bm.bmWidthBytes*bm.bmHeight); GetBitmapBits(imi.hbmImage,bm.bmWidthBytes*bm.bmHeight,bits); } { int iy; BYTE *bcbits; int wb=((imi.rcImage.right-imi.rcImage.left)*bm.bmBitsPixel>>3); bcbits=bits+(bm.bmHeight-imi.rcImage.bottom)*bm.bmWidthBytes+(imi.rcImage.left*bm.bmBitsPixel>>3); for (iy=0; iy>24); if (a!=0) { BYTE r= (BYTE)((val&0xFF0000)>>16); BYTE g= (BYTE)((val&0xFF00)>>8); BYTE b= (BYTE)(val&0xFF); if (ahdc,p->xLeft,p->yTop,p->hIcon,p->cxWidth,p->cyWidth,p->istepIfAniCur,p->hbrFlickerFreeDraw,p->diFlags); } BOOL ske_DrawIconEx(HDC hdcDst,int xLeft,int yTop,HICON hIcon,int cxWidth,int cyWidth, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags) { ICONINFO ici; BYTE alpha=(BYTE)((diFlags&0xFF000000)>>24); HDC imDC; HBITMAP oldBmp, imBmp,tBmp; BITMAP imbt,immaskbt; BYTE * imbits; BYTE * imimagbits; BYTE * immaskbits; DWORD cx,cy,icy; BYTE *t1, *t2, *t3; BOOL NoDIBImage=FALSE; //lockimagelist BYTE hasmask=FALSE; BYTE no32bit=FALSE; BYTE noMirrorMask=FALSE; BYTE hasalpha=FALSE; alpha=alpha?alpha:255; if ( g_CluiData.fDisableSkinEngine && !(diFlags&0x80)) return DrawIconEx(hdcDst,xLeft,yTop,hIcon,cxWidth,cyWidth,istepIfAniCur,hbrFlickerFreeDraw,diFlags&0xFFFF7F); if (!GetIconInfo(hIcon,&ici)) return 0; GetObject(ici.hbmColor,sizeof(BITMAP),&imbt); if (imbt.bmWidth*imbt.bmHeight==0) { DeleteObject(ici.hbmColor); DeleteObject(ici.hbmMask); return 0; } GetObject(ici.hbmMask,sizeof(BITMAP),&immaskbt); cy=imbt.bmHeight; if (imbt.bmBitsPixel!=32) { HDC tempDC1; HBITMAP otBmp; no32bit=TRUE; tempDC1=CreateCompatibleDC(hdcDst); tBmp=ske_CreateDIB32(imbt.bmWidth,imbt.bmHeight); if (tBmp) { GetObject(tBmp,sizeof(BITMAP),&imbt); otBmp=(HBITMAP)SelectObject(tempDC1,tBmp); DrawIconEx(tempDC1,0,0,hIcon,imbt.bmWidth,imbt.bmHeight,istepIfAniCur,hbrFlickerFreeDraw,DI_IMAGE); noMirrorMask=TRUE; } SelectObject(tempDC1,otBmp); mod_DeleteDC(tempDC1); } /* if (imbt.bmBitsPixel!=32) { HDC tempDC1; HBITMAP otBmp; no32bit=TRUE; tempDC1=ske_RequestBufferDC(hdcDst,BUFFER_DRAWICON,imbt.bmWidth,imbt.bmHeight); if (tempDC1) { DrawIconEx(tempDC1,0,0,hIcon,imbt.bmWidth,imbt.bmHeight,istepIfAniCur,hbrFlickerFreeDraw,DI_IMAGE); noMirrorMask=TRUE; ske_ReleaseBufferDC(tempDC1,2000); //keep buffer for 2 seconds } } */ if (imbt.bmBits==NULL) { NoDIBImage=TRUE; imimagbits=(BYTE*)malloc(cy*imbt.bmWidthBytes); GetBitmapBits(ici.hbmColor,cy*imbt.bmWidthBytes,(void*)imimagbits); } else imimagbits=(BYTE*)imbt.bmBits; if (immaskbt.bmBits==NULL) { immaskbits=(BYTE*)malloc(cy*immaskbt.bmWidthBytes); GetBitmapBits(ici.hbmMask,cy*immaskbt.bmWidthBytes,(void*)immaskbits); } else immaskbits=(BYTE*)immaskbt.bmBits; icy=imbt.bmHeight; cx=imbt.bmWidth; imDC=CreateCompatibleDC(hdcDst); imBmp=ske_CreateDIB32Point(cx,icy,(void**)&imbits); oldBmp=(HBITMAP)SelectObject(imDC,imBmp); if (imbits!=NULL && imimagbits!=NULL && immaskbits!=NULL) { int x; int y; int bottom,right,top,h; int mwb,mwb2; mwb=immaskbt.bmWidthBytes; mwb2=imbt.bmWidthBytes; bottom=icy; right=cx; top=0; h=icy; for (y=top;(y>3))))!=0; if (mask)// && !hasalpha) { if (!hasalpha) { *dest=0; continue; } else { if (((BYTE*)src)[3]>0 ) a = ((BYTE*)src)[3]; else a = 0; } } else if (hasalpha || hasmask) a=(((BYTE*)src)[3]>0?((BYTE*)src)[3]:255); else if (!hasalpha && !hasmask) a=255; else { *dest=0; continue; } } if (a>0) { ((BYTE*)dest)[3]=a; ((BYTE*)dest)[0]=((BYTE*)src)[0]*a/255; ((BYTE*)dest)[1]=((BYTE*)src)[1]*a/255; ((BYTE*)dest)[2]=((BYTE*)src)[2]*a/255; } else *dest=0; } } } { BLENDFUNCTION bf={AC_SRC_OVER, diFlags&128, alpha, AC_SRC_ALPHA }; ske_AlphaBlend(hdcDst,xLeft,yTop,cxWidth, cyWidth, imDC,0,0, cx,icy,bf); } if (immaskbt.bmBits==NULL) free(immaskbits); if (imbt.bmBits==NULL) free(imimagbits); SelectObject(imDC,oldBmp); DeleteObject(imBmp); if(no32bit)DeleteObject(tBmp); DeleteObject(ici.hbmColor); DeleteObject(ici.hbmMask); SelectObject(imDC,GetStockObject(DEFAULT_GUI_FONT)); mod_DeleteDC(imDC); return 1;// DrawIconExS(hdc,xLeft,yTop,hIcon,cxWidth,cyWidth,istepIfAniCur,hbrFlickerFreeDraw,diFlags); } int ske_PrepeareImageButDontUpdateIt(RECT * r) { if (g_CluiData.fLayered) { mutex_bLockUpdate=1; ske_DrawNonFramedObjects(TRUE,r); ske_ValidateFrameImageProc(r); mutex_bLockUpdate=0; return 0; } else { return ske_ReCreateBackImage(FALSE,r); } return 0; } int ske_RedrawCompleteWindow() { if (g_CluiData.fLayered) { ske_DrawNonFramedObjects(TRUE,0); CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,0,0); } else { RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_ALLCHILDREN|RDW_ERASE|RDW_INVALIDATE|RDW_FRAME); } return 0; } // Request to repaint frame or change/drop callback data // wParam = hWnd of called frame // lParam = pointer to sPaintRequest (or NULL to redraw all) // return 2 - already queued, data updated, 1-have been queued, 0 - failure static INT_PTR ske_Service_UpdateFrameImage(WPARAM wParam, LPARAM lParam) // Immideately recall paint routines for frame and refresh image { if ( MirandaLoading()) return 0; RECT wnd; FRAMEWND *frm; BOOL NoCancelPost=0; BOOL IsAnyQueued=0; if (!g_CluiData.mutexOnEdgeSizing) GetWindowRect(pcli->hwndContactList,&wnd); else wnd=g_rcEdgeSizingRect; if (!g_CluiData.fLayered) { RedrawWindow((HWND)wParam,NULL,NULL,RDW_UPDATENOW|RDW_ERASE|RDW_INVALIDATE|RDW_FRAME); return 0; } if (g_pCachedWindow==NULL) ske_ValidateFrameImageProc(&wnd); else if (g_pCachedWindow->Width!=wnd.right-wnd.left || g_pCachedWindow->Height!=wnd.bottom-wnd.top) ske_ValidateFrameImageProc(&wnd); else if (wParam==0) ske_ValidateFrameImageProc(&wnd); else // all Ok Update Single Frame { // TO BE LOCKED OR PROXIED frm=FindFrameByItsHWND((HWND)wParam); if (!frm) ske_ValidateFrameImageProc(&wnd); // Validate frame, update window image and remove it from queue else { if(frm->UpdateRgn) { DeleteObject(frm->UpdateRgn); frm->UpdateRgn=0; } ske_ValidateSingleFrameImage(frm,0); ske_UpdateWindowImage(); NoCancelPost=1; //-- Remove frame from queue if (flag_bUpdateQueued) { int i; frm->bQueued=0; for(i=0;ifloating)) return InvalidateRect((HWND)wParam,pr?(RECT*)&(pr->rcUpdate):NULL,FALSE); if (frm) { if (frm->PaintCallbackProc!=NULL) { frm->PaintData=(sPaintRequest *)pr; frm->bQueued=1; if (pr) { HRGN r2; if (!IsRectEmpty(&pr->rcUpdate)) { RECT rcClient; RECT rcUpdate; GetClientRect(frm->hWnd,&rcClient); IntersectRect( &rcUpdate, &rcClient, &pr->rcUpdate ); if ( IsRectEmpty( &rcUpdate )) return 0; r2=CreateRectRgn( rcUpdate.left, rcUpdate.top, rcUpdate.right, rcUpdate.bottom ); } else { RECT r; GetClientRect(frm->hWnd,&r); r2=CreateRectRgn(r.left,r.top,r.right,r.bottom); } if (!frm->UpdateRgn) { frm->UpdateRgn=CreateRectRgn(0,0,1,1); CombineRgn(frm->UpdateRgn,r2,0,RGN_COPY); } else CombineRgn(frm->UpdateRgn,frm->UpdateRgn,r2,RGN_OR); DeleteObject(r2); } } } else { Sync( QueueAllFramesUpdating, (BYTE)1 ); } } else Sync( QueueAllFramesUpdating , (BYTE)1 ); if (!flag_bUpdateQueued||g_flag_bPostWasCanceled) if (PostMessage(pcli->hwndContactList,UM_UPDATE,0,0)) { flag_bUpdateQueued=1; g_flag_bPostWasCanceled=0; } return 1; } static int ske_ValidateSingleFrameImage(FRAMEWND * Frame, BOOL SkipBkgBlitting) // Calling frame paint proc { if (!g_pCachedWindow) { TRACE("ske_ValidateSingleFrameImage calling without cached\n"); return 0;} if (Frame->hWnd==(HWND)-1 && !Frame->PaintCallbackProc) { TRACE("ske_ValidateSingleFrameImage calling without FrameProc\n"); return 0;} { // if ok update image HDC hdc; HBITMAP o,n; RECT rcPaint,wnd; RECT ru={0}; int w,h,x,y; int w1,h1,x1,y1; CLUI_SizingGetWindowRect(pcli->hwndContactList,&wnd); rcPaint=Frame->wndSize; { int dx,dy,bx,by; if (g_CluiData.mutexOnEdgeSizing) { dx=rcPaint.left-wnd.left; dy=rcPaint.top-wnd.top; bx=rcPaint.right-wnd.right; by=rcPaint.bottom-wnd.bottom; wnd=g_rcEdgeSizingRect; rcPaint.left=wnd.left+dx; rcPaint.top=wnd.top+dy; rcPaint.right=wnd.right+bx; rcPaint.bottom=wnd.bottom+by; } } //OffsetRect(&rcPaint,-wnd.left,-wnd.top); w=rcPaint.right-rcPaint.left; h=rcPaint.bottom-rcPaint.top; if (w<=0 || h<=0) { TRACE("Frame size smaller than 0\n"); return 0; } x=rcPaint.left; y=rcPaint.top; hdc=CreateCompatibleDC(g_pCachedWindow->hImageDC); n=ske_CreateDIB32(w,h); o=(HBITMAP)SelectObject(hdc,n); { if (Frame->UpdateRgn && !SkipBkgBlitting) { GetRgnBox(Frame->UpdateRgn,&ru); { RECT rc; GetClientRect(Frame->hWnd,&rc); if (ru.top<0) ru.top=0; if (ru.left<0) ru.left=0; if (ru.right>rc.right) ru.right=rc.right; if (ru.bottom>rc.bottom) ru.bottom=rc.bottom; } if (!IsRectEmpty(&ru)) { x1=ru.left; y1=ru.top; w1=ru.right-ru.left; h1=ru.bottom-ru.top; } else {x1=0; y1=0; w1=w; h1=h;} // copy image at hdc if (SkipBkgBlitting) //image already at foreground { BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hImageDC,x+x1,y+y1,SRCCOPY); } else { BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hBackDC,x+x1,y+y1,SRCCOPY); } Frame->PaintCallbackProc(Frame->hWnd,hdc,&ru,Frame->UpdateRgn, Frame->dwFlags,Frame->PaintData); } else { HRGN rgnUpdate; RECT r; GetClientRect(Frame->hWnd,&r); rgnUpdate=CreateRectRgn(r.left,r.top,r.right,r.bottom); ru=r; if (!IsRectEmpty(&ru)) { x1=ru.left; y1=ru.top; w1=ru.right-ru.left; h1=ru.bottom-ru.top; } else {x1=0; y1=0; w1=w; h1=h;} // copy image at hdc if (SkipBkgBlitting) //image already at foreground { BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hImageDC,x+x1,y+y1,SRCCOPY); } else { BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hBackDC,x+x1,y+y1,SRCCOPY); } Frame->PaintCallbackProc(Frame->hWnd,hdc,&r,rgnUpdate, Frame->dwFlags,Frame->PaintData); ru=r; DeleteObject(rgnUpdate); } DeleteObject(Frame->UpdateRgn); Frame->UpdateRgn=0; } if (!IsRectEmpty(&ru)) { x1=ru.left; y1=ru.top; w1=ru.right-ru.left; h1=ru.bottom-ru.top; } else {x1=0; y1=0; w1=w; h1=h;} /* if (!SkipBkgBlitting) { BitBlt(g_pCachedWindow->hImageDC,x+x1,y+y1,w1,h1,g_pCachedWindow->hBackDC,x+x1,y+y1,SRCCOPY); } */ { //BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; BitBlt(g_pCachedWindow->hImageDC,x+x1,y+y1,w1,h1,hdc,x1,y1,SRCCOPY); //BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; //MyAlphaBlend(g_pCachedWindow->hImageDC,x+x1,y+y1,w1,h1,hdc,x1,y1,w1,h1,bf); } if ( fnGetScrollBarInfo && (GetWindowLongPtr(Frame->hWnd,GWL_STYLE) & WS_VSCROLL)) { //Draw vertical scroll bar // RECT rThumb; RECT rUpBtn; RECT rDnBtn; RECT rLine; int dx,dy; SCROLLBARINFO si={0}; si.cbSize=sizeof(SCROLLBARINFO); fnGetScrollBarInfo(Frame->hWnd,OBJID_VSCROLL,&si); rLine=(si.rcScrollBar); rUpBtn=rLine; rDnBtn=rLine; rThumb=rLine; rUpBtn.bottom=rUpBtn.top+si.dxyLineButton; rDnBtn.top=rDnBtn.bottom-si.dxyLineButton; rThumb.top=rLine.top+si.xyThumbTop; rThumb.bottom=rLine.top+si.xyThumbBottom; { dx=Frame->wndSize.right-rLine.right; dy=-rLine.top+Frame->wndSize.top; } OffsetRect(&rLine,dx,dy); OffsetRect(&rUpBtn,dx,dy); OffsetRect(&rDnBtn,dx,dy); OffsetRect(&rThumb,dx,dy); BitBlt(g_pCachedWindow->hImageDC,rLine.left,rLine.top,rLine.right-rLine.left,rLine.bottom-rLine.top,g_pCachedWindow->hBackDC,rLine.left,rLine.top,SRCCOPY); { char req[255]; _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=Back",Frame->szName); SkinDrawGlyph(g_pCachedWindow->hImageDC,&rLine,&rLine,req); _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=Thumb",Frame->szName); SkinDrawGlyph(g_pCachedWindow->hImageDC,&rThumb,&rThumb,req); _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=UpLineButton",Frame->szName); SkinDrawGlyph(g_pCachedWindow->hImageDC,&rUpBtn,&rUpBtn,req); _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=DownLineButton",Frame->szName); SkinDrawGlyph(g_pCachedWindow->hImageDC,&rDnBtn,&rDnBtn,req); } } SelectObject(hdc,o); DeleteObject(n); mod_DeleteDC(hdc); } return 1; } int ske_BltBackImage (HWND destHWND, HDC destDC, RECT * BltClientRect) { POINT ptMainWnd={0}; POINT ptChildWnd={0}; RECT from={0}; RECT w={0}; if (g_CluiData.fDisableSkinEngine) { FillRect(destDC,BltClientRect,GetSysColorBrush(COLOR_3DFACE)); return 0; } ske_ReCreateBackImage(FALSE,NULL); if (BltClientRect) w=*BltClientRect; else GetClientRect(destHWND,&w); ptChildWnd.x=w.left; ptChildWnd.y=w.top; ClientToScreen(destHWND,&ptChildWnd); ClientToScreen(pcli->hwndContactList,&ptMainWnd); //TODO if main not relative to client area return BitBlt(destDC,w.left,w.top,(w.right-w.left),(w.bottom-w.top),g_pCachedWindow->hBackDC,(ptChildWnd.x-ptMainWnd.x),(ptChildWnd.y-ptMainWnd.y),SRCCOPY); } int ske_ReCreateBackImage(BOOL Erase,RECT *w) { HBITMAP hb2; RECT wnd={0}; BOOL IsNewCache=0; if (g_CluiData.fDisableSkinEngine) return 0; GetClientRect(pcli->hwndContactList,&wnd); if (w) wnd=*w; //-- Check cached. if (g_pCachedWindow==NULL) { //-- Create New Cache { g_pCachedWindow=(CURRWNDIMAGEDATA*)mir_calloc(sizeof(CURRWNDIMAGEDATA)); g_pCachedWindow->hScreenDC=GetDC(NULL); g_pCachedWindow->hBackDC=CreateCompatibleDC(g_pCachedWindow->hScreenDC); g_pCachedWindow->hImageDC=CreateCompatibleDC(g_pCachedWindow->hScreenDC); g_pCachedWindow->Width=wnd.right-wnd.left; g_pCachedWindow->Height=wnd.bottom-wnd.top; if (g_pCachedWindow->Width!=0 && g_pCachedWindow->Height!=0) { g_pCachedWindow->hImageDIB=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte)); g_pCachedWindow->hBackDIB=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte)); g_pCachedWindow->hImageOld=(HBITMAP)SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageDIB); g_pCachedWindow->hBackOld=(HBITMAP)SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackDIB); } } IsNewCache=1; } if (g_pCachedWindow->Width!=wnd.right-wnd.left || g_pCachedWindow->Height!=wnd.bottom-wnd.top) { HBITMAP hb1=NULL,hb2=NULL; g_pCachedWindow->Width=wnd.right-wnd.left; g_pCachedWindow->Height=wnd.bottom-wnd.top; if (g_pCachedWindow->Width!=0 && g_pCachedWindow->Height!=0) { hb1=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte)); hb2=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte)); SelectObject(g_pCachedWindow->hImageDC,hb1); SelectObject(g_pCachedWindow->hBackDC,hb2); } else { SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageOld); SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackOld); } if (g_pCachedWindow->hImageDIB) DeleteObject(g_pCachedWindow->hImageDIB); if (g_pCachedWindow->hBackDIB) DeleteObject(g_pCachedWindow->hBackDIB); g_pCachedWindow->hImageDIB=hb1; g_pCachedWindow->hBackDIB=hb2; IsNewCache=1; } if ((Erase || IsNewCache )&& (g_pCachedWindow->Width!=0 && g_pCachedWindow->Height!=0)) { hb2=ske_CreateDIB32(g_pCachedWindow->Width,g_pCachedWindow->Height); SelectObject(g_pCachedWindow->hBackDC,hb2); DeleteObject(g_pCachedWindow->hBackDIB); g_pCachedWindow->hBackDIB=hb2; FillRect(g_pCachedWindow->hBackDC,&wnd,GetSysColorBrush(COLOR_BTNFACE)); SkinDrawGlyph(g_pCachedWindow->hBackDC,&wnd,&wnd,"Main,ID=Background,Opt=Non-Layered"); ske_SetRectOpaque(g_pCachedWindow->hBackDC,&wnd); } return 1; } int ske_DrawNonFramedObjects(BOOL Erase,RECT *r) { RECT w,wnd; if (r) w=*r; else CLUI_SizingGetWindowRect(pcli->hwndContactList,&w); if (!g_CluiData.fLayered) return ske_ReCreateBackImage(FALSE,0); if (g_pCachedWindow==NULL) return ske_ValidateFrameImageProc(&w); wnd=w; OffsetRect(&w, -w.left, -w.top); if (Erase) { HBITMAP hb2; hb2=ske_CreateDIB32(g_pCachedWindow->Width,g_pCachedWindow->Height); SelectObject(g_pCachedWindow->hBackDC,hb2); DeleteObject(g_pCachedWindow->hBackDIB); g_pCachedWindow->hBackDIB=hb2; } SkinDrawGlyph(g_pCachedWindow->hBackDC,&w,&w,"Main,ID=Background"); //--Draw frames captions { int i; for(i=0;ihBackDC, &rc, g_pfwFrames[i].id ); } } g_mutex_bLockUpdating=1; flag_bJustDrawNonFramedObjects=1; return 0; } int ske_ValidateFrameImageProc(RECT * r) // Calling queued frame paint procs and refresh image { RECT wnd={0}; BOOL IsNewCache=0; BOOL IsForceAllPainting=0; if (r) wnd=*r; else GetWindowRect(pcli->hwndContactList,&wnd); if (wnd.right-wnd.left==0 || wnd.bottom-wnd.top==0) return 0; g_mutex_bLockUpdating=1; //-- Check cached. if (g_pCachedWindow==NULL) { //-- Create New Cache { g_pCachedWindow=(CURRWNDIMAGEDATA*)mir_calloc(sizeof(CURRWNDIMAGEDATA)); g_pCachedWindow->hScreenDC=GetDC(NULL); g_pCachedWindow->hBackDC=CreateCompatibleDC(g_pCachedWindow->hScreenDC); g_pCachedWindow->hImageDC=CreateCompatibleDC(g_pCachedWindow->hScreenDC); g_pCachedWindow->Width=wnd.right-wnd.left; g_pCachedWindow->Height=wnd.bottom-wnd.top; g_pCachedWindow->hImageDIB=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte)); g_pCachedWindow->hBackDIB=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte)); g_pCachedWindow->hImageOld=(HBITMAP)SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageDIB); g_pCachedWindow->hBackOld=(HBITMAP)SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackDIB); } IsNewCache=1; } if (g_pCachedWindow->Width!=wnd.right-wnd.left || g_pCachedWindow->Height!=wnd.bottom-wnd.top) { HBITMAP hb1,hb2; g_pCachedWindow->Width=wnd.right-wnd.left; g_pCachedWindow->Height=wnd.bottom-wnd.top; hb1=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte)); hb2=ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte)); SelectObject(g_pCachedWindow->hImageDC,hb1); SelectObject(g_pCachedWindow->hBackDC,hb2); DeleteObject(g_pCachedWindow->hImageDIB); DeleteObject(g_pCachedWindow->hBackDIB); g_pCachedWindow->hImageDIB=hb1; g_pCachedWindow->hBackDIB=hb2; IsNewCache=1; } if (IsNewCache) { ske_DrawNonFramedObjects(0,&wnd); IsForceAllPainting=1; } if (flag_bJustDrawNonFramedObjects) { IsForceAllPainting=1; flag_bJustDrawNonFramedObjects=0; } if (IsForceAllPainting) { BitBlt(g_pCachedWindow->hImageDC,0,0,g_pCachedWindow->Width,g_pCachedWindow->Height,g_pCachedWindow->hBackDC,0,0,SRCCOPY); Sync( QueueAllFramesUpdating, (BYTE)1 ); } //-- Validating frames { int i; for(i=0;ihwndContactList,&r); return ske_UpdateWindowImageRect(&r); } else ske_ReCreateBackImage(FALSE,0); ske_ApplyTransluency(); return 0; } int ske_UpdateWindowImageRect(RECT * r) // Update window with current image and { //if not validity -> ValidateImageProc //else Update using current alpha RECT wnd=*r; if (!g_CluiData.fLayered) return ske_ReCreateBackImage(FALSE,0); if (g_pCachedWindow==NULL) return ske_ValidateFrameImageProc(&wnd); if (g_pCachedWindow->Width!=wnd.right-wnd.left || g_pCachedWindow->Height!=wnd.bottom-wnd.top) return ske_ValidateFrameImageProc(&wnd); if (g_flag_bFullRepaint) { g_flag_bFullRepaint=0; return ske_ValidateFrameImageProc(&wnd); } ske_JustUpdateWindowImageRect(&wnd); return 0; } void ske_ApplyTransluency() { int IsTransparancy; HWND hwnd=pcli->hwndContactList; BOOL layered=(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED)?TRUE:FALSE; IsTransparancy=g_CluiData.fSmoothAnimation || g_bTransparentFlag; if (!g_bTransparentFlag && !g_CluiData.fSmoothAnimation && g_CluiData.bCurrentAlpha!=0) g_CluiData.bCurrentAlpha=255; if (!g_CluiData.fLayered && (/*(g_CluiData.bCurrentAlpha==255)||*/(g_proc_SetLayeredWindowAttributesNew && IsTransparancy))) { if (!layered) SetWindowLongPtr(hwnd, GWL_EXSTYLE, GetWindowLongPtr(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); if (g_proc_SetLayeredWindowAttributesNew) g_proc_SetLayeredWindowAttributesNew(hwnd, RGB(0,0,0), (BYTE)g_CluiData.bCurrentAlpha, LWA_ALPHA); } AniAva_RedrawAllAvatars(FALSE); return; } int ske_JustUpdateWindowImage() { RECT r; if (!g_CluiData.fLayered) { ske_ApplyTransluency(); return 0; } GetWindowRect(pcli->hwndContactList,&r); return ske_JustUpdateWindowImageRect(&r); } int ske_JustUpdateWindowImageRect(RECT * rty) //Update window image { BLENDFUNCTION bf={AC_SRC_OVER, 0,g_CluiData.bCurrentAlpha, AC_SRC_ALPHA }; POINT dest={0}, src={0}; int res; RECT wnd=*rty; RECT rect; SIZE sz={0}; if (!g_CluiData.fLayered) { ske_ApplyTransluency(); return 0; } if (!pcli->hwndContactList) return 0; rect=wnd; dest.x=rect.left; dest.y=rect.top; sz.cx=rect.right-rect.left; sz.cy=rect.bottom-rect.top; if (g_proc_UpdateLayeredWindow && g_CluiData.fLayered) { if (!(GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE)&WS_EX_LAYERED)) SetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) |WS_EX_LAYERED); Sync( SetAlpha, g_CluiData.bCurrentAlpha ); res=g_proc_UpdateLayeredWindow(pcli->hwndContactList,g_pCachedWindow->hScreenDC,&dest,&sz,g_pCachedWindow->hImageDC,&src,RGB(1,1,1),&bf,ULW_ALPHA); g_CluiData.fAeroGlass = false; CLUI_UpdateAeroGlass(); } else InvalidateRect(pcli->hwndContactList,NULL,TRUE); return 0; } int ske_DrawImageAt(HDC hdc, RECT *rc) { BLENDFUNCTION bf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; BitBlt(g_pCachedWindow->hImageDC,rc->left,rc->top,rc->right-rc->left,rc->bottom-rc->top,g_pCachedWindow->hBackDC,rc->left,rc->top,SRCCOPY); ske_AlphaBlend(g_pCachedWindow->hImageDC,rc->left,rc->top,rc->right-rc->left,rc->bottom-rc->top,hdc,0,0,rc->right-rc->left,rc->bottom-rc->top,bf); if (!g_mutex_bLockUpdating) ske_UpdateWindowImage(); return 0; } HBITMAP ske_GetCurrentWindowImage() { return g_pCachedWindow->hImageDIB; } /* * Glyph text routine */ static DWORD ske_HexToARGB(char * Hex) { char buf[10]={0}; char buf2[11]={0}; char * st; BYTE alpha; DWORD AARRGGBB=0; _snprintf(buf,10,"%s\n",Hex); if (buf[1]=='x' || buf[1]=='X') _snprintf(buf2,11,"0x%s\n",buf+2); else _snprintf(buf2,11,"0x%s\n",buf); buf2[10]='\0'; AARRGGBB=strtoul(buf2,&st,16); alpha=(BYTE)((AARRGGBB&0xFF000000)>>24); alpha=255-((alpha==0)?255:alpha); AARRGGBB=(alpha<<24)+((AARRGGBB&0x00FF0000)>>16)+((AARRGGBB&0x000000FF)<<16)+(AARRGGBB&0x0000FF00); return AARRGGBB; } static TCHAR *ske_ReAppend(TCHAR *lfirst, TCHAR * lsecond, int len) { int l1=lfirst?lstrlen(lfirst):0; int l2=(len?len:(lstrlen(lsecond)+1)); TCHAR *buf=(TCHAR *)mir_alloc((l1+l2+1)*sizeof(TCHAR)); if (lfirst) memmove(buf,lfirst,l1*sizeof(TCHAR)); memmove(buf+l1,lsecond,l2*sizeof(TCHAR)); if (lfirst) mir_free(lfirst); if (len) buf[l1+l2]=_T('\0'); return buf; } TCHAR* ske_ReplaceVar(TCHAR *var) { if (!var) return mir_tstrdup(_T("")); if (!lstrcmpi(var,TEXT("Profile"))) { char buf[MAX_PATH]={0}; CallService(MS_DB_GETPROFILENAME,(WPARAM)MAX_PATH,(LPARAM)buf); { int i=strlen(buf); while (buf[i]!='.' && i>0) i--; buf[i]='\0'; } mir_free_and_nill(var); return mir_a2u(buf); } mir_free_and_nill(var); return mir_tstrdup(_T("")); } TCHAR *ske_ParseText(TCHAR *stzText) { int len=lstrlen(stzText); TCHAR *result=NULL; int stpos=0; int curpos=0; while(curpos0) result=ske_ReAppend(result,stzText+stpos,curpos-stpos); stpos=curpos+1; curpos++; //3 find second % while(curpos0) { TCHAR *var=(TCHAR *)mir_alloc((curpos-stpos+1)*sizeof(TCHAR)); memmove(var,stzText+stpos,(curpos-stpos)*sizeof(TCHAR)); var[curpos-stpos]=(TCHAR)'\0'; var=ske_ReplaceVar(var); result=ske_ReAppend(result,var,0); mir_free_and_nill(var); } else result=ske_ReAppend(result,_T("%"),0); curpos++; stpos=curpos; } else { // if (curpos-stpos>0) // result=ske_ReAppend(result,stzText+stpos,curpos-stpos); break; } } else { if (curpos-stpos>0) result=ske_ReAppend(result,stzText+stpos,curpos-stpos); break; } } return result; } /* * Parse text object string, find glyph object and add text to it. * szGlyphTextID and Define string is: * t[szGlyphTextID]=s[HostObjectID],[Left],[Top],[Right],[Bottom],[LTRBHV],[FontID],[Color1],[reservedforColor2],[Text] */ static void OLDske_AddParseTextGlyphObject(char * szGlyphTextID,char * szDefineString,SKINOBJECTSLIST *Skin) { GLYPHOBJECT *globj=NULL; { char buf[255]={0}; GetParamN(szDefineString,buf,sizeof(buf),0,',',TRUE); if (strlen(buf)) { SKINOBJECTDESCRIPTOR * lpobj; lpobj=ske_FindObjectByName(buf,OT_GLYPHOBJECT,Skin); if (lpobj) globj=(GLYPHOBJECT*)lpobj->Data; } if (globj) { GLYPHTEXT * glText; if (!globj->plTextList) { globj->plTextList=List_Create(0,1); globj->plTextList->sortFunc=ske_SortTextGlyphObjectFunc; } glText=(GLYPHTEXT*)mir_calloc(sizeof(GLYPHTEXT)); glText->szGlyphTextID=mir_strdup(szGlyphTextID); glText->szObjectName=mir_strdup(buf); glText->iLeft=atoi(GetParamN(szDefineString,buf,sizeof(buf),1,',',TRUE)); glText->iTop=atoi(GetParamN(szDefineString,buf,sizeof(buf),2,',',TRUE)); glText->iRight=atoi(GetParamN(szDefineString,buf,sizeof(buf),3,',',TRUE)); glText->iBottom=atoi(GetParamN(szDefineString,buf,sizeof(buf),4,',',TRUE)); { memset(buf,0,6); GetParamN(szDefineString,buf,sizeof(buf),5,',',TRUE); buf[0]&=95; buf[1]&=95; buf[2]&=95; buf[3]&=95; buf[4]&=95; buf[5]&=95; //to uppercase: &01011111 (0-95) glText->RelativeFlags= (buf[0]=='C'?1:((buf[0]=='R')?2:0)) //[BC][RC][BC][RC] --- Left relative |(buf[1]=='C'?4:((buf[1]=='B')?8:0)) // | | |--------- Top relative |(buf[2]=='C'?16:((buf[2]=='R')?32:0)) // | |--------------Right relative |(buf[3]=='C'?64:((buf[3]=='B')?128:0)); // |------------------Bottom relative glText->dwFlags=(buf[4]=='C'?DT_CENTER:((buf[4]=='R')?DT_RIGHT:DT_LEFT)) |(buf[5]=='C'?DT_VCENTER:((buf[5]=='B')?DT_BOTTOM:DT_TOP)); } glText->szFontID=mir_strdup(GetParamN(szDefineString,buf,sizeof(buf),6,',',TRUE)); glText->dwColor=ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),7,',',TRUE)); glText->dwShadow=ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),8,',',TRUE)); glText->stValueText=mir_a2u(GetParamN(szDefineString,buf,sizeof(buf),9,',',TRUE)); glText->stText=ske_ParseText(glText->stValueText); List_Insert(globj->plTextList,(void*)glText,globj->plTextList->realCount); qsort(globj->plTextList->items,globj->plTextList->realCount,sizeof(void*),(int(*)(const void*, const void*))globj->plTextList->sortFunc); } } } static void ske_AddParseTextGlyphObject(char * szGlyphTextID,char * szDefineString,SKINOBJECTSLIST *Skin) { char buf[255]={0}; GetParamN(szDefineString,buf,sizeof(buf),0,',',TRUE); if (strlen(buf)) { GLYPHTEXT * glText; glText=(GLYPHTEXT*)mir_calloc(sizeof(GLYPHTEXT)); glText->szGlyphTextID=mir_strdup(szGlyphTextID); glText->szObjectName=mir_strdup(buf); glText->iLeft=atoi(GetParamN(szDefineString,buf,sizeof(buf),1,',',TRUE)); glText->iTop=atoi(GetParamN(szDefineString,buf,sizeof(buf),2,',',TRUE)); glText->iRight=atoi(GetParamN(szDefineString,buf,sizeof(buf),3,',',TRUE)); glText->iBottom=atoi(GetParamN(szDefineString,buf,sizeof(buf),4,',',TRUE)); { memset(buf,0,6); GetParamN(szDefineString,buf,sizeof(buf),5,',',TRUE); buf[0]&=95; buf[1]&=95; buf[2]&=95; buf[3]&=95; buf[4]&=95; buf[5]&=95; //to uppercase: &01011111 (0-95) glText->RelativeFlags= (buf[0]=='C'?1:((buf[0]=='R')?2:0)) //[BC][RC][BC][RC] --- Left relative |(buf[1]=='C'?4:((buf[1]=='B')?8:0)) // | | |--------- Top relative |(buf[2]=='C'?16:((buf[2]=='R')?32:0)) // | |--------------Right relative |(buf[3]=='C'?64:((buf[3]=='B')?128:0)); // |------------------Bottom relative glText->dwFlags=(buf[4]=='C'?DT_CENTER:((buf[4]=='R')?DT_RIGHT:DT_LEFT)) |(buf[5]=='C'?DT_VCENTER:((buf[5]=='B')?DT_BOTTOM:DT_TOP)); } glText->szFontID=mir_strdup(GetParamN(szDefineString,buf,sizeof(buf),6,',',TRUE)); glText->dwColor=ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),7,',',TRUE)); glText->dwShadow=ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),8,',',TRUE)); glText->stValueText=mir_a2u(GetParamN(szDefineString,buf,sizeof(buf),9,',',TRUE)); glText->stText=ske_ParseText(glText->stValueText); if (!Skin->pTextList) Skin->pTextList=List_Create(0,1); List_InsertPtr(Skin->pTextList,glText); } } /* * Parse font definition string. * szGlyphTextID and Define string is: * f[szFontID]=s[FontTypefaceName],[size],[BIU] */ static void ske_AddParseSkinFont(char * szFontID,char * szDefineString,SKINOBJECTSLIST *Skin) { //SortedList * gl_plSkinFonts=NULL; SKINFONT * sf =NULL; sf=(SKINFONT*)mir_calloc(sizeof(SKINFONT)); if (sf) { { char buf[255]; int fntSize=0; BOOL fntBold=FALSE, fntItalic=FALSE, fntUnderline=FALSE; LOGFONTA logfont={0}; logfont.lfCharSet=DEFAULT_CHARSET; logfont.lfOutPrecision=OUT_DEFAULT_PRECIS; logfont.lfClipPrecision=CLIP_DEFAULT_PRECIS; logfont.lfQuality=DEFAULT_QUALITY; logfont.lfPitchAndFamily=DEFAULT_PITCH|FF_DONTCARE; strncpy(logfont.lfFaceName,GetParamN(szDefineString,buf,sizeof(buf),0,',',TRUE),32); logfont.lfHeight=atoi(GetParamN(szDefineString,buf,sizeof(buf),1,',',TRUE)); if (logfont.lfHeight<0) { HDC hdc=CreateCompatibleDC(NULL); logfont.lfHeight=(long)-MulDiv(logfont.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72); mod_DeleteDC(hdc); } logfont.lfHeight=-logfont.lfHeight; GetParamN(szDefineString,buf,sizeof(buf),2,',',TRUE); buf[0]&=95; buf[1]&=95; buf[2]&=95; logfont.lfWeight=(buf[0]=='B')?FW_BOLD:FW_NORMAL; logfont.lfItalic=(buf[1]=='I')?1:0; logfont.lfUnderline=(buf[2]=='U')?1:0; sf->hFont=CreateFontIndirectA(&logfont); if (sf->hFont) { sf->szFontID=mir_strdup(szFontID); if (!gl_plSkinFonts) gl_plSkinFonts=List_Create(0,1); if (gl_plSkinFonts) { List_Insert(gl_plSkinFonts,(void*)sf,gl_plSkinFonts->realCount); } } } } } /* HICON ske_CreateJoinedIcon_Old(HICON hBottom, HICON hTop,BYTE alpha) { HDC tempDC; HICON res=NULL; HBITMAP oImage,nImage; HBITMAP nMask; ICONINFO iNew={0}; ICONINFO iciBottom={0}; ICONINFO iciTop={0}; BITMAP bmp={0}; SIZE sz={0}; { if (!GetIconInfo(hBottom,&iciBottom)) return NULL; GetObject(iciBottom.hbmColor,sizeof(BITMAP),&bmp); sz.cx=bmp.bmWidth; sz.cy=bmp.bmHeight; if(iciBottom.hbmColor) DeleteObject(iciBottom.hbmColor); if(iciBottom.hbmMask) DeleteObject(iciBottom.hbmMask); } if (sz.cx==0 || sz.cy==0) return NULL; tempDC=CreateCompatibleDC(NULL); nImage=ske_CreateDIB32(sz.cx,sz.cy); oImage=SelectObject(tempDC,nImage); ske_DrawIconEx(tempDC,0,0,hBottom,sz.cx,sz.cy,0,NULL,DI_NORMAL); ske_DrawIconEx(tempDC,0,0,hTop,sz.cx,sz.cy,0,NULL,DI_NORMAL|(alpha<<24)); SelectObject(tempDC,oImage); DeleteDC(tempDC); { BYTE * p=malloc(sz.cx*sz.cy/8+10); nMask=CreateBitmap(sz.cx,sz.cy,1,1,(void*)p); iNew.fIcon=TRUE; iNew.hbmColor=nImage; iNew.hbmMask=nMask; res=CreateIconIndirect(&iNew); if (!res) TRACE_ERROR(); DeleteObject(nImage); DeleteObject(nMask); free(p); } return res; } */ /* * ske_CheckHasAlfaChannel - checks if image has at least one BYTE in alpha chennel * that is not a 0. (is image real 32 bit or just 24 bit) */ static BOOL ske_CheckHasAlfaChannel(BYTE * from, int widthByte, int height) { int i=0,j=0; DWORD * pt=(DWORD*)from; while (j>3)))&(0x01<<(7-(x&0x07))))!=0; } /* * ske_Blend - alpha ske_Blend ARGB values of 2 pixels. X1 - underlaying, * X2 - overlaying points. */ static DWORD ske_Blend(DWORD X1,DWORD X2, BYTE alpha) { BYTE a1=(BYTE)(X1>>24); BYTE a2=(BYTE)(((X2>>24)*alpha)>>8); BYTE r1=(BYTE)(X1>>16); BYTE r2=(BYTE)(X2>>16); BYTE g1=(BYTE)(X1>>8); BYTE g2=(BYTE)(X2>>8); BYTE b1=(BYTE)(X1); BYTE b2=(BYTE)(X2); BYTE a_1=~a1; BYTE a_2=~a2; WORD am=(WORD)a1*a_2; /* it is possible to use >>8 instead of /255 but it is require additional * checking of alphavalues */ WORD ar=a1+(((WORD)a_1*a2)/255); // if a2 more than 0 than result should be more // or equal (if a1==0) to a2, else in combination // with mask we can get here black points ar=(a2>ar)?a2:ar; if (ar==0) return 0; //else { WORD arm=ar*255; WORD rr=(((WORD)r1*am+(WORD)r2*a2*255))/arm; WORD gr=(((WORD)g1*am+(WORD)g2*a2*255))/arm; WORD br=(((WORD)b1*am+(WORD)b2*a2*255))/arm; return (ar<<24)|(rr<<16)|(gr<<8)|br; } } /* * CreateJoinedIcon - creates new icon by drawing hTop over hBottom. */ HICON ske_CreateJoinedIcon(HICON hBottom, HICON hTop, BYTE alpha) { HDC tempDC; HICON res=NULL; HBITMAP oImage,nImage; HBITMAP nMask; BITMAP bmp={0}; BYTE *ptPixels; ICONINFO iNew={0}; ICONINFO iciBottom={0}; ICONINFO iciTop={0}; BITMAP bmp_top={0}; BITMAP bmp_top_mask={0}; BITMAP bmp_bottom={0}; BITMAP bmp_bottom_mask={0}; tempDC=CreateCompatibleDC(NULL); nImage=ske_CreateDIB32Point(16,16,(void**)&ptPixels); oImage=(HBITMAP)SelectObject(tempDC,nImage); GetIconInfo(hBottom,&iciBottom); GetObject(iciBottom.hbmColor,sizeof(BITMAP),&bmp_bottom); GetObject(iciBottom.hbmMask,sizeof(BITMAP),&bmp_bottom_mask); GetIconInfo(hTop,&iciTop); GetObject(iciTop.hbmColor,sizeof(BITMAP),&bmp_top); GetObject(iciTop.hbmMask,sizeof(BITMAP),&bmp_top_mask); if (bmp_bottom.bmBitsPixel==32 &&bmp_top.bmBitsPixel==32 && IsWinVerXPPlus()) { BYTE * BottomBuffer, * TopBuffer, * BottomMaskBuffer, * TopMaskBuffer; BYTE * bb, * tb, * bmb, * tmb; BYTE * db=ptPixels; int vstep_d=16*4; int vstep_b=bmp_bottom.bmWidthBytes; int vstep_t=bmp_top.bmWidthBytes; int vstep_bm=bmp_bottom_mask.bmWidthBytes; int vstep_tm=bmp_top_mask.bmWidthBytes; alpha=alpha?alpha:255; if (bmp_bottom.bmBits) bb=BottomBuffer=(BYTE*)bmp_bottom.bmBits; else { BottomBuffer=(BYTE*)malloc(bmp_bottom.bmHeight*bmp_bottom.bmWidthBytes); GetBitmapBits(iciBottom.hbmColor,bmp_bottom.bmHeight*bmp_bottom.bmWidthBytes,BottomBuffer); bb=BottomBuffer+vstep_b*(bmp_bottom.bmHeight-1); vstep_b=-vstep_b; } if (bmp_top.bmBits) tb=TopBuffer=(BYTE*)bmp_top.bmBits; else { TopBuffer=(BYTE*)malloc(bmp_top.bmHeight*bmp_top.bmWidthBytes); GetBitmapBits(iciTop.hbmColor,bmp_top.bmHeight*bmp_top.bmWidthBytes,TopBuffer); tb=TopBuffer+vstep_t*(bmp_top.bmHeight-1); vstep_t=-vstep_t; } if (bmp_bottom_mask.bmBits) { BottomMaskBuffer=(BYTE*)bmp_bottom_mask.bmBits; bmb=BottomMaskBuffer; } else { BottomMaskBuffer=(BYTE*)malloc(bmp_bottom_mask.bmHeight*bmp_bottom_mask.bmWidthBytes); GetBitmapBits(iciBottom.hbmMask,bmp_bottom_mask.bmHeight*bmp_bottom_mask.bmWidthBytes,BottomMaskBuffer); bmb=BottomMaskBuffer+vstep_bm*(bmp_bottom_mask.bmHeight-1); vstep_bm=-vstep_bm; } if (bmp_top_mask.bmBits) { TopMaskBuffer=(BYTE*)bmp_top_mask.bmBits; tmb=TopMaskBuffer; } else { TopMaskBuffer=(BYTE*)malloc(bmp_top_mask.bmHeight*bmp_top_mask.bmWidthBytes); GetBitmapBits(iciTop.hbmMask,bmp_top_mask.bmHeight*bmp_top_mask.bmWidthBytes,TopMaskBuffer); tmb=TopMaskBuffer+vstep_tm*(bmp_top_mask.bmHeight-1); vstep_tm=-vstep_tm; } { int x=0; int y=0; BOOL topHasAlpha=ske_CheckHasAlfaChannel(TopBuffer,bmp_top.bmWidthBytes,bmp_top.bmHeight); BOOL bottomHasAlpha=ske_CheckHasAlfaChannel(BottomBuffer,bmp_bottom.bmWidthBytes,bmp_bottom.bmHeight); BOOL topHasMask=ske_CheckIconHasMask(TopMaskBuffer); BOOL bottomHasMask=ske_CheckIconHasMask(BottomMaskBuffer); for (y=0; y<16; y++) { for (x=0; x<16; x++) { BOOL mask_b=ske_GetMaskBit(bmb,x); BOOL mask_t=ske_GetMaskBit(tmb,x); DWORD bottom_d=((DWORD*)bb)[x]; DWORD top_d=((DWORD*)tb)[x]; if (topHasMask) { if (mask_t==1 && !topHasAlpha ) top_d&=0xFFFFFF; else if (!topHasAlpha) top_d|=0xFF000000; } if (bottomHasMask) { if (mask_b==1 && !bottomHasAlpha) bottom_d&=0xFFFFFF; else if (!bottomHasAlpha) bottom_d|=0xFF000000; } ((DWORD*)db)[x]=ske_Blend(bottom_d,top_d,alpha); } bb+=vstep_b; tb+=vstep_t; bmb+=vstep_bm; tmb+=vstep_tm; db+=vstep_d; } } if (!bmp_bottom.bmBits) free(BottomBuffer); if (!bmp_top.bmBits) free(TopBuffer); if (!bmp_bottom_mask.bmBits) free(BottomMaskBuffer); if (!bmp_top_mask.bmBits) free(TopMaskBuffer); } else { ske_DrawIconEx(tempDC,0,0,hBottom,16,16,0,NULL,DI_NORMAL); ske_DrawIconEx(tempDC,0,0,hTop,16,16,0,NULL,DI_NORMAL|(alpha<<24)); } DeleteObject(iciBottom.hbmColor); DeleteObject(iciTop.hbmColor); DeleteObject(iciBottom.hbmMask); DeleteObject(iciTop.hbmMask); SelectObject(tempDC,oImage); DeleteDC(tempDC); { //BYTE *p=malloc(32); //memset(p,0,32); BYTE p[32] = {0}; nMask=CreateBitmap(16,16,1,1,(void*)&p); { HDC tempDC2=CreateCompatibleDC(NULL); HDC tempDC3=CreateCompatibleDC(NULL); HBITMAP hbm=CreateCompatibleBitmap(tempDC3,16,16); HBITMAP obmp=(HBITMAP)SelectObject(tempDC2,nMask); HBITMAP obmp2=(HBITMAP)SelectObject(tempDC3,hbm); DrawIconEx(tempDC2,0,0,hBottom,16,16,0,NULL,DI_MASK); DrawIconEx(tempDC3,0,0,hTop,16,16,0,NULL,DI_MASK); BitBlt(tempDC2,0,0,16,16,tempDC3,0,0,SRCAND); SelectObject(tempDC2,obmp); SelectObject(tempDC3,obmp2); DeleteObject(hbm); DeleteDC(tempDC2); DeleteDC(tempDC3); } iNew.fIcon=TRUE; iNew.hbmColor=nImage; iNew.hbmMask=nMask; res=CreateIconIndirect(&iNew); DeleteObject(nImage); DeleteObject(nMask); } return res; } #define NEWJOINEDSTR( destination, first, separator, last) \ destination=(char*)alloca(strlen(first)+strlen(separator)+strlen(last)+1); \ if (destination) { \ *destination='\0'; \ strcat(destination,first); \ strcat(destination,separator); \ strcat(destination,last); \ } #define SKINSETSECTION "SkinnedSettings" BOOL SkinDBGetContactSetting(HANDLE hContact, const char* szSection, const char*szKey, DBVARIANT * retdbv, BOOL * bSkined ) { if (!hContact) { //only for not contact settings char * szSkinKey; NEWJOINEDSTR(szSkinKey,szSection,"@",szKey); if ( !ModernGetSetting(hContact, SKINSETSECTION, szSkinKey, retdbv)) { if (bSkined) *bSkined=TRUE; return FALSE; } } // not skinned if (bSkined) bSkined=FALSE; return ModernGetSetting(hContact, szSection, szKey, retdbv); } BYTE SkinDBGetContactSettingByte(HANDLE hContact, const char* szSection, const char*szKey, BYTE bDefault) { DBVARIANT dbv={0}; BOOL bSkined=FALSE; if ( !SkinDBGetContactSetting(hContact, szSection, szKey, &dbv, &bSkined)) { if (dbv.type==DBVT_BYTE) { BYTE retVal=dbv.bVal; ModernDBFreeVariant(&dbv); return retVal; } else { ModernDBFreeVariant(&dbv); if (!bSkined) return ModernGetSettingByte(hContact, szSection, szKey, bDefault); } } return bDefault; } WORD SkinDBGetContactSettingWord(HANDLE hContact, const char* szSection, const char*szKey, WORD wDefault) { BOOL bSkined=FALSE; DBVARIANT dbv={0}; if ( !SkinDBGetContactSetting(hContact, szSection, szKey, &dbv, &bSkined)) { if (dbv.type==DBVT_WORD) { WORD retVal=dbv.wVal; ModernDBFreeVariant(&dbv); return retVal; } else { ModernDBFreeVariant(&dbv); if (!bSkined) return ModernGetSettingWord(hContact, szSection, szKey, wDefault); } } return wDefault; } DWORD SkinDBGetContactSettingDword(HANDLE hContact, const char* szSection, const char*szKey, DWORD dwDefault) { DBVARIANT dbv={0}; BOOL bSkined=FALSE; if ( !SkinDBGetContactSetting(hContact, szSection, szKey, &dbv, &bSkined)) { if (dbv.type==DBVT_DWORD) { DWORD retVal=dbv.dVal; ModernDBFreeVariant(&dbv); return retVal; } else { ModernDBFreeVariant(&dbv); if (!bSkined) return ModernGetSettingDword(hContact, szSection, szKey, dwDefault); } } return dwDefault; }