示例#1
0
void cImage::DrawAlpha( HDC hdc, int x, int y, RECT& rcSour, BYTE alpha)
{

	DWORD sourW = rcSour.right - rcSour.left;
	DWORD sourH = rcSour.bottom - rcSour.top;
	DWORD sourX = rcSour.left;
	DWORD sourY = rcSour.top;


	m_BlendFunc.SourceConstantAlpha = alpha;

	//컬러키값이 있을때....
	if( m_TransColorKey != -1 ){

		//1. hdc TargetDC 내용을 BlendDC 에 그린다.
		BitBlt( 
			m_BlendDC, 
			0, 0, sourW, sourH,
			hdc, x, y, SRCCOPY );

		//2. Sour의 내용을 BlendDC 에 그린다.
		GdiTransparentBlt(
			m_BlendDC,				//Target DC
			0, 0,					//Target DC 위치
			sourW, sourH,  //크리기 가로세로 량
			m_BitDC,				//Source DC
			sourX, sourY,					//Source 시작
			sourW, sourH,
			m_TransColorKey );

		//3. BlendDC 의 내용을 hdc 에 Alpha 블렌드로 그린다.
		GdiAlphaBlend(
			hdc, 
			x, y, 
			sourW, sourH,
			m_BlendDC, 
			0, 0,
			sourW, sourH,
			m_BlendFunc );

	}

	//컬러 키 값이 없을때..
	else{
		GdiAlphaBlend(
			hdc, 
			x, y, 
			sourW, sourH,
			m_BitDC, 
			sourX, sourY,
			sourW, sourH,
			m_BlendFunc );

	}
}
示例#2
0
void cImage::DrawAlpha( HDC hdc, int x, int y, BYTE alpha )
{
	m_BlendFunc.SourceConstantAlpha = alpha;

	//컬러키값이 있을때....
	if( m_TransColorKey != -1 ){
		
		//1. hdc TargetDC 내용을 BlendDC 에 그린다.
		BitBlt( 
			m_BlendDC, 
			0, 0, m_dwWidth, m_dwHeight,
			hdc, x, y, SRCCOPY );

		//2. Sour의 내용을 BlendDC 에 그린다.
		GdiTransparentBlt(
			m_BlendDC,				//Target DC
			0, 0,					//Target DC 위치
			m_dwWidth, m_dwHeight,  //크리기 가로세로 량
			m_BitDC,				//Source DC
			0, 0,					//Source 시작
			m_dwWidth, m_dwHeight,
			m_TransColorKey );

		//3. BlendDC 의 내용을 hdc 에 Alpha 블렌드로 그린다.
		GdiAlphaBlend(
			hdc, 
			x, y, 
			m_dwWidth, m_dwHeight,
			m_BlendDC, 
			0, 0, 
			m_dwWidth, m_dwHeight,
			m_BlendFunc );
	}

	//컬러 키 값이 없을때..
	else{
		GdiAlphaBlend(
			hdc, 
			x, y, 
			m_dwWidth, m_dwHeight,
			m_BitDC, 
			0, 0, 
			m_dwWidth, m_dwHeight,
			m_BlendFunc );

	}
}
示例#3
0
/**
 * render basic button content like nickname and icon. Used for the basic layouts
 * only. Pretty much the same code as used for the tabs.
 *
 * @param hdc	 : target device context
 * @param rcItem : rectangle to render into
 */
