static void sttDrawNonLayeredSkinedBar(HWND hwnd, HDC hdc)
{
		HDC hdc2;
		HBITMAP hbmp,hbmpo;
		RECT rc={0};
		GetClientRect(hwnd,&rc);
		rc.right++;
		rc.bottom++;
		hdc2=CreateCompatibleDC(hdc);
		hbmp=ske_CreateDIB32(rc.right,rc.bottom);
		hbmpo=(HBITMAP)SelectObject(hdc2,hbmp);		
		if (GetParent(hwnd)!=pcli->hwndContactList)
		{
			HBRUSH br=GetSysColorBrush(COLOR_3DFACE);
			FillRect(hdc2,&rc,br);
		}
		else
			ske_BltBackImage(hwnd,hdc2,&rc);
		SendMessage(hwnd,MTBM_LAYEREDPAINT, (WPARAM)hdc2, 0);
		BitBlt(hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,
			hdc2,rc.left,rc.top,SRCCOPY);
		SelectObject(hdc2,hbmpo);
		DeleteObject(hbmp);
		mod_DeleteDC(hdc2);

		SelectObject(hdc,(HFONT)GetStockObject(DEFAULT_GUI_FONT));

		ValidateRect(hwnd,NULL);		        							
}
static int ModernSkinButtonPaintWorker(HWND hwnd, HDC whdc)
{
	HDC hdc;
	RECT rc;
	ModernSkinButtonCtrl* bct = (ModernSkinButtonCtrl *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
	if (!bct) return 0;
	if (!IsWindowVisible(hwnd)) return 0;
	if (!whdc && !g_CluiData.fLayered) InvalidateRect(hwnd, nullptr, FALSE);

	if (whdc && g_CluiData.fLayered) hdc = whdc;
	else {
		//sdc = GetWindowDC(GetParent(hwnd));
		hdc = CreateCompatibleDC(nullptr);
	}
	GetClientRect(hwnd, &rc);
	HBITMAP bmp = ske_CreateDIB32(rc.right, rc.bottom);
	HBITMAP oldbmp = (HBITMAP)SelectObject(hdc, bmp);
	if (!g_CluiData.fLayered)
		ske_BltBackImage(bct->hwnd, hdc, nullptr);
	{
		MODERNMASK Request = {};
		//   int res;
		//HBRUSH br = CreateSolidBrush(RGB(255,255,255));
		char * Value = nullptr;
		{
			if (bct->ValueDBSection && bct->ValueTypeDef) {
				char * key;
				char * section;
				DWORD defval = 0;
				char buf[20];
				key = mir_strdup(bct->ValueDBSection);
				section = key;
				if (bct->ValueTypeDef[0] != 's')
					defval = (DWORD)atol(bct->ValueTypeDef + 1);
				do {
					if (key[0] == '/') { key[0] = '\0'; key++; break; }
					key++;
				} while (key[0] != '\0');
				switch (bct->ValueTypeDef[0]) {
				case 's':
					{
						Value = db_get_sa(0, section, key);
						if (!Value)
							Value = mir_strdup(bct->ValueTypeDef + 1);
						break;
					}
				case 'd':
					defval = db_get_dw(0, section, key, defval);
					Value = mir_strdup(_ltoa(defval, buf, _countof(buf)));
					break;
				case 'w':
					defval = db_get_w(0, section, key, defval);
					Value = mir_strdup(_ltoa(defval, buf, _countof(buf)));
					break;
				case 'b':
					defval = db_get_b(0, section, key, defval);
					Value = mir_strdup(_ltoa(defval, buf, _countof(buf)));
					break;
				}
				mir_free(section);
			}

		}
		g_clcPainter.AddParam(&Request, mod_CalcHash("Module"), "MButton", 0);
		g_clcPainter.AddParam(&Request, mod_CalcHash("ID"), bct->ID, 0);
		g_clcPainter.AddParam(&Request, mod_CalcHash("Down"), bct->down ? "1" : "0", 0);
		g_clcPainter.AddParam(&Request, mod_CalcHash("Focused"), bct->focus ? "1" : "0", 0);
		g_clcPainter.AddParam(&Request, mod_CalcHash("Hovered"), bct->hover ? "1" : "0", 0);
		if (Value) {
			g_clcPainter.AddParam(&Request, mod_CalcHash("Value"), Value, 0);
			mir_free(Value);
		}
		SkinDrawGlyphMask(hdc, &rc, &rc, &Request);
		SkinSelector_DeleteMask(&Request);
	}

	if (!whdc && g_CluiData.fLayered) {
		RECT r;
		SetRect(&r, bct->Left, bct->Top, bct->Right, bct->Bottom);
		ske_DrawImageAt(hdc, &r);
		//CallingService to immeadeately update window with new image.
	}
	if (whdc && !g_CluiData.fLayered) {
		RECT r = { 0 };
		GetClientRect(bct->hwnd, &r);
		BitBlt(whdc, 0, 0, r.right, r.bottom, hdc, 0, 0, SRCCOPY);
	}
	SelectObject(hdc, oldbmp);
	DeleteObject(bmp);
	if (!whdc || !g_CluiData.fLayered) {
		SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
		DeleteDC(hdc);
	}
	//  if (sdc)
	//    ReleaseDC(GetParent(hwnd),sdc);
	return 0;
}
static LRESULT CALLBACK EventArea_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg) {
	case WM_MEASUREITEM:
		{
			MEASUREITEMSTRUCT *lpi = (LPMEASUREITEMSTRUCT) lParam;
			MENUITEMINFOA mii = {0};

			mii.cbSize = sizeof(mii);
			mii.fMask = MIIM_DATA | MIIM_ID;
			if (GetMenuItemInfoA(g_CluiData.hMenuNotify, lpi->itemID, FALSE, &mii) != 0) {
				if (mii.dwItemData == lpi->itemData) {
					lpi->itemWidth = 8 + 16;
					lpi->itemHeight = 0;
					return TRUE;
				}
			}
		}
		break;

	case WM_DRAWITEM:
		{
			LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam;
			if (dis->hwndItem == (HWND) g_CluiData.hMenuNotify) {
				NotifyMenuItemExData *nmi = 0;

				MENUITEMINFOA mii = {0};
				mii.cbSize = sizeof(mii);
				mii.fMask = MIIM_DATA;
				if (GetMenuItemInfoA(g_CluiData.hMenuNotify, (UINT) dis->itemID, FALSE, &mii) != 0) {
					nmi = (NotifyMenuItemExData *) mii.dwItemData;
					if (nmi) {
						int iIcon = cli_GetContactIcon(nmi->hContact);
						ske_ImageList_DrawEx(g_himlCListClc, nmi->iIcon, dis->hDC, 2, (dis->rcItem.bottom + dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
						ske_ImageList_DrawEx(g_himlCListClc, iIcon, dis->hDC, 2+GetSystemMetrics(SM_CXSMICON)+2, (dis->rcItem.bottom + dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
						return TRUE;
					}
				}
			}
			break;
		}
	case WM_LBUTTONUP:
		if (g_CluiData.bEventAreaEnabled)
			SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_NOTIFYBUTTON, 0), 0);
		break;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDC_NOTIFYBUTTON) {
			int iSelection;
			MENUITEMINFO mii = {0};
			POINT pt;
			struct NotifyMenuItemExData *nmi = 0;
			int iCount = GetMenuItemCount(g_CluiData.hMenuNotify);
			BOOL result;

			GetCursorPos(&pt);
			mii.cbSize = sizeof(mii);
			mii.fMask = MIIM_DATA;
			if (iCount > 1)
				iSelection = TrackPopupMenu(g_CluiData.hMenuNotify, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
			else
				iSelection = GetMenuItemID(g_CluiData.hMenuNotify, 0);
			result = GetMenuItemInfo(g_CluiData.hMenuNotify, (UINT) iSelection, FALSE, &mii);
			if (result != 0) {
				nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
				if (nmi) {
					CLISTEVENT *cle = MyGetEvent(iSelection);
					if (cle) {
						CLISTEVENT *cle1 = NULL;
						CallService(cle->pszService, (WPARAM) NULL, (LPARAM) cle);
						// re-obtain the pointer, it may already be invalid/point to another event if the
						// event we're interested in was removed by the service (nasty one...)
						cle1 = MyGetEvent(iSelection);
						if (cle1 != NULL)
							CallService(MS_CLIST_REMOVEEVENT, (WPARAM) cle->hContact, (LPARAM) cle->hDbEvent);
					}
				}
			}
			break;
		}
		break;

	case WM_SIZE:
		if (!g_CluiData.fLayered)
			InvalidateRect(hwnd,NULL,FALSE);
		return DefWindowProc(hwnd, msg, wParam, lParam);

	case WM_ERASEBKGND:
		return 1;

	case WM_PAINT:
		if (GetParent(hwnd) == pcli->hwndContactList && g_CluiData.fLayered)
			CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)hwnd,0);
		else if (GetParent(hwnd) == pcli->hwndContactList && !g_CluiData.fLayered) {
			HDC hdc, hdc2;
			HBITMAP hbmp,hbmpo;
			RECT rc = {0};
			GetClientRect(hwnd,&rc);
			rc.right++;
			rc.bottom++;
			hdc = GetDC(hwnd);
			hdc2 = CreateCompatibleDC(hdc);
			hbmp = ske_CreateDIB32(rc.right,rc.bottom);
			hbmpo = (HBITMAP)SelectObject(hdc2,hbmp);
			ske_BltBackImage(hwnd,hdc2,&rc);
			EventArea_DrawWorker(hwnd,hdc2);
			BitBlt(hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,
				hdc2,rc.left,rc.top,SRCCOPY);
			SelectObject(hdc2,hbmpo);
			DeleteObject(hbmp);
			DeleteDC(hdc2);
			SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
			ReleaseDC(hwnd,hdc);
			ValidateRect(hwnd,NULL);
		}
		else {
			HDC hdc, hdc2;
			HBITMAP hbmp, hbmpo;
			RECT rc;
			PAINTSTRUCT ps;
			HBRUSH br = GetSysColorBrush(COLOR_3DFACE);
			GetClientRect(hwnd,&rc);
			hdc = BeginPaint(hwnd,&ps);
			hdc2 = CreateCompatibleDC(hdc);
			hbmp = ske_CreateDIB32(rc.right,rc.bottom);
			hbmpo = (HBITMAP)SelectObject(hdc2,hbmp);
			FillRect(hdc2,&ps.rcPaint,br);
			EventArea_DrawWorker(hwnd,hdc2);
			BitBlt(hdc,ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top,
				hdc2,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
			SelectObject(hdc2,hbmpo);
			DeleteObject(hbmp);
			DeleteDC(hdc2);
			ps.fErase = FALSE;
			EndPaint(hwnd,&ps);
		}

	default:
		return DefWindowProc(hwnd, msg, wParam, lParam);
	}
	return TRUE;
}
static void _AniAva_RenderAvatar(ANIAVA_WINDOWINFO * dat, HDC hdcParent /* = NULL*/, RECT * rcInParent /* = NULL */ )
{
	if (dat->bPaused>0)	{	dat->bPended=TRUE;	return; 	}
	else dat->bPended=FALSE;
	
	if ( IMMEDIATE_DRAW && hdcParent == NULL ) return;
	GdiFlush();
#ifdef _DEBUG
	__AniAva_DebugRenderStrip();
#endif
	if (dat->bPlaying && IsWindowVisible(dat->hWindow))
	{
		POINT ptWnd={0};
		SIZE szWnd={dat->rcPos.right-dat->rcPos.left,dat->rcPos.bottom-dat->rcPos.top};
		BLENDFUNCTION bf={AC_SRC_OVER, 0,g_CluiData.bCurrentAlpha*dat->bAlpha/256, AC_SRC_ALPHA };
		POINT pt_from={0,0};
		HDC hDC_animation=GetDC(NULL);
		HDC copyFromDC;
		RECT clistRect;
		HDC tempDC=NULL;
		HBITMAP hBmp;
		HBITMAP hOldBmp;

		/*
		int x=bf.SourceConstantAlpha;
		x=(49152/(383-x))-129;
		x=min(x,255);	x=max(x,0);
		bf.SourceConstantAlpha=x;
		*/
		if ( AniAva.bFlags == 0 ) //simple and fastest method - no borders, round corners and etc. just copy
		{
			pt_from.x=dat->ptFromPoint.x+dat->currentFrame*dat->sizeAvatar.cx;
			pt_from.y=dat->ptFromPoint.y;
			copyFromDC=AniAva.hAniAvaDC;
		}
		else
		{
			// ... need to create additional hDC_animation
			HRGN hRgn=NULL;
			int cornerRadius= AniAva.cornerRadius;
			tempDC	= CreateCompatibleDC( NULL );
			hBmp	= ske_CreateDIB32( szWnd.cx, szWnd.cy );
			hOldBmp	= (HBITMAP)SelectObject(tempDC,hBmp);
			if ( AniAva.bFlags & AAO_ROUND_CORNERS )
			{
				if (!cornerRadius)  //auto radius
					cornerRadius = min(szWnd.cx, szWnd.cy )/5;
			}
			if ( AniAva.bFlags & AAO_HAS_BORDER )
			{
				// if has borders - create region (round corners) and fill it, remember internal as clipping
				HBRUSH hBrush = CreateSolidBrush( AniAva.borderColor );
				HBRUSH hOldBrush = (HBRUSH)SelectObject( tempDC, hBrush );
				HRGN rgnOutside = CreateRoundRectRgn( 0, 0, szWnd.cx+1, szWnd.cy+1, cornerRadius<<1, cornerRadius<<1);
				hRgn=CreateRoundRectRgn( 1, 1, szWnd.cx, szWnd.cy, cornerRadius<<1, cornerRadius<<1);
				CombineRgn( rgnOutside,rgnOutside,hRgn,RGN_DIFF);
				FillRgn( tempDC, rgnOutside, hBrush);
				ske_SetRgnOpaque( tempDC, rgnOutside, TRUE);
				SelectObject(tempDC, hOldBrush);
				DeleteObject(hBrush);
				DeleteObject(rgnOutside);
			} 
			else if ( cornerRadius > 0 )
			{
				// else create clipping area (round corners)
				hRgn=CreateRoundRectRgn(0, 0, szWnd.cx+1, szWnd.cy+1, cornerRadius<<1, cornerRadius<<1);
			}
			else
			{
				hRgn=CreateRectRgn(0, 0, szWnd.cx+1, szWnd.cy+1);
			}
			// select clip area
			if ( hRgn )
				ExtSelectClipRgn(tempDC, hRgn, RGN_AND);

			if ( AniAva.bFlags & AAO_OPAQUE)
			{
				// if back color - fill clipping area
				HBRUSH hBrush = CreateSolidBrush( AniAva.bkgColor );
				HBRUSH hOldBrush = (HBRUSH)SelectObject( tempDC, hBrush );
				FillRgn( tempDC, hRgn, hBrush );
				ske_SetRgnOpaque( tempDC, hRgn, TRUE );
			}
			// draw avatar
			if ( !(AniAva.bFlags & AAO_OPAQUE) )
				BitBlt(tempDC,0, 0, szWnd.cx, szWnd.cy , AniAva.hAniAvaDC , dat->ptFromPoint.x+dat->sizeAvatar.cx*dat->currentFrame, dat->ptFromPoint.y, SRCCOPY);
			else
			{
				BLENDFUNCTION abf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
				ske_AlphaBlend(tempDC,0, 0, szWnd.cx, szWnd.cy , AniAva.hAniAvaDC, dat->ptFromPoint.x+dat->sizeAvatar.cx*dat->currentFrame, dat->ptFromPoint.y, szWnd.cx, szWnd.cy, abf);
			}
			// reset clip area
			if ( hRgn )
			{
				DeleteObject(hRgn);
				hRgn = CreateRectRgn(0, 0, szWnd.cx, szWnd.cy);
				SelectClipRgn(tempDC, hRgn);
				DeleteObject(hRgn);
			}

			if ( ( AniAva.bFlags & AAO_HAS_OVERLAY )
				  && ( dat->overlayIconIdx != -1 )
				  && ( AniAva.overlayIconImageList ) )
			{
				// if overlay - draw overlay icon
				// position - on avatar
				int x=szWnd.cx-ICON_WIDTH;
				int y=szWnd.cy-ICON_HEIGHT;
				ske_ImageList_DrawEx(AniAva.overlayIconImageList,
					dat->overlayIconIdx&0xFFFF,
					tempDC, x, y, ICON_WIDTH, ICON_HEIGHT,
					CLR_NONE, CLR_NONE, ILD_NORMAL);
			}
			copyFromDC=tempDC;
		}
		// intersect visible area
		// update layered window
		GetWindowRect(pcli->hwndContactTree, &clistRect);
		if (dat->rcPos.top<0)
		{
			pt_from.y+=-dat->rcPos.top;
			szWnd.cy+=dat->rcPos.top;
		}
		if (dat->rcPos.bottom>clistRect.bottom-clistRect.top)
		{
			szWnd.cy-=(dat->rcPos.bottom-(clistRect.bottom-clistRect.top));
		}
		ptWnd.x=dat->rcPos.left+clistRect.left;
		ptWnd.y=(dat->rcPos.top>0 ? dat->rcPos.top :0)+clistRect.top;
		if (szWnd.cy>0)
		{
			if ( hdcParent && rcInParent && IMMEDIATE_DRAW )
			{
				if ( AniAva.bFlags & AAO_OPAQUE )
					BitBlt( hdcParent, rcInParent->left, rcInParent->top, szWnd.cx, szWnd.cy, copyFromDC, pt_from.x, pt_from.y, SRCCOPY);
				else
				{
					BLENDFUNCTION abf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
					ske_AlphaBlend( hdcParent, rcInParent->left, rcInParent->top, szWnd.cx, szWnd.cy, copyFromDC, pt_from.x, pt_from.y, szWnd.cx, szWnd.cy, abf);
				}
			}
			else if (!g_proc_UpdateLayeredWindow(dat->hWindow, hDC_animation, &ptWnd, &szWnd, copyFromDC, &pt_from, RGB(0,0,0), &bf, ULW_ALPHA ))
			{
				LONG exStyle;
				exStyle=GetWindowLong(dat->hWindow,GWL_EXSTYLE);
				exStyle|=WS_EX_LAYERED;
				SetWindowLong(dat->hWindow,GWL_EXSTYLE,exStyle);
				if ( !IMMEDIATE_DRAW )
					SetWindowPos( pcli->hwndContactTree, dat->hWindow, 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING );
				g_proc_UpdateLayeredWindow(dat->hWindow, hDC_animation, &ptWnd, &szWnd, copyFromDC, &pt_from, RGB(0,0,0), &bf, ULW_ALPHA );
			}

			g_CluiData.fAeroGlass = false;
			CLUI_UpdateAeroGlass();
		}
		else
		{
			dat->bPlaying=FALSE;
		}
		ReleaseDC(NULL,hDC_animation);
		if (tempDC)
		{
			SelectObject(tempDC, hOldBmp);
			DeleteObject(hBmp);
			DeleteDC(tempDC);
		}
	}
	if (!dat->bPlaying)
	{
		ShowWindow(dat->hWindow, SW_HIDE);
		KillTimer(dat->hWindow,2);  //stop animation till set pos will be called
	}
	GdiFlush();
}
static void _AniAva_RealRemoveAvatar(DWORD UniqueID)
{
	int j,k;
	for (j=0; j<AniAva.AniAvatarList->realCount; j++)
	{
		ANIAVA_INFO * aai=(ANIAVA_INFO *) AniAva.AniAvatarList->items[j];
		if (aai->dwAvatarUniqId==UniqueID)
		{
			aai->nRefCount--;
			if (aai->nRefCount==0)
			{
				_AniAva_PausePainting();
				#ifdef _DEBUG
					__AniAva_DebugRenderStrip();
				#endif
				if (aai->tcsFilename) mir_free(aai->tcsFilename);
				if (aai->pFrameDelays) free(aai->pFrameDelays);
				_AniAva_ReduceAvatarImages(aai->nStripTop,aai->FrameSize.cx*aai->nFrameCount, FALSE);
				for (k=0; k<AniAva.AniAvatarList->realCount; k++)
					if (k!=j)	{
						ANIAVA_INFO * taai=(ANIAVA_INFO *) AniAva.AniAvatarList->items[k];
						if (taai->nStripTop>aai->nStripTop)
							taai->nStripTop-=aai->FrameSize.cx*aai->nFrameCount;
					}
				if (AniAva.AniAvatarList->realCount>0)
				{
					//lets create hNewDC
					HDC	 hNewDC;
					HBITMAP	 hNewBmp, hNewOldBmp;

					int newWidth=AniAva.width-aai->FrameSize.cx*aai->nFrameCount;
					int newHeight=0;
					int i;
					for (i=0; i<AniAva.AniAvatarList->realCount; i++)
						if (i!=j)
						{
							newHeight=max(newHeight,((ANIAVA_INFO *) AniAva.AniAvatarList->items[i])->FrameSize.cy);
						}

					hNewDC=CreateCompatibleDC(NULL);
					hNewBmp=ske_CreateDIB32(newWidth,newHeight);
					hNewOldBmp=(HBITMAP)SelectObject(hNewDC,hNewBmp);
					// copy from old and from new strip
					if (aai->nStripTop>0)
						BitBlt(hNewDC,0,0,aai->nStripTop,newHeight,AniAva.hAniAvaDC,0,0, SRCCOPY);
					if (aai->nStripTop+aai->FrameSize.cx*aai->nFrameCount<AniAva.width)
						BitBlt(hNewDC,aai->nStripTop,0,AniAva.width-(aai->nStripTop+aai->FrameSize.cx*aai->nFrameCount),newHeight,AniAva.hAniAvaDC,aai->nStripTop+aai->FrameSize.cx*aai->nFrameCount,0, SRCCOPY);

					_AniAva_RemoveAniAvaDC(&AniAva);
					AniAva.hAniAvaDC		=hNewDC;
					AniAva.hAniAvaBitmap	=hNewBmp;
					AniAva.hAniAvaOldBitmap	=hNewOldBmp;
					AniAva.width			=newWidth;
					AniAva.height			=newHeight;

				}
				else
				{
					_AniAva_RemoveAniAvaDC(&AniAva);
				}
				#ifdef _DEBUG
					__AniAva_DebugRenderStrip();
				#endif
				li.List_Remove(AniAva.AniAvatarList, j);
				mir_free(aai);
				_AniAva_ResumePainting();
				break;
			}
		}
	}
}
static int	_AniAva_LoadAvatarFromImage(TCHAR * szFileName, int width, int height, ANIAVATARIMAGEINFO * pRetAII)
{
	ANIAVA_INFO aai={0};
	ANIAVA_INFO * paai=NULL;
	BOOL fNeedInsertToList=FALSE;
	int idx=0;
	aai.tcsFilename=szFileName;
	aai.FrameSize.cx=width;
	aai.FrameSize.cy=height;

	if (!li.List_GetIndex(AniAva.AniAvatarList,(void*)&aai,&idx)) idx=-1;
	if (idx==-1)	//item not present in list
	{
		HBITMAP hBitmap=NULL;
		HDC hTempDC;
		HBITMAP hOldBitmap;
		HDC hNewDC;
		HBITMAP hNewBmp;
		HBITMAP hNewOldBmp;
		int newWidth;
		int newHeight;

		paai=(ANIAVA_INFO *)mir_calloc(sizeof(ANIAVA_INFO));
		paai->tcsFilename=mir_tstrdup(szFileName);
		paai->dwAvatarUniqId=rand();
		fNeedInsertToList=TRUE;
		//get image strip
		GDIPlus_ExtractAnimatedGIF(szFileName, width, height, &hBitmap, &(paai->pFrameDelays), &(paai->nFrameCount), &(paai->FrameSize));

		//copy image to temp DC
		hTempDC=CreateCompatibleDC(NULL);
		hOldBitmap=(HBITMAP)SelectObject(hTempDC,hBitmap);

		//lets create hNewDC
		/*
		newWidth=max(paai->FrameSize.cx*paai->nFrameCount,AniAva.width);
		newHeight=AniAva.height+paai->FrameSize.cy;
		*/
		newWidth=AniAva.width+paai->FrameSize.cx*paai->nFrameCount;
		newHeight=max(paai->FrameSize.cy,AniAva.height);

		hNewDC=CreateCompatibleDC(NULL);
		hNewBmp=ske_CreateDIB32(newWidth,newHeight);
		hNewOldBmp=(HBITMAP)SelectObject(hNewDC,hNewBmp);

		_AniAva_PausePainting();
		GdiFlush();
		// copy from old and from new strip
		BitBlt(hNewDC,0,0,AniAva.width,AniAva.height,AniAva.hAniAvaDC,0,0, SRCCOPY);
		BitBlt(hNewDC,AniAva.width,0,paai->FrameSize.cx*paai->nFrameCount,paai->FrameSize.cy,hTempDC,0,0, SRCCOPY);
		
		paai->nStripTop=AniAva.width;
		
		GdiFlush();
		//remove temp DC
		SelectObject(hTempDC,hOldBitmap);
		DeleteObject(hNewBmp);
		DeleteDC(hTempDC);
        DeleteObject(hBitmap);


		//delete old
		_AniAva_RemoveAniAvaDC(&AniAva);
		//setNewDC;
		AniAva.hAniAvaDC		=hNewDC;
		AniAva.hAniAvaBitmap	=hNewBmp;
		AniAva.hAniAvaOldBitmap	=hNewOldBmp;
		AniAva.width			=newWidth;
		AniAva.height			=newHeight;
		GdiFlush();
		_AniAva_ResumePainting();
	}
	else
	{
		paai=(ANIAVA_INFO *)AniAva.AniAvatarList->items[idx];
	}
	if (paai)
	{
		paai->nRefCount++;
		pRetAII->nFramesCount=paai->nFrameCount;
		pRetAII->pFrameDelays=paai->pFrameDelays;
		pRetAII->ptImagePos.x=paai->nStripTop;
		pRetAII->ptImagePos.y=0;
		pRetAII->szSize=paai->FrameSize;
		if (fNeedInsertToList)
		{
			//add to list
			int idx=AniAva.AniAvatarList->realCount;
			li.List_GetIndex(AniAva.AniAvatarList, paai,&idx);
			li.List_Insert(AniAva.AniAvatarList, (void*)paai, idx);
		}
		return paai->dwAvatarUniqId;
	}
	return 0;
}
Exemple #7
0
INT_PTR CALLBACK DlgSkinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg) {
	case WM_DESTROY:
		if (hPreviewBitmap)
			ske_UnloadGlyphImage(hPreviewBitmap);
		break;

	case WM_INITDIALOG:
		TranslateDialogDefault(hwndDlg);
		SetDlgItemText(hwndDlg, IDC_SKINFOLDERLABEL, SkinsFolder);
		{
			HTREEITEM it = FillAvailableSkinList(hwndDlg);
			HWND wnd = GetDlgItem(hwndDlg, IDC_TREE1);
			TreeView_SelectItem(wnd, it);
		}
		return 0;

	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDC_COLOUR_MENUNORMAL:
		case IDC_COLOUR_MENUSELECTED:
		case IDC_COLOUR_FRAMES:
		case IDC_COLOUR_STATUSBAR:
			SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
			break;

		case IDC_BUTTON_INFO:
		{
			TCHAR Author[255], URL[MAX_PATH], Contact[255], Description[400], text[2000];
			SkinListData *sd = NULL;
			HTREEITEM hti = TreeView_GetSelection(GetDlgItem(hwndDlg, IDC_TREE1));
			if (hti == 0) return 0;
			{
				TVITEM tvi = { 0 };
				tvi.hItem = hti;
				tvi.mask = TVIF_HANDLE | TVIF_PARAM;
				TreeView_GetItem(GetDlgItem(hwndDlg, IDC_TREE1), &tvi);
				sd = (SkinListData*)(tvi.lParam);
			}
			if (!sd) return 0;
			if (sd->File && !_tcschr(sd->File, _T('%'))) {
				GetPrivateProfileString(_T("Skin_Description_Section"), _T("Author"), TranslateT("( unknown )"), Author, _countof(Author), sd->File);
				GetPrivateProfileString(_T("Skin_Description_Section"), _T("URL"), _T(""), URL, _countof(URL), sd->File);
				GetPrivateProfileString(_T("Skin_Description_Section"), _T("Contact"), _T(""), Contact, _countof(Contact), sd->File);
				GetPrivateProfileString(_T("Skin_Description_Section"), _T("Description"), _T(""), Description, _countof(Description), sd->File);
				mir_sntprintf(text, TranslateT("%s\n\n%s\n\nAuthor(s):\t %s\nContact:\t %s\nWeb:\t %s\n\nFile:\t %s"),
					sd->Name, Description, Author, Contact, URL, sd->File);
			}
			else {
				mir_sntprintf(text, TranslateT("%s\n\n%s\n\nAuthor(s): %s\nContact:\t %s\nWeb:\t %s\n\nFile:\t %s"),
					TranslateT("reVista for Modern v0.5"),
					TranslateT("This is second default Modern Contact list skin in Vista Aero style"),
					TranslateT("Angeli-Ka (graphics), FYR (template)"),
					_T("JID: [email protected]"),
					_T("fyr.mirandaim.ru"),
					TranslateT("Inside library"));
			}
			MessageBox(hwndDlg, text, TranslateT("Skin information"), MB_OK | MB_ICONINFORMATION);
		}
		break;

		case IDC_BUTTON_APPLY_SKIN:
			if (HIWORD(wParam) == BN_CLICKED) {
				SkinListData *sd = NULL;
				HTREEITEM hti = TreeView_GetSelection(GetDlgItem(hwndDlg, IDC_TREE1));
				if (hti == 0) return 0;
				{
					TVITEM tvi = { 0 };
					tvi.hItem = hti;
					tvi.mask = TVIF_HANDLE | TVIF_PARAM;
					TreeView_GetItem(GetDlgItem(hwndDlg, IDC_TREE1), &tvi);
					sd = (SkinListData*)(tvi.lParam);
				}
				if (!sd) return 0;
				ske_LoadSkinFromIniFile(sd->File, FALSE);
				ske_LoadSkinFromDB();
				pcli->pfnClcBroadcast(INTM_RELOADOPTIONS, 0, 0);
				Sync(CLUIFrames_OnClistResize_mod, 0, 0);
				ske_RedrawCompleteWindow();
				Sync(CLUIFrames_OnClistResize_mod, 0, 0);
				{
					HWND hwnd = pcli->hwndContactList;
					RECT rc = { 0 };
					GetWindowRect(hwnd, &rc);
					Sync(CLUIFrames_OnMoving, hwnd, &rc);
				}
				if (g_hCLUIOptionsWnd) {
					SendDlgItemMessage(g_hCLUIOptionsWnd, IDC_LEFTMARGINSPIN, UDM_SETPOS, 0, db_get_b(NULL, "CLUI", "LeftClientMargin", SETTING_LEFTCLIENTMARIGN_DEFAULT));
					SendDlgItemMessage(g_hCLUIOptionsWnd, IDC_RIGHTMARGINSPIN, UDM_SETPOS, 0, db_get_b(NULL, "CLUI", "RightClientMargin", SETTING_RIGHTCLIENTMARIGN_DEFAULT));
					SendDlgItemMessage(g_hCLUIOptionsWnd, IDC_TOPMARGINSPIN, UDM_SETPOS, 0, db_get_b(NULL, "CLUI", "TopClientMargin", SETTING_TOPCLIENTMARIGN_DEFAULT));
					SendDlgItemMessage(g_hCLUIOptionsWnd, IDC_BOTTOMMARGINSPIN, UDM_SETPOS, 0, db_get_b(NULL, "CLUI", "BottomClientMargin", SETTING_BOTTOMCLIENTMARIGN_DEFAULT));
				}
			}
			break;

		case IDC_BUTTON_RESCAN:
			if (HIWORD(wParam) == BN_CLICKED) {
				HTREEITEM it = FillAvailableSkinList(hwndDlg);
				HWND wnd = GetDlgItem(hwndDlg, IDC_TREE1);
				TreeView_SelectItem(wnd, it);
			}
		}
		break;

	case WM_DRAWITEM:
		if (wParam == IDC_PREVIEW)
		{
			//TODO:Draw hPreviewBitmap here
			int mWidth, mHeight;
			HBRUSH hbr = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
			DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam;
			mWidth = dis->rcItem.right - dis->rcItem.left;
			mHeight = dis->rcItem.bottom - dis->rcItem.top;
			HDC memDC = CreateCompatibleDC(dis->hDC);
			HBITMAP hbmp = ske_CreateDIB32(mWidth, mHeight);
			HBITMAP holdbmp = (HBITMAP)SelectObject(memDC, hbmp);
			RECT workRect = dis->rcItem;
			OffsetRect(&workRect, -workRect.left, -workRect.top);
			FillRect(memDC, &workRect, hbr);
			DeleteObject(hbr);
			if (hPreviewBitmap)
			{
				//variables
				BITMAP bmp = { 0 };
				POINT imgPos = { 0 };
				float xScale = 1, yScale = 1;
				//GetSize
				GetObject(hPreviewBitmap, sizeof(BITMAP), &bmp);
				int wWidth = workRect.right - workRect.left;
				int wHeight = workRect.bottom - workRect.top;
				if (wWidth < bmp.bmWidth) xScale = (float)wWidth / bmp.bmWidth;
				if (wHeight < bmp.bmHeight) yScale = (float)wHeight / bmp.bmHeight;
				xScale = min(xScale, yScale);
				yScale = xScale;
				int dWidth = (int)(xScale*bmp.bmWidth);
				int dHeight = (int)(yScale*bmp.bmHeight);
				//CalcPosition
				imgPos.x = workRect.left + ((wWidth - dWidth) >> 1);
				imgPos.y = workRect.top + ((wHeight - dHeight) >> 1);
				//DrawImage
				DrawAvatarImageWithGDIp(memDC, imgPos.x, imgPos.y, dWidth, dHeight, hPreviewBitmap, 0, 0, bmp.bmWidth, bmp.bmHeight, 8, 255);
			}
			BitBlt(dis->hDC, dis->rcItem.left, dis->rcItem.top, mWidth, mHeight, memDC, 0, 0, SRCCOPY);
			SelectObject(memDC, holdbmp);
			DeleteObject(hbmp);
			DeleteDC(memDC);
		}
		break;

	case WM_NOTIFY:
		switch (((LPNMHDR)lParam)->idFrom) {
		case IDC_TREE1:
		{
			NMTREEVIEW * nmtv = (NMTREEVIEW *)lParam;
			if (nmtv == NULL)
				return 0;

			if (nmtv->hdr.code == TVN_SELCHANGED) {
				SkinListData * sd = NULL;
				if (hPreviewBitmap) {
					ske_UnloadGlyphImage(hPreviewBitmap);
					hPreviewBitmap = NULL;
				}

				if (nmtv->itemNew.lParam) {
					sd = (SkinListData*)nmtv->itemNew.lParam;

					TCHAR buf[MAX_PATH];
					PathToRelativeT(sd->File, buf);
					SetDlgItemText(hwndDlg, IDC_EDIT_SKIN_FILENAME, buf);

					TCHAR prfn[MAX_PATH] = { 0 }, imfn[MAX_PATH] = { 0 }, skinfolder[MAX_PATH] = { 0 };
					GetPrivateProfileString(_T("Skin_Description_Section"), _T("Preview"), _T(""), imfn, _countof(imfn), sd->File);
					IniParser::GetSkinFolder(sd->File, skinfolder);
					mir_sntprintf(prfn, _T("%s\\%s"), skinfolder, imfn);
					PathToAbsoluteT(prfn, imfn);
					hPreviewBitmap = ske_LoadGlyphImage(imfn);

					EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_APPLY_SKIN), TRUE);
					EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_INFO), TRUE);
					if (hPreviewBitmap)
						InvalidateRect(GetDlgItem(hwndDlg, IDC_PREVIEW), NULL, TRUE);
					else { //prepare text
						TCHAR Author[255], URL[MAX_PATH], Contact[255], Description[400], text[2000];
						SkinListData* sd2 = NULL;
						HTREEITEM hti = TreeView_GetSelection(GetDlgItem(hwndDlg, IDC_TREE1));
						if (hti == 0) return 0;
						{
							TVITEM tvi = { 0 };
							tvi.hItem = hti;
							tvi.mask = TVIF_HANDLE | TVIF_PARAM;
							TreeView_GetItem(GetDlgItem(hwndDlg, IDC_TREE1), &tvi);
							sd2 = (SkinListData*)(tvi.lParam);
						}
						if (!sd2) return 0;

						if (sd2->File && !_tcschr(sd2->File, _T('%'))) {
							GetPrivateProfileString(_T("Skin_Description_Section"), _T("Author"), TranslateT("( unknown )"), Author, _countof(Author), sd2->File);
							GetPrivateProfileString(_T("Skin_Description_Section"), _T("URL"), _T(""), URL, _countof(URL), sd2->File);
							GetPrivateProfileString(_T("Skin_Description_Section"), _T("Contact"), _T(""), Contact, _countof(Contact), sd2->File);
							GetPrivateProfileString(_T("Skin_Description_Section"), _T("Description"), _T(""), Description, _countof(Description), sd2->File);
							mir_sntprintf(text, TranslateT("Preview is not available\n\n%s\n----------------------\n\n%s\n\nAUTHOR(S):\n%s\n\nCONTACT:\n%s\n\nHOMEPAGE:\n%s"),
								sd2->Name, Description, Author, Contact, URL);
						}
						else {
							mir_sntprintf(text, TranslateT("%s\n\n%s\n\nAUTHORS:\n%s\n\nCONTACT:\n%s\n\nWEB:\n%s\n\n\n"),
								TranslateT("reVista for Modern v0.5"),
								TranslateT("This is second default Modern Contact list skin in Vista Aero style"),
								TranslateT("graphics by Angeli-Ka\ntemplate by FYR"),
								_T("JID: [email protected]"),
								_T("fyr.mirandaim.ru"));
						}
						ShowWindow(GetDlgItem(hwndDlg, IDC_PREVIEW), SW_HIDE);
						ShowWindow(GetDlgItem(hwndDlg, IDC_STATIC_INFO), SW_SHOW);
						SetDlgItemText(hwndDlg, IDC_STATIC_INFO, text);
					}
				}
				else {
					//no selected
					SetDlgItemText(hwndDlg, IDC_EDIT_SKIN_FILENAME, TranslateT("Select skin from list"));
					EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_APPLY_SKIN), FALSE);
					EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_INFO), FALSE);
					SetDlgItemText(hwndDlg, IDC_STATIC_INFO, TranslateT("Please select skin to apply"));
					ShowWindow(GetDlgItem(hwndDlg, IDC_PREVIEW), SW_HIDE);
				}
				ShowWindow(GetDlgItem(hwndDlg, IDC_PREVIEW), hPreviewBitmap ? SW_SHOW : SW_HIDE);
				return 0;
			}
			else if (nmtv->hdr.code == TVN_DELETEITEM) {
				mir_free_and_nil(nmtv->itemOld.lParam);
				return 0;
			}
		}
		break;

		case 0:
			switch (((LPNMHDR)lParam)->code) {
			case PSN_APPLY:
				pcli->pfnClcBroadcast(INTM_RELOADOPTIONS, 0, 0);
				NotifyEventHooks(g_CluiData.hEventBkgrChanged, 0, 0);
				pcli->pfnClcBroadcast(INTM_INVALIDATE, 0, 0);
				RedrawWindow(GetParent(pcli->hwndContactTree), NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
			}
			break;
		}
	}