void CSideBarButton::renderIconAndNick(const HDC hdc, const RECT *rcItem) const
{
	HICON	hIcon;
	RECT	rc = *rcItem;
	DWORD	dwTextFlags = DT_SINGLELINE | DT_VCENTER;
	int		stateId = m_buttonControl->stateId;
	int		iSize = 16;
	const 	TContainerData *pContainer = m_sideBar->getContainer();

	if (m_dat && pContainer) {
		hIcon = m_dat->cache->getIcon(iSize);

		if (m_dat->mayFlashTab == FALSE || (m_dat->mayFlashTab == TRUE && m_dat->bTabFlash != 0) || !(pContainer->dwFlagsEx & TCF_FLASHICON)) {
			DWORD ix = rc.left + 4;
			DWORD iy = (rc.bottom + rc.top - iSize) / 2;
			if (m_dat->dwFlagsEx & MWF_SHOW_ISIDLE && PluginConfig.m_bIdleDetect)
				CSkin::DrawDimmedIcon(hdc, ix, iy, iSize, iSize, hIcon, 180);
			else
				::DrawIconEx(hdc, ix, iy, hIcon, iSize, iSize, 0, NULL, DI_NORMAL | DI_COMPAT);
		}

		rc.left += (iSize + 7);

		/*
		 * draw the close button if enabled
		 */
		if (m_sideBar->getContainer()->dwFlagsEx & TCF_CLOSEBUTTON) {
			if (m_sideBar->getHoveredClose() != this)
				CSkin::m_default_bf.SourceConstantAlpha = 150;

			GdiAlphaBlend(hdc, rc.right - 20, (rc.bottom + rc.top - 16) / 2, 16, 16, CSkin::m_tabCloseHDC, 0, 0, 16, 16, CSkin::m_default_bf);

			rc.right -= 19;
			CSkin::m_default_bf.SourceConstantAlpha = 255;
		}

		::SetBkMode(hdc, TRANSPARENT);

		if (m_dat->mayFlashTab == FALSE || (m_dat->mayFlashTab == TRUE && m_dat->bTabFlash != 0) || !(pContainer->dwFlagsEx & TCF_FLASHLABEL)) {
			bool  	 fIsActive = (m_sideBar->getActiveItem() == this ? true : false);
			COLORREF clr = 0;
			dwTextFlags |= DT_WORD_ELLIPSIS;

			if (fIsActive || stateId == PBS_PRESSED)
				clr = PluginConfig.tabConfig.colors[1];
			else if (stateId == PBS_HOT)
				clr = PluginConfig.tabConfig.colors[3];
			else
				clr = PluginConfig.tabConfig.colors[0];

			CSkin::RenderText(hdc, m_buttonControl->hThemeButton, m_dat->newtitle, &rc, dwTextFlags, CSkin::m_glowSize, clr);
		}
	}
}
示例#4
0
void ImageFType::DrawInternal(HDC hdc, int x, int y, int sizeX, int sizeY)
{
	if (m_bmp == NULL) return;

	HDC hdcImg = CreateCompatibleDC(hdc);
	HBITMAP oldBmp = (HBITMAP)SelectObject(hdcImg, m_bmp);

	BITMAP bm;
	GetObject(m_bmp, sizeof(bm), &bm);

	if (bm.bmBitsPixel == 32) {
		BLENDFUNCTION bf = { 0 };
		bf.SourceConstantAlpha = 255;
		bf.AlphaFormat = AC_SRC_ALPHA;
		GdiAlphaBlend(hdc, x, y, sizeX, sizeY, hdcImg, 0, 0, bm.bmWidth, bm.bmHeight, bf);
	}
	else BitBlt(hdc, x, y, sizeX, sizeY, hdcImg, 0, 0, SRCCOPY);

	SelectObject(hdcImg, oldBmp);
	DeleteDC(hdcImg);
}
示例#5
0
/**
 * content renderer for the advanced side bar button layout. includes
 * avatars
 */
void __fastcall CSideBar::m_AdvancedContentRenderer(const HDC hdc, const RECT *rcBox,
	const CSideBarButton *item)
{
	const TWindowData *dat = item->getDat();
	UINT id = item->getID();

	LONG	cx = rcBox->right - rcBox->left;
	LONG	cy = rcBox->bottom - rcBox->top;
	SIZE	szFirstLine, szSecondLine;

	if (id == IDC_SIDEBARUP || id == IDC_SIDEBARDOWN)
		m_DefaultContentRenderer(hdc, rcBox, item);
	else if (dat) {
		RECT rc = *rcBox;

		if (dat->ace && dat->ace->hbmPic) {		// we have an avatar
			double	dNewHeight, dNewWidth;
			LONG	maxHeight = cy - 8;
			bool	fFree = false;

			Utils::scaleAvatarHeightLimited(dat->ace->hbmPic, dNewWidth, dNewHeight, maxHeight);

			HBITMAP hbmResized = CSkin::ResizeBitmap(dat->ace->hbmPic, dNewWidth, dNewHeight, fFree);
			HDC		dc = CreateCompatibleDC(hdc);
			HBITMAP hbmOld = reinterpret_cast<HBITMAP>(::SelectObject(dc, hbmResized));

			LONG	xOff = (cx - maxHeight) + (maxHeight - (LONG)dNewWidth) / 2 - 4;
			LONG	yOff = (cy - (LONG)dNewHeight) / 2;

			GdiAlphaBlend(hdc, xOff, yOff, (LONG)dNewWidth, (LONG)dNewHeight, dc, 0, 0, (LONG)dNewWidth, (LONG)dNewHeight, CSkin::m_default_bf);
			::SelectObject(dc, hbmOld);
			if (hbmResized != dat->ace->hbmPic)
				::DeleteObject(hbmResized);
			::DeleteDC(dc);
			rc.right -= (maxHeight + 6);
		}

		/*
		 * calculate metrics based on font configuration. Determine if we have enough
		 * space for both lines
		 */

		rc.left += 3;
		HFONT	hOldFont = reinterpret_cast<HFONT>(::SelectObject(hdc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_NICK]));
		::GetTextExtentPoint32A(hdc, "A", 1, &szFirstLine);
		::SelectObject(hdc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_STATUS]);
		::GetTextExtentPoint32A(hdc, "A", 1, &szSecondLine);
		szSecondLine.cy = max(szSecondLine.cy, 18);

		LONG	required = szFirstLine.cy + szSecondLine.cy;
		bool	fSecondLine = (required < cy ? true : false);

		DWORD	dtFlags = DT_SINGLELINE | DT_WORD_ELLIPSIS | DT_END_ELLIPSIS | (!fSecondLine ? DT_VCENTER : 0);

		::SelectObject(hdc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_NICK]);
		rc.top++;
		::SetBkMode(hdc, TRANSPARENT);
		CSkin::RenderText(hdc, dat->hThemeIP, dat->cache->getNick(), &rc,
			dtFlags, CSkin::m_glowSize, CInfoPanel::m_ipConfig.clrs[IPFONTID_NICK]);

		if (fSecondLine) {
			int		iSize;
			HICON	hIcon = dat->cache->getIcon(iSize);

			/*
			 * TODO support larger icons at a later time. This side bar button
			 * could use 32x32 icons as well.
			 */

			rc.top = rc.bottom - szSecondLine.cy - 2;
			::DrawIconEx(hdc, rc.left, rc.top + (rc.bottom - rc.top) / 2 - 8, hIcon, 16, 16, 0, 0, DI_NORMAL);
			rc.left += 18;
			::SelectObject(hdc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_STATUS]);
			CSkin::RenderText(hdc, dat->hThemeIP, dat->szStatus, &rc,
				dtFlags | DT_VCENTER, CSkin::m_glowSize, CInfoPanel::m_ipConfig.clrs[IPFONTID_STATUS]);
		}
		::SelectObject(hdc, hOldFont);
	}
}
示例#6
0
bool CBackground::FillBackground(
	const BITMAPFILEHEADER* apBkImgData, // Содержимое *.bmp файла
	LONG X, LONG Y, LONG Width, LONG Height, // Куда нужно положить картинку
	BackgroundOp Operation,              // {eUpLeft = 0, eStretch = 1, eTile = 2, eUpRight = 4, ...}
	bool abFade)                         // затемнение картинки, когда ConEmu НЕ в фокусе
{
	if (!hBgDc)
		return false;

	// Залить черным фоном
	RECT rcFull = MakeRect(X,Y,Width,Height);
	FillRect(hBgDc, &rcFull, (HBRUSH)GetStockObject(BLACK_BRUSH));

	if (apBkImgData == NULL ||
	        apBkImgData->bfType != 0x4D42/*BM*/ ||
	        IsBadReadPtr(apBkImgData, apBkImgData->bfSize))
	{
		return false;
	}

	bool lbRc = false;
	HDC         hLoadDC = NULL;
	HBITMAP     hLoadBmp = NULL;
	BITMAPINFO* pBmp  = (BITMAPINFO*)(apBkImgData+1);
	LPBYTE      pBits = ((LPBYTE)apBkImgData) + apBkImgData->bfOffBits;
	LPVOID      pDstBits = NULL;
	BITMAPINFOHEADER* pHdr = &pBmp->bmiHeader;

	if (pHdr->biPlanes != 1 || pHdr->biCompression != BI_RGB)  // BI_JPEG|BI_PNG
	{
		return false;
	}

	DWORD       nBitSize = apBkImgData->bfSize - apBkImgData->bfOffBits;
	TODO("Stride?");
	DWORD       nCalcSize = (pHdr->biWidth * pHdr->biHeight * pHdr->biBitCount) >> 3;

	if (nBitSize > nCalcSize)
		nBitSize = nCalcSize;

	if (!gpSet->isFadeInactive)
		abFade = false;

	// Создать MemoryDC
	const HDC hScreenDC = GetDC(ghWnd);

	if (hScreenDC)
	{
		hLoadDC = CreateCompatibleDC(hScreenDC);
		ReleaseDC(ghWnd, hScreenDC);

		if (hLoadDC)
		{
			hLoadBmp = CreateDIBSection(hLoadDC, pBmp, DIB_RGB_COLORS, &pDstBits, NULL, 0);

			if (hLoadBmp && pDstBits)
			{
				// Поместить биты из apBkImgData в hLoadDC
				HBITMAP hOldLoadBmp = (HBITMAP)SelectObject(hLoadDC, hLoadBmp);
				memmove(pDstBits, pBits, nBitSize);
				GdiFlush(); // Гарантировать commit битов
				// Теперь - скопировать биты из hLoadDC в hBgDc с учетом положения и Operation
				BLENDFUNCTION bf = {AC_SRC_OVER, 0, gpSet->bgImageDarker, 0};

				if (abFade)
				{
					// GetFadeColor возвращает ColorRef, поэтому при вызове для (0..255)
					// он должен вернуть "коэффициент" затемнения или осветления
					DWORD nHigh = (gpSet->GetFadeColor(255) & 0xFF);

					if (nHigh < 255)
					{
						// Затемнение фона
						bf.SourceConstantAlpha = LOBYTE(nHigh * bf.SourceConstantAlpha / 255);
					}

					//// "коэффициент" вернется в виде RGB (R==G==B)
					//DWORD nLow = gpSet->GetFadeColor(0);
					//if (nLow > 0 && ((nLow & 0xFF) < nHigh))
					//{
					//	// Осветление фона
					//	RECT r = {X,Y,X+Width,Y+Height};
					//	HBRUSH h = CreateSolidBrush(nLow);
					//	FillRect(hBgDc, &r, h);
					//	DeleteObject(h);
					//	// еще нужно убедиться, что сама картинка будет немного прозрачной,
					//	// чтобы это осветление было заметно
					//	if ((nLow & 0xFF) < 200)
					//		bf.SourceConstantAlpha = klMin((int)bf.SourceConstantAlpha, (int)(255 - (nLow & 0xFF)));
					//	else if (bf.SourceConstantAlpha >= 240)
					//		bf.SourceConstantAlpha = 240;
					//}
				}

				if ((Operation == eUpLeft) || (Operation == eUpRight)
					|| (Operation == eDownLeft) || (Operation == eDownRight)
					|| (Operation == eCenter))
				{
					int W = klMin(Width,pHdr->biWidth); int H = klMin(Height,pHdr->biHeight);

					if (GdiAlphaBlend(hBgDc, X, Y, W, H, hLoadDC, 0, 0, W, H, bf))
						lbRc = true;
				}
				else if (Operation == eStretch || Operation == eFit)
				{
					if (GdiAlphaBlend(hBgDc, X, Y, Width, Height, hLoadDC, 0, 0, pHdr->biWidth, pHdr->biHeight, bf))
						lbRc = true;
				}
				else if (Operation == eFill)
				{
					int srcX = 0, srcY = 0, srcW = pHdr->biWidth, srcH = pHdr->biHeight;
					if (Width && Width > Height)
					{
						srcH = klMin((srcW * Height / Width), _abs(pHdr->biHeight));
						srcY = (pHdr->biHeight - srcH) / 2;
					}
					else if (Height)
					{
						srcW = klMin((srcH * Width / Height), pHdr->biWidth);
						srcX = (pHdr->biWidth - srcW) / 2;
					}

					if (GdiAlphaBlend(hBgDc, X, Y, Width, Height, hLoadDC, srcX, srcY, srcW, srcH, bf))
						lbRc = true;
				}
				else if (Operation == eTile)
				{
					for (int DY = Y; DY < (Y+Height); DY += pHdr->biHeight)
					{
						for (int DX = X; DX < (X+Width); DX += pHdr->biWidth)
						{
							int W = klMin((Width-DX),pHdr->biWidth);
							int H = klMin((Height-DY),pHdr->biHeight);

							if (GdiAlphaBlend(hBgDc, DX, DY, W, H, hLoadDC, 0, 0, W, H, bf))
								lbRc = true;
						}
					}
				}

				_ASSERTE(lbRc && "GdiAlphaBlend failed in background creation?");

				TODO("Осветление картинки в Fade, когда gpSet->mn_FadeLow>0");
				//if (abFade)
				//{
				//	// "коэффициент" вернется в виде RGB (R==G==B)
				//	DWORD nLow = gpSet->GetFadeColor(0);
				//	if (nLow)
				//	{
				//		// Осветление фона
				//		RECT r = {X,Y,X+Width,Y+Height};
				//		HBRUSH h = CreateSolidBrush(nLow);
				//		// Осветлить картинку
				//		//FillRect(hBgDc, &r, h);
				//		DeleteObject(h);
				//	}
				//}
				SelectObject(hLoadDC, hOldLoadBmp);
			}

			if (hLoadBmp)
			{
				DeleteObject(hLoadBmp);
				hLoadBmp = NULL;
			}

			DeleteDC(hLoadDC);
			hLoadDC = NULL;
		}
	}

	return lbRc;
}
DWORD WINAPI ScriptThread(LPVOID p)
{
	HWND hWnd=(HWND)p;
	HBRUSH brush;
	HBITMAP bmp;
	HDC hDC, hMemDC;
	RECT rect;
	SIZE size;
	int i,j,x,y,len;
	Sleep(100);
	hDC = GetDC(hWnd);
	hMemDC = CreateCompatibleDC( hDC );
	GetClientRect(hWnd,&rect);
	bmp = CreateCompatibleBitmap(hDC, rect.right, rect.bottom);
	hFont = CreateFont( 30, 0, 0, 0, FW_THIN,
		FALSE, FALSE, FALSE,
		DEFAULT_CHARSET,
		OUT_DEFAULT_PRECIS,
		CLIP_DEFAULT_PRECIS,
		DEFAULT_QUALITY,
		DEFAULT_PITCH |
		FF_DONTCARE,
		L"MS Mincho" );
	SelectObject(hDC, hFont);
	SelectObject(hMemDC, hFont);
	SelectObject(hMemDC, bmp);
	brush = CreateSolidBrush(RGB(0xFF,0xFF,0xFF));
	FillRect(hMemDC,&rect,brush);
	FillRect(hDC,&rect,brush);

	TEXTMETRIC tm;
	GetTextMetrics(hDC,&tm);
	len=wcslen(str);
	size.cx=tm.tmMaxCharWidth*len;
	size.cy=tm.tmHeight+10;
	IthDrawText(hMemDC, str, len, 0, 0);

	ftn.SourceConstantAlpha=0x20;
	for (i=0;i<alpha_depth;i++)
	{
		if (!running) break;
		Sleep(100);
		GetClientRect(hWnd,&rect);
		GdiAlphaBlend(hDC, (rect.right-size.cx)>>1, (rect.bottom-size.cy)>>1, size.cx, size.cy, hMemDC, 0, 0, size.cx, size.cy, ftn);
		UpdateWindow(hWnd);
	}
	FillRect(hMemDC,&rect,brush);

	for (i=0;i<alpha_depth;i++)
	{
		if (!running) break;
		Sleep(100);
		GdiAlphaBlend(hDC, (rect.right-size.cx)>>1, (rect.bottom-size.cy)>>1, size.cx, size.cy, hMemDC, 0, 0, size.cx, size.cy, ftn);
		UpdateWindow(hWnd);
	}
	FillRect(hDC,&rect,brush);

	SelectObject(hMemDC,hFont);
	for (i=0;i<sentence_count;i++)
	{
		len=wcslen(text[i]);
		size.cx=len*tm.tmMaxCharWidth;
		size.cy=tm.tmHeight+10;
		HBITMAP text_bmp=CreateCompatibleBitmap(hDC, size.cx, size.cy);
		RECT r={0,0,size.cx, size.cy};
		SelectObject(hMemDC,text_bmp);
		FillRect(hMemDC,&r,brush);
		IthDrawText(hMemDC,text[i],len,0,0);
		j=0; y=0; 
		x=0; click=0;
		while (len>char_per_line)
		{
			size.cx=char_per_line*tm.tmMaxCharWidth;
			len-=char_per_line;
			j=20;		
			while (j<size.cx)
			{
				if (click) break;
				GdiAlphaBlend(hDC, 0, y, j, size.cy, hMemDC, x, 0, j, size.cy, ftn);
				Sleep(20);
				j+=20;

			}
			BitBlt(hDC,0, y, size.cx, size.cy, hMemDC, x, 0, SRCCOPY);
			y+=size.cy;
			x+=size.cx;
		}
		size.cx=len*tm.tmMaxCharWidth;
		j=20;
		while (j<size.cx)
		{
			if (click) break;
			GdiAlphaBlend(hDC, 0, y, j, size.cy, hMemDC, x, 0, j, size.cy, ftn);
			Sleep(20);
			j+=20;
		}
		BitBlt(hDC,0, y, size.cx, size.cy, hMemDC, x, 0, SRCCOPY);
		y+=size.cy;
		UpdateWindow(hWnd);
		SelectObject(hMemDC,bmp);
		DeleteObject(text_bmp);
		ResetEvent(hClickEvent);
		WaitForSingleObject(hClickEvent,-1);
		ResetEvent(hClickEvent);
		FillRect(hDC,&rect,brush);
	}

	DeleteDC(hMemDC);
	ReleaseDC(hWnd, hDC);
	DeleteObject(bmp);
	MessageBox(0,L"Script over.",L"Over",0);
	return 0;
}
示例#8
0
static INT_PTR CALLBACK PhotoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	const unsigned long iPageId = 3;

	TCHAR szAvatarFileName[MAX_PATH], szTempPath[MAX_PATH], szTempFileName[MAX_PATH];
	PhotoDlgProcData* dat = (PhotoDlgProcData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);

	switch (msg) {
	case WM_INITDIALOG:
		if (!lParam) break; // Launched from userinfo
		TranslateDialogDefault(hwndDlg);
		SendDlgItemMessage(hwndDlg, IDC_LOAD, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(hInst, MAKEINTRESOURCE(IDI_OPEN), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0));
		SendDlgItemMessage(hwndDlg, IDC_LOAD, BUTTONSETASFLATBTN, TRUE, 0);
		SendDlgItemMessage(hwndDlg, IDC_DELETE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(hInst, MAKEINTRESOURCE(IDI_DELETE), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0));
		SendDlgItemMessage(hwndDlg, IDC_DELETE, BUTTONSETASFLATBTN, TRUE, 0);
		ShowWindow(GetDlgItem(hwndDlg, IDC_SAVE), SW_HIDE);
		{
			dat = new PhotoDlgProcData;
			dat->ppro = (CJabberProto*)lParam;
			dat->hBitmap = NULL;
			dat->ppro->m_bPhotoChanged = FALSE;
			SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
			dat->ppro->WindowSubscribe(hwndDlg);
		}
		SendMessage(hwndDlg, WM_JABBER_REFRESH_VCARD, 0, 0);
		break;

	case WM_JABBER_REFRESH_VCARD:
		if (dat->hBitmap) {
			DeleteObject(dat->hBitmap);
			dat->hBitmap = NULL;
			DeleteFile(dat->ppro->m_szPhotoFileName);
			dat->ppro->m_szPhotoFileName[0] = '\0';
		}
		EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE);
		dat->ppro->GetAvatarFileName(NULL, szAvatarFileName, _countof(szAvatarFileName));
		if (_taccess(szAvatarFileName, 0) == 0) {
			if (GetTempPath(_countof(szTempPath), szTempPath) <= 0)
				mir_tstrcpy(szTempPath, _T(".\\"));
			if (GetTempFileName(szTempPath, _T("jab"), 0, szTempFileName) > 0) {
				dat->ppro->debugLog(_T("Temp file = %s"), szTempFileName);
				if (CopyFile(szAvatarFileName, szTempFileName, FALSE) == TRUE) {
					if ((dat->hBitmap = Bitmap_Load(szTempFileName)) != NULL) {
						FIP->FI_Premultiply(dat->hBitmap);
						mir_tstrcpy(dat->ppro->m_szPhotoFileName, szTempFileName);
						EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), TRUE);
					}
					else DeleteFile(szTempFileName);
				}
				else DeleteFile(szTempFileName);
			}
		}

		dat->ppro->m_bPhotoChanged = FALSE;
		InvalidateRect(hwndDlg, NULL, TRUE);
		UpdateWindow(hwndDlg);
		break;

	case WM_JABBER_CHANGED:
		dat->ppro->SetServerVcard(dat->ppro->m_bPhotoChanged, dat->ppro->m_szPhotoFileName);
		break;

	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDC_DELETE:
			if (dat->hBitmap) {
				DeleteObject(dat->hBitmap);
				dat->hBitmap = NULL;
				DeleteFile(dat->ppro->m_szPhotoFileName);
				dat->ppro->m_szPhotoFileName[0] = '\0';
				dat->ppro->m_bPhotoChanged = TRUE;
				EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE);
				InvalidateRect(hwndDlg, NULL, TRUE);
				UpdateWindow(hwndDlg);
				dat->ppro->m_vCardUpdates |= (1UL << iPageId);
				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
			}
			break;

		case IDC_LOAD:
			TCHAR szFilter[512], szFileName[MAX_PATH];
			Bitmap_GetFilter(szFilter, _countof(szFilter));

			OPENFILENAME ofn = { 0 };
			ofn.lStructSize = sizeof(ofn);
			ofn.hwndOwner = hwndDlg;
			ofn.lpstrFilter = szFilter;
			ofn.lpstrCustomFilter = NULL;
			ofn.lpstrFile = szFileName;
			ofn.nMaxFile = MAX_PATH;
			ofn.Flags = OFN_FILEMUSTEXIST | OFN_DONTADDTORECENT;
			szFileName[0] = '\0';
			if (GetOpenFileName(&ofn)) {
				struct _stat st;
				HBITMAP hNewBitmap;

				dat->ppro->debugLog(_T("File selected is %s"), szFileName);
				if (_tstat(szFileName, &st) < 0 || st.st_size > 40 * 1024) {
					MessageBox(hwndDlg, TranslateT("Only JPG, GIF, and BMP image files smaller than 40 KB are supported."), TranslateT("Jabber vCard"), MB_OK | MB_SETFOREGROUND);
					break;
				}
				if (GetTempPath(_countof(szTempPath), szTempPath) <= 0)
					mir_tstrcpy(szTempPath, _T(".\\"));
				
				if (GetTempFileName(szTempPath, _T("jab"), 0, szTempFileName) > 0) {
					dat->ppro->debugLog(_T("Temp file = %s"), szTempFileName);
					if (CopyFile(szFileName, szTempFileName, FALSE) == TRUE) {
						if ((hNewBitmap = Bitmap_Load(szTempFileName)) != NULL) {
							if (dat->hBitmap) {
								DeleteObject(dat->hBitmap);
								DeleteFile(dat->ppro->m_szPhotoFileName);
							}

							dat->hBitmap = hNewBitmap;
							mir_tstrcpy(dat->ppro->m_szPhotoFileName, szTempFileName);
							dat->ppro->m_bPhotoChanged = TRUE;
							EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), TRUE);
							InvalidateRect(hwndDlg, NULL, TRUE);
							UpdateWindow(hwndDlg);
							dat->ppro->m_vCardUpdates |= (1UL << iPageId);
							SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
						}
						else DeleteFile(szTempFileName);
					}
					else DeleteFile(szTempFileName);
				}
			}
			break;
		}
		break;

	case WM_PAINT:
		if (dat->hBitmap) {
			BITMAP bm;
			POINT ptSize, ptOrg, pt, ptFitSize;
			RECT rect;

			HWND hwndCanvas = GetDlgItem(hwndDlg, IDC_CANVAS);
			HDC hdcCanvas = GetDC(hwndCanvas);
			HDC hdcMem = CreateCompatibleDC(hdcCanvas);
			SelectObject(hdcMem, dat->hBitmap);
			SetMapMode(hdcMem, GetMapMode(hdcCanvas));
			GetObject(dat->hBitmap, sizeof(BITMAP), (LPVOID)&bm);
			ptSize.x = bm.bmWidth;
			ptSize.y = bm.bmHeight;
			DPtoLP(hdcCanvas, &ptSize, 1);
			ptOrg.x = ptOrg.y = 0;
			DPtoLP(hdcMem, &ptOrg, 1);
			GetClientRect(hwndCanvas, &rect);
			InvalidateRect(hwndCanvas, NULL, TRUE);
			UpdateWindow(hwndCanvas);
			if (ptSize.x <= rect.right && ptSize.y <= rect.bottom) {
				pt.x = (rect.right - ptSize.x) / 2;
				pt.y = (rect.bottom - ptSize.y) / 2;
				ptFitSize = ptSize;
			}
			else {
				if (((float)(ptSize.x - rect.right)) / ptSize.x > ((float)(ptSize.y - rect.bottom)) / ptSize.y) {
					ptFitSize.x = rect.right;
					ptFitSize.y = (ptSize.y*rect.right) / ptSize.x;
					pt.x = 0;
					pt.y = (rect.bottom - ptFitSize.y) / 2;
				}
				else {
					ptFitSize.x = (ptSize.x*rect.bottom) / ptSize.y;
					ptFitSize.y = rect.bottom;
					pt.x = (rect.right - ptFitSize.x) / 2;
					pt.y = 0;
				}
			}

			RECT rc;
			GetClientRect(hwndCanvas, &rc);
			if (IsThemeActive())
				DrawThemeParentBackground(hwndCanvas, hdcCanvas, &rc);
			else
				FillRect(hdcCanvas, &rc, (HBRUSH)GetSysColorBrush(COLOR_BTNFACE));

			if (bm.bmBitsPixel == 32) {
				BLENDFUNCTION bf = { 0 };
				bf.AlphaFormat = AC_SRC_ALPHA;
				bf.BlendOp = AC_SRC_OVER;
				bf.SourceConstantAlpha = 255;
				GdiAlphaBlend(hdcCanvas, pt.x, pt.y, ptFitSize.x, ptFitSize.y, hdcMem, ptOrg.x, ptOrg.y, ptSize.x, ptSize.y, bf);
			}
			else {
				SetStretchBltMode(hdcCanvas, COLORONCOLOR);
				StretchBlt(hdcCanvas, pt.x, pt.y, ptFitSize.x, ptFitSize.y, hdcMem, ptOrg.x, ptOrg.y, ptSize.x, ptSize.y, SRCCOPY);
			}

			DeleteDC(hdcMem);
		}
		break;

	case WM_NOTIFY:
		if (((LPNMHDR)lParam)->idFrom == 0) {
			switch (((LPNMHDR)lParam)->code) {
			case PSN_PARAMCHANGED:
				SendMessage(hwndDlg, WM_INITDIALOG, 0, ((PSHNOTIFY*)lParam)->lParam);
				break;

			case PSN_APPLY:
				dat->ppro->m_vCardUpdates &= ~(1UL << iPageId);
				dat->ppro->SaveVcardToDB(hwndDlg, iPageId);
				if (!dat->ppro->m_vCardUpdates)
					dat->ppro->SetServerVcard(dat->ppro->m_bPhotoChanged, dat->ppro->m_szPhotoFileName);
				break;
			}
		}
		break;

	case WM_DESTROY:
		DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_LOAD, BM_SETIMAGE, IMAGE_ICON, 0));
		DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_DELETE, BM_SETIMAGE, IMAGE_ICON, 0));
		dat->ppro->WindowUnsubscribe(hwndDlg);
		if (dat->hBitmap) {
			dat->ppro->debugLogA("Delete bitmap");
			DeleteObject(dat->hBitmap);
			DeleteFile(dat->ppro->m_szPhotoFileName);
		}
		delete dat;
		break;
	}
	return FALSE;
}