static void PaintWorker(TBBUTTONDATA *bct, HDC hdcPaint, POINT *pOffset)
{
	if (!hdcPaint)
		return;  //early exit

	POINT offset;
	if (pOffset)
		offset = *pOffset;
	else
		offset.x = offset.y = 0;

	RECT rcClient;
	GetClientRect(bct->hwnd, &rcClient);
	int width = rcClient.right - rcClient.left;
	int height = rcClient.bottom - rcClient.top;

	HBITMAP hbmMem = NULL;
	HBITMAP hbmOld = NULL;
	HDC hdcMem = pOffset ? hdcPaint : CreateCompatibleDC(hdcPaint);
	HFONT hOldFont = (HFONT)SelectObject(hdcMem, bct->hFont);
	if (!pOffset) {
		hbmMem = ske_CreateDIB32(width, height);
		hbmOld = (HBITMAP)SelectObject(hdcMem, hbmMem);
	}
	else OffsetRect(&rcClient, offset.x, offset.y);

	if (!g_CluiData.fDisableSkinEngine) {
		char szRequest[128];
		/* painting */
		mir_snprintf(szRequest, "Button,ID=%s,Hovered=%s,Pressed=%s,Focused=%s",
			bct->szButtonID,				// ID		
			b2str(bct->stateId == PBS_HOT),	// Hovered
			b2str(bct->stateId == PBS_PRESSED || bct->bIsPushed == TRUE),	// Pressed
			b2str(bct->bFocused));		// Focused

		SkinDrawGlyph(hdcMem, &rcClient, &rcClient, szRequest);
	}
	else if (xpt_IsThemed(bct->hThemeToolbar)) {
		RECT *rc = &rcClient;
		int state = IsWindowEnabled(bct->hwnd) ? /*(bct->stateId == PBS_PRESSED || bct->bIsPushed == TRUE) ? PBS_PRESSED :*/ (bct->stateId == PBS_NORMAL && bct->bIsDefault ? PBS_DEFAULTED : bct->stateId) : PBS_DISABLED;
		xpt_DrawTheme(bct->hThemeToolbar, bct->hwnd, hdcMem, TP_BUTTON, TBStateConvert2Flat(state), rc, rc);
	}
	else {
		HBRUSH hbr = NULL;

		if (bct->stateId == PBS_PRESSED || bct->stateId == PBS_HOT)
			hbr = GetSysColorBrush(COLOR_3DLIGHT);
		else {
			RECT btnRect;
			POINT pt = { 0 };
			int ret;
			HWND hwndParent = GetParent(bct->hwnd);
			HDC dc = CreateCompatibleDC(NULL);
			HBITMAP memBM, oldBM;
			GetWindowRect(hwndParent, &btnRect);
			memBM = ske_CreateDIB32(btnRect.right - btnRect.left, btnRect.bottom - btnRect.top);
			oldBM = (HBITMAP)SelectObject(dc, memBM);
			ret = SendMessage(hwndParent, WM_ERASEBKGND, (WPARAM)dc, 0);
			GetWindowRect(bct->hwnd, &btnRect);
			ClientToScreen(hwndParent, &pt);
			OffsetRect(&btnRect, -pt.x, -pt.y);
			if (ret)
				BitBlt(hdcMem, 0, 0, btnRect.right - btnRect.left, btnRect.bottom - btnRect.top, dc, btnRect.left, btnRect.top, SRCCOPY);
			oldBM = (HBITMAP)SelectObject(dc, oldBM);
			DeleteObject(memBM);
			DeleteDC(dc);
			if (!ret) { //WM_ERASEBKG return false need to paint
				HDC pdc = GetDC(hwndParent);
				HBRUSH oldBrush = (HBRUSH)GetCurrentObject(pdc, OBJ_BRUSH);
				hbr = (HBRUSH)SendMessage(hwndParent, WM_CTLCOLORDLG, (WPARAM)pdc, (LPARAM)hwndParent);
				SelectObject(pdc, oldBrush);
				ReleaseDC(hwndParent, pdc);
			}
		}
		if (hbr) {
			FillRect(hdcMem, &rcClient, hbr);
			DeleteObject(hbr);
		}
		if (bct->stateId == PBS_HOT || bct->bFocused) {
			if (bct->bIsPushed)
				DrawEdge(hdcMem, &rcClient, EDGE_ETCHED, BF_RECT | BF_SOFT);
			else
				DrawEdge(hdcMem, &rcClient, BDR_RAISEDOUTER, BF_RECT | BF_SOFT | BF_FLAT);
		}
		else if (bct->stateId == PBS_PRESSED)
			DrawEdge(hdcMem, &rcClient, BDR_SUNKENOUTER, BF_RECT | BF_SOFT);
	}

	RECT  rcTemp = rcClient;  //content rect
	bool  bPressed = (bct->stateId == PBS_PRESSED || bct->bIsPushed == TRUE);
	bool  bHasText = (bct->szText[0] != '\0');

	/* formatter */
	if (!g_CluiData.fDisableSkinEngine) {
		/* correct rect according to rcMargins */

		rcTemp.left += bct->rcMargins.left;
		rcTemp.top += bct->rcMargins.top;
		rcTemp.bottom -= bct->rcMargins.bottom;
		rcTemp.right -= bct->rcMargins.right;
	}

	/* reposition button items */
	RECT rcIcon = rcTemp, rcText = rcTemp;
	if (bct->hIcon) {
		if (bHasText) {
			rcIcon.right = rcIcon.left + 16; /* CXSM_ICON */
			rcText.left = rcIcon.right + 2;
		}
		else {
			rcIcon.left += (rcIcon.right - rcIcon.left) / 2 - 8;
			rcIcon.right = rcIcon.left + 16;
		}
	}

	/*	Check sizes*/
	if (bct->hIcon && (rcIcon.right > rcTemp.right || rcIcon.bottom > rcTemp.bottom || rcIcon.left < rcTemp.left || rcIcon.top < rcTemp.top))
		bct->hIcon = NULL;

	if (bHasText && (rcText.right > rcTemp.right || rcText.bottom > rcTemp.bottom || rcText.left < rcTemp.left || rcText.top < rcTemp.top))
		bHasText = FALSE;

	if (bct->hIcon) {
		/* center icon vertically */
		rcIcon.top += (rcClient.bottom - rcClient.top) / 2 - 8; /* CYSM_ICON/2 */
		rcIcon.bottom = rcIcon.top + 16; /* CYSM_ICON */
		/* draw it */
		ske_DrawIconEx(hdcMem, rcIcon.left + bPressed, rcIcon.top + bPressed, bct->hIcon, 16, 16, 0, NULL, DI_NORMAL);
	}

	if (bHasText) {
		BOOL bCentered = TRUE;
		SetBkMode(hdcMem, TRANSPARENT);
		if (bct->nFontID >= 0)
			g_clcPainter.ChangeToFont(hdcMem, NULL, bct->nFontID, NULL);

		RECT TextRequiredRect = rcText;
		ske_DrawText(hdcMem, bct->szText, -1, &TextRequiredRect, DT_CENTER | DT_VCENTER | DT_CALCRECT | DT_SINGLELINE);
		if (TextRequiredRect.right - TextRequiredRect.left > rcText.right - rcText.left)
			bCentered = FALSE;

		ske_DrawText(hdcMem, bct->szText, -1, &rcText, (bCentered ? DT_CENTER : 0) | DT_VCENTER | DT_SINGLELINE);
		ske_ResetTextEffect(hdcMem);
	}
	if (!pOffset)
		BitBlt(hdcPaint, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY);

	// better to use try/finally but looks like last one is Microsoft specific
	SelectObject(hdcMem, hOldFont);
	if (!pOffset) {
		SelectObject(hdcMem, hbmOld);
		DeleteObject(hbmMem);
		DeleteDC(hdcMem);
	}
}
void Cache_GetAvatar(struct ClcData *dat, struct ClcContact *contact)
{
	int old_pos=contact->avatar_pos;
    if (g_CluiData.bSTATE!=STATE_NORMAL
        || (dat->use_avatar_service && !ServiceExists(MS_AV_GETAVATARBITMAP)) ) // workaround for avatar service and other wich destroys service on OK_TOEXIT
    {
        contact->avatar_pos = AVATAR_POS_DONT_HAVE;
        contact->avatar_data = NULL;
        return;
    }
    if (dat->use_avatar_service && ServiceExists(MS_AV_GETAVATARBITMAP))
    {
        if (dat->avatars_show && !ModernGetSettingByte(contact->hContact, "CList", "HideContactAvatar", 0))
        {
            contact->avatar_data = (struct avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)contact->hContact, 0);
            if (contact->avatar_data == NULL || contact->avatar_data->cbSize != sizeof(struct avatarCacheEntry) 
                || contact->avatar_data->dwFlags == AVS_BITMAP_EXPIRED)
            {
                contact->avatar_data = NULL;
            }

            if (contact->avatar_data != NULL)
			{
                contact->avatar_data->t_lastAccess = (DWORD)time(NULL);				
			}
        }
        else
        {
            contact->avatar_data = NULL;
        }
		Cache_ProceedAvatarInList(dat, contact);
    }
    else
    {
        contact->avatar_pos = AVATAR_POS_DONT_HAVE;
        if (dat->avatars_show && !ModernGetSettingByte(contact->hContact, "CList", "HideContactAvatar", 0))
        {
            DBVARIANT dbv;
            if (!ModernGetSettingTString(contact->hContact, "ContactPhoto", "File", &dbv))
            {
                HBITMAP hBmp = (HBITMAP) CallService(MS_UTILS_LOADBITMAPT, 0, (LPARAM)dbv.ptszVal);
                if (hBmp != NULL)
                {
                    // Make bounds
                    BITMAP bm;
                    if (GetObject(hBmp,sizeof(BITMAP),&bm))
                    {
                        // Create data...
                        HDC hdc; 
                        HBITMAP hDrawBmp,oldBmp;

                        // Make bounds -> keep aspect radio
                        LONG width_clip;
                        LONG height_clip;
                        RECT rc = {0};

                        // Clipping width and height
                        width_clip = dat->avatars_maxheight_size;
                        height_clip = dat->avatars_maxheight_size;

                        if (height_clip * bm.bmWidth / bm.bmHeight <= width_clip)
                        {
                            width_clip = height_clip * bm.bmWidth / bm.bmHeight;
                        }
                        else
                        {
                            height_clip = width_clip * bm.bmHeight / bm.bmWidth;					
                        }

                        // Create objs
                        hdc = CreateCompatibleDC(dat->avatar_cache.hdc); 
                        hDrawBmp = ske_CreateDIB32(width_clip, height_clip);
						oldBmp=(HBITMAP)SelectObject(hdc, hDrawBmp);
                        SetBkMode(hdc,TRANSPARENT);
                        {
                            POINT org;
                            GetBrushOrgEx(hdc, &org);
                            SetStretchBltMode(hdc, HALFTONE);
                            SetBrushOrgEx(hdc, org.x, org.y, NULL);
                        }

                        rc.right = width_clip - 1;
                        rc.bottom = height_clip - 1;

                        // Draw bitmap             8//8
                        {
                            HDC dcMem = CreateCompatibleDC(hdc);
							HBITMAP obmp=(HBITMAP)SelectObject(dcMem, hBmp);						
                            StretchBlt(hdc, 0, 0, width_clip, height_clip,dcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
                            SelectObject(dcMem,obmp);
                            mod_DeleteDC(dcMem);
                        }
                        {
                            RECT rtr={0};
                            rtr.right=width_clip+1;
                            rtr.bottom=height_clip+1;
                            ske_SetRectOpaque(hdc,&rtr);
                        }

						hDrawBmp = (HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP);
                        SelectObject(hdc,oldBmp);
                        mod_DeleteDC(hdc);

                        // Add to list
                        if (old_pos >= 0)
                        {
                            ImageArray_ChangeImage(&dat->avatar_cache, hDrawBmp, old_pos);
                            contact->avatar_pos = old_pos;
                        }
                        else
                        {
                            contact->avatar_pos = ImageArray_AddImage(&dat->avatar_cache, hDrawBmp, -1);
                        }

                        DeleteObject(hDrawBmp);
                    } // if (GetObject(hBmp,sizeof(BITMAP),&bm))
                    DeleteObject(hBmp);
                } //if (hBmp != NULL)
            }
            ModernDBFreeVariant(&dbv);
        }

        // Remove avatar if needed
        if (old_pos >= 0 && contact->avatar_pos == AVATAR_POS_DONT_HAVE)
        {
            ImageArray_RemoveImage(&dat->avatar_cache, old_pos);
            // Update all items
            ExecuteOnAllContacts(dat, ReduceAvatarPosition, (void *)&old_pos);
        }
		if (old_pos==AVATAR_POS_ANIMATED && contact->avatar_pos != AVATAR_POS_ANIMATED)
		{
			AniAva_RemoveAvatar( contact->hContact );
		}
    }
}
void Cache_ProceedAvatarInList(struct ClcData *dat, struct ClcContact *contact)
{
	struct avatarCacheEntry * ace=contact->avatar_data;
	int old_pos=contact->avatar_pos;

	if (   ace==NULL 
		|| ace->dwFlags == AVS_BITMAP_EXPIRED
		|| ace->hbmPic == NULL)
	{
		//Avatar was not ready or removed - need to remove it from cache
		if (old_pos>=0)
		{
			ImageArray_RemoveImage(&dat->avatar_cache, old_pos);
			// Update all items
			ExecuteOnAllContacts(dat, ReduceAvatarPosition, (void *)&old_pos);
			contact->avatar_pos=AVATAR_POS_DONT_HAVE;
			return;
		}
	}
	else if (contact->avatar_data->hbmPic != NULL) //Lets Add it
	{
		HDC hdc; 
		HBITMAP hDrawBmp,oldBmp;
		void * pt;

		// Make bounds -> keep aspect radio
		LONG width_clip;
		LONG height_clip;
		RECT rc = {0};

		// Clipping width and height
		width_clip = dat->avatars_maxwidth_size?dat->avatars_maxwidth_size:dat->avatars_maxheight_size;
		height_clip = dat->avatars_maxheight_size;

		if (height_clip * ace->bmWidth / ace->bmHeight <= width_clip)
		{
			width_clip = height_clip * ace->bmWidth / ace->bmHeight;
		}
		else
		{
			height_clip = width_clip * ace->bmHeight / ace->bmWidth;					
		}
		if (wildcmpi(contact->avatar_data->szFilename,_T("*.gif")))
		{
			int res;
			if (old_pos==AVATAR_POS_ANIMATED)
				AniAva_RemoveAvatar(contact->hContact);

			res=AniAva_AddAvatar(contact->hContact, contact->avatar_data->szFilename, width_clip, height_clip);
			if (res)
			{
				contact->avatar_pos=AVATAR_POS_ANIMATED;
				contact->avatar_size.cy=HIWORD(res);
				contact->avatar_size.cx=LOWORD(res);
				return;
			}
		}
		// Create objs
		hdc = CreateCompatibleDC(dat->avatar_cache.hdc); 
		hDrawBmp = ske_CreateDIB32Point(width_clip, height_clip,&pt);
		oldBmp=(HBITMAP)SelectObject(hdc, hDrawBmp);
		//need to draw avatar bitmap here
		{
			RECT real_rc={0,0,width_clip, height_clip};
			/*
			if (ServiceExists(MS_AV_BLENDDRAWAVATAR))
			{
				AVATARDRAWREQUEST adr;

				adr.cbSize = sizeof(AVATARDRAWREQUEST);
				adr.hContact = contact->hContact;
				adr.hTargetDC = hdc;
				adr.rcDraw = real_rc;
				adr.dwFlags = 0;				
				adr.alpha = 255;
				CallService(MS_AV_BLENDDRAWAVATAR, 0, (LPARAM) &adr);
			}
			else
			*/
			{
				int w=width_clip;
				int h=height_clip;
				if (!g_CluiData.fGDIPlusFail) //Use gdi+ engine
				{
					DrawAvatarImageWithGDIp(hdc, 0, 0, w, h,ace->hbmPic,0,0,ace->bmWidth,ace->bmHeight,ace->dwFlags,255);
				}
				else
				{
					if (!(ace->dwFlags&AVS_PREMULTIPLIED))
					{
						HDC hdcTmp = CreateCompatibleDC(hdc);
						RECT r={0,0,w,h};
						HDC hdcTmp2 = CreateCompatibleDC(hdc);
						HBITMAP bmo=(HBITMAP)SelectObject(hdcTmp,ace->hbmPic);
						HBITMAP b2=ske_CreateDIB32(w,h);
						HBITMAP bmo2=(HBITMAP)SelectObject(hdcTmp2,b2);
						SetStretchBltMode(hdcTmp,  HALFTONE);
						SetStretchBltMode(hdcTmp2,  HALFTONE);
						StretchBlt(hdcTmp2, 0, 0, w, h,
							hdcTmp, 0, 0, ace->bmWidth, ace->bmHeight,
							SRCCOPY);

						ske_SetRectOpaque(hdcTmp2,&r);
						BitBlt(hdc, rc.left, rc.top, w, h,hdcTmp2,0,0,SRCCOPY);
						SelectObject(hdcTmp2,bmo2);
						SelectObject(hdcTmp,bmo);
						mod_DeleteDC(hdcTmp);
						mod_DeleteDC(hdcTmp2);
						DeleteObject(b2);
					}
					else {
						BLENDFUNCTION bf={AC_SRC_OVER, 0,255, AC_SRC_ALPHA };
						HDC hdcTempAv = CreateCompatibleDC(hdc);
						HBITMAP hbmTempAvOld;
						hbmTempAvOld = (HBITMAP)SelectObject(hdcTempAv,ace->hbmPic);
						ske_AlphaBlend(hdc, rc.left, rc.top, w, h, hdcTempAv, 0, 0,ace->bmWidth,ace->bmHeight, bf);
						SelectObject(hdcTempAv, hbmTempAvOld);
						mod_DeleteDC(hdcTempAv);
					}
				}
			}
		}
		SelectObject(hdc,oldBmp);
		DeleteDC(hdc);
		// Add to list
		if (old_pos >= 0)
		{
			ImageArray_ChangeImage(&dat->avatar_cache, hDrawBmp, old_pos);
			contact->avatar_pos = old_pos;
		}
		else
		{
			contact->avatar_pos = ImageArray_AddImage(&dat->avatar_cache, hDrawBmp, -1);
		}
		if (old_pos==AVATAR_POS_ANIMATED && contact->avatar_pos!=AVATAR_POS_ANIMATED)
		{
			AniAva_RemoveAvatar(contact->hContact);
		}

		DeleteObject(hDrawBmp);

	}

}
INT_PTR CALLBACK DlgSkinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch ( msg )
	{
	case WM_DESTROY: 
		{
			if ( hPreviewBitmap ) ske_UnloadGlyphImage( hPreviewBitmap );
			break;
		}

	case WM_INITDIALOG:
		{ 
			HTREEITEM it;
			TranslateDialogDefault( hwndDlg );
			it = FillAvailableSkinList( hwndDlg );
			HWND wnd = GetDlgItem( hwndDlg, IDC_TREE1 );
			TreeView_SelectItem( wnd, it );						
		}
		return 0;
	case WM_COMMAND:
		{
			int isLoad = 0;
			switch ( LOWORD( wParam ) ) 
			{
			case IDC_COLOUR_MENUNORMAL:
			case IDC_COLOUR_MENUSELECTED:
			case IDC_COLOUR_FRAMES:
			case IDC_COLOUR_STATUSBAR:
				SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
				break;

			case IDC_BUTTON_INFO:
				{
					TCHAR Author[255];
					TCHAR URL[MAX_PATH];
					TCHAR Contact[255];
					TCHAR Description[400];
					TCHAR text[2000];
					SkinListData *sd = NULL;  
					HTREEITEM hti = TreeView_GetSelection( GetDlgItem( hwndDlg, IDC_TREE1 ) );				
					if ( hti == 0 ) return 0;
					{
						TVITEM tvi = {0};
						tvi.hItem = hti;
						tvi.mask = TVIF_HANDLE|TVIF_PARAM;
						TreeView_GetItem( GetDlgItem( hwndDlg, IDC_TREE1 ), &tvi );
						sd = ( SkinListData* )( tvi.lParam );
					}
					if ( !sd ) return 0;
					if ( sd->File && !_tcschr( sd->File, _T('%') ) )
					{
						GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Author" ), 	TranslateT( "( unknown )" ), 	Author, 		SIZEOF( Author ), 		sd->File );
						GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "URL" ), 		_T( "" ), 						URL, 		SIZEOF( URL ), 		sd->File );
						GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Contact" ), 	_T( "" ), 						Contact, 	SIZEOF( Contact ), 	sd->File );
						GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Description" ), _T( "" ), 					Description, SIZEOF( Description ), sd->File );
						_sntprintf( text, SIZEOF( text ), TranslateT( "%s\n\n%s\n\nAuthor(s):\t %s\nContact:\t %s\nWeb:\t %s\n\nFile:\t %s" ), 
							sd->Name, Description, Author, Contact, URL, sd->File );
					}
					else
					{
						_sntprintf( text, SIZEOF( text ), TranslateT( "%s\n\n%s\n\nAuthor(s): %s\nContact:\t %s\nWeb:\t %s\n\nFile:\t %s" ), 
							TranslateT( "reVista for Modern v0.5" ), 
							TranslateT( "This is second default Modern Contact list skin in Vista Aero style" ), 
							TranslateT( "Angeli-Ka (graphics), FYR (template)" ), 
							_T( "JID: [email protected]" ), 
							_T("fyr.mirandaim.ru"), 
							TranslateT( "Inside library" ) );
					}
					MessageBox( hwndDlg, text, TranslateT( "Skin Information" ), MB_OK|MB_ICONINFORMATION );
				}
				break;
			case IDC_BUTTON_APPLY_SKIN:
				if ( HIWORD( wParam ) == BN_CLICKED )
				{ 		
					SkinListData *sd = NULL;  
					HTREEITEM hti = TreeView_GetSelection( GetDlgItem( hwndDlg, IDC_TREE1 ) );				
					if ( hti == 0 ) return 0;
					{
						TVITEM tvi = {0};
						tvi.hItem = hti;
						tvi.mask = TVIF_HANDLE|TVIF_PARAM;
						TreeView_GetItem( GetDlgItem( hwndDlg, IDC_TREE1 ), &tvi );
						sd = ( SkinListData* )( tvi.lParam );
					}
					if ( !sd ) return 0;
					if ( glSkinWasModified>0 )
					{
						int res = 0;
						if ( glSkinWasModified == 1 )
							res = MessageBox( hwndDlg, TranslateT( "Skin editor contains not stored changes.\n\nAll changes will be lost.\n\n Continue to load new skin?" ), TranslateT( "Warning!" ), MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2|MB_TOPMOST );
						else
							res = MessageBox( hwndDlg, TranslateT( "Current skin was not saved to file.\n\nAll changes will be lost.\n\n Continue to load new skin?" ), TranslateT( "Warning!" ), MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2|MB_TOPMOST );
						if ( res!= IDOK ) return 0;
					}
					ske_LoadSkinFromIniFile( sd->File, FALSE );
					ske_LoadSkinFromDB( );	
					glOtherSkinWasLoaded = TRUE;
					pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, 0, 0 );
					Sync( CLUIFrames_OnClistResize_mod, 0, 0 );
					ske_RedrawCompleteWindow( );        
					Sync( CLUIFrames_OnClistResize_mod, 0, 0 );
					{
						HWND hwnd = pcli->hwndContactList;
						RECT rc = {0};
						GetWindowRect( hwnd, &rc );
						Sync( CLUIFrames_OnMoving, hwnd, &rc );
					}
					if ( g_hCLUIOptionsWnd )
					{
						SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_LEFTMARGINSPIN, UDM_SETPOS, 0, ModernGetSettingByte( NULL, "CLUI", "LeftClientMargin", SETTING_LEFTCLIENTMARIGN_DEFAULT ) );
						SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_RIGHTMARGINSPIN, UDM_SETPOS, 0, ModernGetSettingByte( NULL, "CLUI", "RightClientMargin", SETTING_RIGHTCLIENTMARIGN_DEFAULT ) );
						SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_TOPMARGINSPIN, UDM_SETPOS, 0, ModernGetSettingByte( NULL, "CLUI", "TopClientMargin", SETTING_TOPCLIENTMARIGN_DEFAULT ) );
						SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_BOTTOMMARGINSPIN, UDM_SETPOS, 0, ModernGetSettingByte( NULL, "CLUI", "BottomClientMargin", SETTING_BOTTOMCLIENTMARIGN_DEFAULT ) );
					}
				}
				break;
			case IDC_BUTTON_LOAD:
				isLoad = 1;
				if ( HIWORD( wParam ) == BN_CLICKED )
				{
					{   		
						TCHAR str[MAX_PATH] = {0};
						OPENFILENAME ofn = {0};
						TCHAR filter[512] = {0};
						int res = 0;
						ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
						ofn.hwndOwner = hwndDlg;
						ofn.hInstance = NULL;

						mir_sntprintf(filter, SIZEOF(filter), _T("%s (*.msf)%c*.MSF%c%c"), TranslateT("Miranda skin file"), 0, 0, 0);
						ofn.lpstrFilter = filter;
						ofn.lpstrFile = str;
						ofn.Flags = isLoad?( OFN_FILEMUSTEXIST | OFN_HIDEREADONLY ) : ( OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY ) | OFN_DONTADDTORECENT;
						ofn.nMaxFile = sizeof( str );
						ofn.nMaxFileTitle = MAX_PATH;
						ofn.lpstrDefExt = _T( "msf" );

						{
							DWORD tick = GetTickCount( );
							res = GetOpenFileName( &ofn );
							if( !res ) 
								if ( GetTickCount( )-tick<100 )
								{
									res = GetOpenFileName( &ofn );
									if( !res ) break;
								}
								else break;
						}
						if ( res )
						{
							HTREEITEM it = AddSkinToListFullName( hwndDlg, ofn.lpstrFile );
							TreeView_SelectItem( GetDlgItem( hwndDlg, IDC_TREE1 ), it );
							//SendDlgItemMessage( hwndDlg, IDC_SKINS_LIST, LB_SETCURSEL, it, 0 ); 
							//SendMessage( hwndDlg, WM_COMMAND, MAKEWPARAM( IDC_SKINS_LIST, LBN_SELCHANGE ), 0 );
						}
					}
				}
			}
			break;
		}
	case WM_DRAWITEM:
		if ( wParam == IDC_PREVIEW )
		{
			//TODO:Draw hPreviewBitmap here
			HDC memDC, imgDC;
			HBITMAP hbmp, holdbmp, imgOldbmp;
			int mWidth, mHeight;
			RECT workRect = {0};
			HBRUSH hbr = CreateSolidBrush( GetSysColor( COLOR_3DFACE ) );
			DRAWITEMSTRUCT *dis = ( DRAWITEMSTRUCT * )lParam;
			mWidth = dis->rcItem.right-dis->rcItem.left;
			mHeight = dis->rcItem.bottom-dis->rcItem.top;
			memDC = CreateCompatibleDC( dis->hDC );
			hbmp = ske_CreateDIB32( mWidth, mHeight );
			holdbmp = ( HBITMAP )SelectObject( memDC, hbmp );
			workRect = dis->rcItem;
			OffsetRect( &workRect, -workRect.left, -workRect.top );
			FillRect( memDC, &workRect, hbr );     
			DeleteObject( hbr );
			if ( hPreviewBitmap )
			{
				//variables
				BITMAP bmp = {0};
				POINT imgPos = {0};
				int wWidth, wHeight;
				int dWidth, dHeight;
				float xScale = 1, yScale = 1;
				//GetSize
				GetObject( hPreviewBitmap, sizeof( BITMAP ), &bmp );
				wWidth = workRect.right-workRect.left;
				wHeight = workRect.bottom-workRect.top;
				if ( wWidth<bmp.bmWidth ) xScale = ( float )wWidth/bmp.bmWidth;
				if ( wHeight<bmp.bmHeight ) yScale = ( float )wHeight/bmp.bmHeight;
				xScale = min( xScale, yScale );
				yScale = xScale;                    
				dWidth = ( int )( xScale*bmp.bmWidth );
				dHeight = ( int )( yScale*bmp.bmHeight );
				//CalcPosition
				imgPos.x = workRect.left+( ( wWidth-dWidth )>>1 );
				imgPos.y = workRect.top+( ( wHeight-dHeight )>>1 );     
				//DrawImage
				if ( !g_CluiData.fGDIPlusFail ) //Use gdi+ engine
				{
					DrawAvatarImageWithGDIp( memDC, imgPos.x, imgPos.y, dWidth, dHeight, hPreviewBitmap, 0, 0, bmp.bmWidth, bmp.bmHeight, 8, 255 );
				}   
				else
				{
					BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
					imgDC = CreateCompatibleDC( dis->hDC );
					imgOldbmp = ( HBITMAP )SelectObject( imgDC, hPreviewBitmap );                 
					ske_AlphaBlend( memDC, imgPos.x, imgPos.y, dWidth, dHeight, imgDC, 0, 0, bmp.bmWidth, bmp.bmHeight, bf );
					SelectObject( imgDC, imgOldbmp );
					mod_DeleteDC( imgDC );
				}
			}
			BitBlt( dis->hDC, dis->rcItem.left, dis->rcItem.top, mWidth, mHeight, memDC, 0, 0, SRCCOPY );
			SelectObject( memDC, holdbmp );
			DeleteObject( hbmp );
			mod_DeleteDC( memDC );
		}
		break;

	case WM_NOTIFY:
		switch ( ( ( LPNMHDR )lParam )->idFrom ) 
		{
		case IDC_TREE1:
			{		
				NMTREEVIEW * nmtv = ( NMTREEVIEW * ) lParam;
				if ( !nmtv ) return 0;
				if ( nmtv->hdr.code == TVN_SELCHANGEDA
					|| nmtv->hdr.code == TVN_SELCHANGEDW )
				{	
					SkinListData * sd = NULL;
					if ( hPreviewBitmap ) 
					{
						ske_UnloadGlyphImage( hPreviewBitmap );
						hPreviewBitmap = NULL;
					}
					if ( nmtv->itemNew.lParam )
					{
						sd = ( SkinListData* )nmtv->itemNew.lParam;
						{
							TCHAR buf[MAX_PATH];
							CallService( MS_UTILS_PATHTORELATIVET, ( WPARAM )sd->File, ( LPARAM )buf );
							SendDlgItemMessage( hwndDlg, IDC_EDIT_SKIN_FILENAME, WM_SETTEXT, 0, ( LPARAM )buf );
						}
						{
							TCHAR prfn[MAX_PATH] = {0};
							TCHAR imfn[MAX_PATH] = {0};
							TCHAR skinfolder[MAX_PATH] = {0};
							GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Preview" ), _T( "" ), imfn, SIZEOF( imfn ), sd->File );
							IniParser::GetSkinFolder( sd->File, skinfolder );
							_sntprintf( prfn, SIZEOF( prfn ), _T("%s\\%s"), skinfolder, imfn );
							CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )prfn, ( LPARAM ) imfn );
							char * imfn_ch = mir_t2a( imfn ); 
							hPreviewBitmap = ske_LoadGlyphImage( imfn_ch );
							mir_free( imfn_ch );
						}
						EnableWindow( GetDlgItem( hwndDlg, IDC_BUTTON_APPLY_SKIN ), TRUE );
						EnableWindow( GetDlgItem( hwndDlg, IDC_BUTTON_INFO ), TRUE );
						if ( hPreviewBitmap ) 
							InvalidateRect( GetDlgItem( hwndDlg, IDC_PREVIEW ), NULL, TRUE );
						else  //prepare text
						{
							TCHAR Author[255];
							TCHAR URL[MAX_PATH];
							TCHAR Contact[255];
							TCHAR Description[400];
							TCHAR text[2000];
							SkinListData* sd = NULL;
							HTREEITEM hti = TreeView_GetSelection( GetDlgItem( hwndDlg, IDC_TREE1 ) );				
							if ( hti == 0 ) return 0;
							{
								TVITEM tvi = {0};
								tvi.hItem = hti;
								tvi.mask = TVIF_HANDLE|TVIF_PARAM;
								TreeView_GetItem( GetDlgItem( hwndDlg, IDC_TREE1 ), &tvi );
								sd = ( SkinListData* )( tvi.lParam );
							}
							if ( !sd ) return 0;

							if( sd->File && !_tcschr( sd->File, _T('%') ) )
							{
								GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Author" ), 	TranslateT( "( unknown )" ), 	Author, 		SIZEOF( Author ), 		sd->File );
								GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "URL" ), 		_T( "" ), 						URL, 		SIZEOF( URL ), 		sd->File );
								GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Contact" ), 	_T( "" ), 						Contact, 	SIZEOF( Contact ), 	sd->File );
								GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Description" ), _T( "" ), 					Description, SIZEOF( Description ), sd->File );
								_sntprintf( text, SIZEOF( text ), TranslateT( "Preview is not available\n\n%s\n----------------------\n\n%s\n\nAUTHOR(S):\n%s\n\nCONTACT:\n%s\n\nHOMEPAGE:\n%s" ), 
									sd->Name, Description, Author, Contact, URL );
							}
							else
							{
								_sntprintf( text, SIZEOF( text ), TranslateT( "%s\n\n%s\n\nAUTHORS:\n%s\n\nCONTACT:\n%s\n\nWEB:\n%s\n\n\n" ), 
									TranslateT( "reVista for Modern v0.5" ), 
									TranslateT( "This is second default Modern Contact list skin in Vista Aero style" ), 
									TranslateT( "graphics by Angeli-Ka\ntemplate by FYR" ), 
									_T("JID: [email protected]"), 
									_T("fyr.mirandaim.ru") );
							}
							ShowWindow( GetDlgItem( hwndDlg, IDC_PREVIEW ), SW_HIDE );
							ShowWindow( GetDlgItem( hwndDlg, IDC_STATIC_INFO ), SW_SHOW );
							SendDlgItemMessage( hwndDlg, IDC_STATIC_INFO, WM_SETTEXT, 0, ( LPARAM )text );
						}					
					}
					else
					{
						//no selected
						SendDlgItemMessage( hwndDlg, IDC_EDIT_SKIN_FILENAME, WM_SETTEXT, 0, ( LPARAM )TranslateT( "Select skin from list" ) );
						EnableWindow( GetDlgItem( hwndDlg, IDC_BUTTON_APPLY_SKIN ), FALSE );
						EnableWindow( GetDlgItem( hwndDlg, IDC_BUTTON_INFO ), FALSE );
						SendDlgItemMessage( hwndDlg, IDC_STATIC_INFO, WM_SETTEXT, 0, ( LPARAM )TranslateT( "Please select skin to apply" ) );
						ShowWindow( GetDlgItem( hwndDlg, IDC_PREVIEW ), SW_HIDE );
					}
					ShowWindow( GetDlgItem( hwndDlg, IDC_PREVIEW ), hPreviewBitmap?SW_SHOW:SW_HIDE );
					return 0;
				}			
				else if ( nmtv->hdr.code == TVN_DELETEITEMA || nmtv->hdr.code == TVN_DELETEITEMW )
				{
					if ( nmtv->itemOld.lParam )
						mir_free_and_nill( nmtv->itemOld.lParam );
					return 0;
				}
				break;
			}
		case 0:
			switch ( ( ( LPNMHDR )lParam )->code )
			{
			case PSN_APPLY:
				{
					{
						DWORD tick = GetTickCount( );
						pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, 0, 0 );
						NotifyEventHooks( g_CluiData.hEventBkgrChanged, 0, 0 );
						pcli->pfnClcBroadcast( INTM_INVALIDATE, 0, 0 );	
						RedrawWindow( GetParent( pcli->hwndContactTree ), NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_ALLCHILDREN );
					}
					return 0;
				}
				break;
			}
			break;
		}
	}