コード例 #1
0
ファイル: acc.cpp プロジェクト: 0xmono/miranda-ng
void StartFlash(HWND hwnd, ACCData* data)
{
	if (!ServiceExists(MS_FAVATAR_MAKE))
		return;

	int format;
	if (data->hContact != NULL)
	{
		format = db_get_w(data->hContact, "ContactPhoto", "Format", 0);
	}
	else if (data->proto[0] != '\0')
	{
		protoPicCacheEntry *ace = NULL;
		for (int i = 0; i < g_MyAvatars.getCount(); i++)
		{
			if (!lstrcmpA(data->proto, g_MyAvatars[i].szProtoname))
			{
				ace = &g_MyAvatars[i];
				break;
			}
		}

		if (ace != NULL && ace->szFilename != NULL)
			format = ProtoGetAvatarFormat(ace->szFilename);
		else
			format = 0;
	}
	else
		return;

	if (format != PA_FORMAT_XML && format != PA_FORMAT_SWF)
		return;

	FLASHAVATAR fa = {0};
	fa.hContact = data->hContact;
	fa.cProto = data->proto;
	fa.hParentWindow = hwnd;
	fa.id = 1675;
	CallService(MS_FAVATAR_MAKE, (WPARAM)&fa, 0);

	if (fa.hWindow == NULL)
		return;

	data->showingFlash = TRUE;
	ResizeFlash(hwnd, data);
	SetBkgFlash(hwnd, data);
}
コード例 #2
0
BOOL StartFlash(HWND hwnd, ACCData* data)
{
	if ((data->hContact != NULL || data->proto[0] != '\0')
		&& ServiceExists(MS_FAVATAR_MAKE))
	{
		FLASHAVATAR fa = {0}; 
        fa.hContact = data->hContact;
		fa.cProto = data->proto;
		fa.hParentWindow = hwnd;
        fa.id = 1675;
		CallService(MS_FAVATAR_MAKE, (WPARAM)&fa, 0);

		if (fa.hWindow != NULL) 
		{
			ResizeFlash(hwnd, data);
			SetBkgFlash(hwnd, data);
			return TRUE;
		}
	}

	return FALSE;
}
コード例 #3
0
ファイル: acc.cpp プロジェクト: 0xmono/miranda-ng
static LRESULT CALLBACK ACCWndProc(HWND hwnd, UINT msg,  WPARAM wParam, LPARAM lParam) {
	ACCData* data =  (ACCData *) GetWindowLongPtr(hwnd, 0);
	switch(msg)
	{
		case WM_NCCREATE:
		{
			SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) | BS_OWNERDRAW);
			SetWindowLongPtr(hwnd, GWL_EXSTYLE, GetWindowLongPtr(hwnd, GWL_EXSTYLE) | WS_EX_TRANSPARENT);

			data = (ACCData*) mir_alloc(sizeof(ACCData));
			if (data == NULL)
				return FALSE;
			SetWindowLongPtr(hwnd, 0, (LONG_PTR)data);

			ZeroMemory(data, sizeof(ACCData));
			data->hHook = HookEventMessage(ME_AV_AVATARCHANGED, hwnd, DM_AVATARCHANGED);
			data->hHookMy = HookEventMessage(ME_AV_MYAVATARCHANGED, hwnd, DM_MYAVATARCHANGED);
			data->hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
			data->borderColor = -1;
			data->bkgColor = -1;
			data->avatarBorderColor = -1;
			data->respectHidden = TRUE;
			data->showingFlash = FALSE;
			data->resizeIfSmaller = TRUE;
			data->showingAnimatedGif = FALSE;
			data->fAero = FALSE;

			return TRUE;
		}
		case WM_NCDESTROY:
		{
			DestroyAnimation(hwnd, data);
			if (data)
			{
				UnhookEvent(data->hHook);
				UnhookEvent(data->hHookMy);
				mir_free(data);
			}
			SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL);
			break;
		}
		case WM_SETFONT:
		{
			data->hFont = (HFONT)wParam;
			Invalidate(hwnd);
			break;
		}
		case AVATAR_SETCONTACT:
		{
			DestroyAnimation(hwnd, data);

			data->hContact = lParam;
			if (lParam == NULL)
				data->proto[0] = '\0';
			else
				lstrcpynA(data->proto, GetContactProto(data->hContact), sizeof(data->proto));

			StartAnimation(hwnd, data);

			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETPROTOCOL:
		{
			DestroyAnimation(hwnd, data);

			data->hContact = NULL;
			if (lParam == NULL)
				data->proto[0] = '\0';
			else
				lstrcpynA(data->proto, (char *) lParam, sizeof(data->proto));

			StartAnimation(hwnd, data);

			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETBKGCOLOR:
		{
			data->bkgColor = (COLORREF) lParam;
			if (data->showingFlash)
				SetBkgFlash(hwnd, data);
			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETBORDERCOLOR:
		{
			data->borderColor = (COLORREF) lParam;
			if (data->showingFlash)
				ResizeFlash(hwnd, data);
			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETAVATARBORDERCOLOR:
		{
			data->avatarBorderColor = (COLORREF) lParam;
			if (data->showingFlash)
				ResizeFlash(hwnd, data);
			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETAVATARROUNDCORNERRADIUS:
		{
			data->avatarRoundCornerRadius = (int) lParam;
			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETNOAVATARTEXT:
		{
			lstrcpyn(data->noAvatarText, TranslateTS((TCHAR*) lParam), SIZEOF(data->noAvatarText));
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_RESPECTHIDDEN:
		{
			data->respectHidden = (BOOL) lParam;
			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETRESIZEIFSMALLER:
		{
			data->resizeIfSmaller = (BOOL) lParam;
			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}

		case AVATAR_SETAEROCOMPATDRAWING:
			data->fAero = lParam;
			return(TRUE);

		case AVATAR_GETUSEDSPACE:
		{
			int *width = (int *)wParam;
			int *height = (int *)lParam;

			RECT rc;
			GetClientRect(hwnd, &rc);

			// Get avatar
			if (data->showingFlash && ServiceExists(MS_FAVATAR_GETINFO))
			{
				FLASHAVATAR fa = {0};
				fa.hContact = data->hContact;
				fa.cProto = data->proto;
				fa.hParentWindow = hwnd;
				fa.id = 1675;
				CallService(MS_FAVATAR_GETINFO, (WPARAM)&fa, 0);
				if (fa.hWindow != NULL)
				{
					*width = rc.right - rc.left;
					*height = rc.bottom - rc.top;
					return TRUE;
				}
			}

			avatarCacheEntry *ace;
			if (data->hContact == NULL)
				ace = (avatarCacheEntry *) CallService(MS_AV_GETMYAVATAR, 0, (LPARAM) data->proto);
			else
				ace = (avatarCacheEntry *) CallService(MS_AV_GETAVATARBITMAP, (WPARAM) data->hContact, 0);

			if (ace == NULL || ace->bmHeight == 0 || ace->bmWidth == 0
				|| (data->respectHidden && (ace->dwFlags & AVS_HIDEONCLIST)))
			{
				*width = 0;
				*height = 0;
				return TRUE;
			}

			// Get its size
			int targetWidth = rc.right - rc.left;
			int targetHeight = rc.bottom - rc.top;

			if (!data->resizeIfSmaller && ace->bmHeight <= targetHeight && ace->bmWidth <= targetWidth)
			{
				*height = ace->bmHeight;
				*width = ace->bmWidth;
			}
			else if (ace->bmHeight > ace->bmWidth)
			{
				float dScale = targetHeight / (float)ace->bmHeight;
				*height = targetHeight;
				*width = (int) (ace->bmWidth * dScale);
			}
			else
			{
				float dScale = targetWidth / (float)ace->bmWidth;
				*height = (int) (ace->bmHeight * dScale);
				*width = targetWidth;
			}

			return TRUE;
		}
		case DM_AVATARCHANGED:
		{
			if (data->hContact == wParam)
			{
				DestroyAnimation(hwnd, data);
				StartAnimation(hwnd, data);

				NotifyAvatarChange(hwnd);
				Invalidate(hwnd);
			}
			break;
		}
		case DM_MYAVATARCHANGED:
		{
			if (data->hContact == NULL && strcmp(data->proto, (char*) wParam) == 0)
			{
				DestroyAnimation(hwnd, data);
				StartAnimation(hwnd, data);

				NotifyAvatarChange(hwnd);
				Invalidate(hwnd);
			}
			break;
		}
		case WM_NCPAINT:
		case WM_PAINT:
		{
			PAINTSTRUCT ps;
			HDC hdc = BeginPaint(hwnd, &ps);
			if (hdc == NULL)
				break;

			int oldBkMode = SetBkMode(hdc, TRANSPARENT);
			SetStretchBltMode(hdc, HALFTONE);

			RECT rc;
			GetClientRect(hwnd, &rc);

			// Draw background
			if (data->bkgColor != -1)
			{
				HBRUSH hbrush = CreateSolidBrush(data->bkgColor);
				FillRect(hdc, &rc, hbrush);
				DeleteObject(hbrush);
			}

			if (data->hContact == NULL && data->proto[0] == '\0'
				&& db_get_b(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1))
			{
				DrawText(hdc, data->hFont, rc, TranslateT("Protocols have different avatars"));
			}

			// Has a flash avatar
			else if (data->showingFlash)
			{
				// Don't draw

				// Draw control border if needed
				if (data->borderColor == -1 && data->avatarBorderColor != -1)
				{
					HBRUSH hbrush = CreateSolidBrush(data->avatarBorderColor);
					FrameRect(hdc, &rc, hbrush);
					DeleteObject(hbrush);
				}
			}

			// Has an animated gif
			// Has a "normal" image
			else
			{
				// Draw avatar
				AVATARDRAWREQUEST avdrq = {0};
				avdrq.cbSize = sizeof(avdrq);
				avdrq.rcDraw = rc;
				avdrq.hContact = data->hContact;
				avdrq.szProto = data->proto;
				avdrq.hTargetDC = hdc;
				avdrq.dwFlags = AVDRQ_HIDEBORDERONTRANSPARENCY
					| (data->respectHidden ? AVDRQ_RESPECTHIDDEN : 0)
					| (data->hContact != NULL ? 0 : AVDRQ_OWNPIC)
					| (data->avatarBorderColor == -1 ? 0 : AVDRQ_DRAWBORDER)
					| (data->avatarRoundCornerRadius <= 0 ? 0 : AVDRQ_ROUNDEDCORNER)
					| (data->fAero ? AVDRQ_AERO : 0)
					| (data->resizeIfSmaller ? 0 : AVDRQ_DONTRESIZEIFSMALLER);
				avdrq.clrBorder = data->avatarBorderColor;
				avdrq.radius = data->avatarRoundCornerRadius;

				INT_PTR ret;
				if (data->showingAnimatedGif)
				{
					InternalDrawAvatar(&avdrq, data->ag.hbms[data->ag.frame.num], data->ag.logicalWidth, data->ag.logicalHeight, 0);
					ret = 1;

					if (!data->ag.started)
					{
						SetTimer(hwnd, 0, data->ag.times[data->ag.frame.num], NULL);
						data->ag.started = TRUE;
					}
				}
				else
					ret = DrawAvatarPicture(0, (LPARAM)&avdrq);

				if (ret == 0)
					DrawText(hdc, data->hFont, rc, data->noAvatarText);
			}

			// Draw control border
			if (data->borderColor != -1)
			{
				HBRUSH hbrush = CreateSolidBrush(data->borderColor);
				FrameRect(hdc, &rc, hbrush);
				DeleteObject(hbrush);
			}

			SetBkMode(hdc, oldBkMode);

			EndPaint(hwnd, &ps);
			return TRUE;
		}
		case WM_ERASEBKGND:
		{
			HDC hdc = (HDC) wParam;
			RECT rc;
			GetClientRect(hwnd, &rc);

			// Draw background
			if (data->bkgColor != -1)
			{
				HBRUSH hbrush = CreateSolidBrush(data->bkgColor);
				FillRect(hdc, &rc, hbrush);
				DeleteObject(hbrush);
			}

			// Draw control border
			if (data->borderColor != -1)
			{
				HBRUSH hbrush = CreateSolidBrush(data->borderColor);
				FrameRect(hdc, &rc, hbrush);
				DeleteObject(hbrush);
			}

			return TRUE;
		}
		case WM_SIZE:
		{
			if (data->showingFlash)
				ResizeFlash(hwnd, data);
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		}
		case WM_TIMER:
		{
			if (wParam != 0)
				break;
			KillTimer(hwnd, 0);

			if (!data->showingAnimatedGif)
				break;

			AnimatedGifDispodeFrame(data);

			int frame = data->ag.frame.num + 1;
			if (frame >= data->ag.frameCount)
			{
				// Don't need fi data no more
				AnimatedGifDeleteTmpValues(data);
				frame = 0;
			}
			AnimatedGifMountFrame(data, frame);

			data->ag.started = FALSE;
			InvalidateRect(hwnd, NULL, FALSE);

			break;
		}
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}
コード例 #4
0
static LRESULT CALLBACK ACCWndProc(HWND hwnd, UINT msg,  WPARAM wParam, LPARAM lParam) {
	ACCData* data =  (ACCData *) GetWindowLong(hwnd, 0);
	switch(msg) 
	{
		case WM_NCCREATE:
		{
			SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | BS_OWNERDRAW);
			SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_TRANSPARENT);

			data = (ACCData*) mir_alloc(sizeof(ACCData));
			if (data == NULL) 
				return FALSE;
			SetWindowLong(hwnd, 0, (LONG)data);

			ZeroMemory(data, sizeof(ACCData));
            data->hHook = HookEventMessage(ME_AV_AVATARCHANGED, hwnd, DM_AVATARCHANGED);
            data->hHookMy = HookEventMessage(ME_AV_MYAVATARCHANGED, hwnd, DM_MYAVATARCHANGED);
			data->hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
			data->borderColor = -1;
			data->bkgColor = -1;
			data->avatarBorderColor = -1;
			data->respectHidden = TRUE;
			data->showingFlash = FALSE;
			data->resizeIfSmaller = TRUE;

			return TRUE;
		}
        case WM_NCDESTROY:
        {
			DestroyFlash(hwnd, data);
			if (data) 
			{
                UnhookEvent(data->hHook);
                UnhookEvent(data->hHookMy);
				mir_free(data);
			}
			SetWindowLong(hwnd, 0, (LONG)NULL);
			break;
		}
		case WM_SETFONT:
		{
			data->hFont = (HFONT)wParam;
			Invalidate(hwnd);
			break;
		}
		case AVATAR_SETCONTACT:
		{
			if (data->showingFlash)
			{
				DestroyFlash(hwnd, data);
				data->showingFlash = FALSE;
			}

			data->hContact = (HANDLE) lParam;
			lstrcpynA(data->proto, (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)data->hContact, 0), sizeof(data->proto));

			if (DBGetContactSettingWord(data->hContact, "ContactPhoto", "Format", 0) == PA_FORMAT_XML)
			{
				data->showingFlash = StartFlash(hwnd, data);
			}

			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETPROTOCOL:
		{
			if (data->showingFlash)
			{
				DestroyFlash(hwnd, data);
				data->showingFlash = FALSE;
			}

			data->hContact = NULL;
			if (lParam == NULL)
				data->proto[0] = '\0';
			else
				lstrcpynA(data->proto, (char *) lParam, sizeof(data->proto));

			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETBKGCOLOR:
		{
			data->bkgColor = (COLORREF) lParam;
			if (data->showingFlash)
				SetBkgFlash(hwnd, data);
			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETBORDERCOLOR:
		{
			data->borderColor = (COLORREF) lParam;
			if (data->showingFlash)
				ResizeFlash(hwnd, data);
			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETAVATARBORDERCOLOR:
		{
			data->avatarBorderColor = (COLORREF) lParam;
			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETAVATARROUNDCORNERRADIUS:
		{
			data->avatarRoundCornerRadius = (int) lParam;
			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETNOAVATARTEXT:
		{
			lstrcpynA(data->noAvatarText, Translate((char*) lParam), sizeof(data->noAvatarText));
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_RESPECTHIDDEN:
		{
			data->respectHidden = (BOOL) lParam;
			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_SETRESIZEIFSMALLER:
		{
			data->resizeIfSmaller = (BOOL) lParam;
			NotifyAvatarChange(hwnd);
			Invalidate(hwnd);
			return TRUE;
		}
		case AVATAR_GETUSEDSPACE:
		{
			int *width = (int *)wParam;
			int *height = (int *)lParam;

			if (data->hContact == NULL && data->proto[0] == '\0')
			{
				*width = 0;
				*height = 0;
				return TRUE;
			}

			RECT rc;
			GetClientRect(hwnd, &rc);

			// Get avatar
			if (data->showingFlash && ServiceExists(MS_FAVATAR_GETINFO))
			{
				FLASHAVATAR fa = {0}; 
                fa.hContact = data->hContact;
				fa.cProto = data->proto;
				fa.hParentWindow = hwnd;
                fa.id = 1675;
				CallService(MS_FAVATAR_GETINFO, (WPARAM)&fa, 0);
				if (fa.hWindow != NULL)
				{
					*width = rc.right - rc.left;
					*height = rc.bottom - rc.top;
					return TRUE;
				}
			}

			avatarCacheEntry *ace;
			if (data->hContact == NULL)
				ace = (avatarCacheEntry *) CallService(MS_AV_GETMYAVATAR, 0, (LPARAM) data->proto);
			else
				ace = (avatarCacheEntry *) CallService(MS_AV_GETAVATARBITMAP, 0, (LPARAM) data->hContact);

			if (ace == NULL || ace->bmHeight == 0 || ace->bmWidth == 0 
				|| (data->respectHidden && (ace->dwFlags & AVS_HIDEONCLIST)))
			{
				*width = 0;
				*height = 0;
				return TRUE;
			}

			// Get its size
			int targetWidth = rc.right - rc.left;
			int targetHeight = rc.bottom - rc.top;

			if (!data->resizeIfSmaller && ace->bmHeight <= targetHeight && ace->bmWidth <= targetWidth)
			{
				*height = ace->bmHeight;
				*width = ace->bmWidth;
			} 
			else if (ace->bmHeight > ace->bmWidth)
			{
				float dScale = targetHeight / (float)ace->bmHeight;
				*height = targetHeight;
				*width = (int) (ace->bmWidth * dScale);
			}
			else 
			{
				float dScale = targetWidth / (float)ace->bmWidth;
				*height = (int) (ace->bmHeight * dScale);
				*width = targetWidth;
			}

			return TRUE;
		}
        case DM_AVATARCHANGED:
		{
			if (data->hContact == (HANDLE) wParam)
			{
				if (data->showingFlash)
				{
					DestroyFlash(hwnd, data);
					data->showingFlash = FALSE;
				}

				if (DBGetContactSettingWord(data->hContact, "ContactPhoto", "Format", 0) == PA_FORMAT_XML)
					data->showingFlash = StartFlash(hwnd, data);

				NotifyAvatarChange(hwnd);
				Invalidate(hwnd);
			}
            break;
		}
        case DM_MYAVATARCHANGED:
		{
			if (data->hContact == NULL && strcmp(data->proto, (char*) wParam) == 0)
			{
				if (data->showingFlash)
				{
					DestroyFlash(hwnd, data);
					data->showingFlash = FALSE;
				}

				NotifyAvatarChange(hwnd);
				Invalidate(hwnd);
			}
            break;
		}
		case WM_NCPAINT:
		case WM_PAINT:
		{
			if (data->hContact == NULL && data->proto[0] == '\0')
				break;

			PAINTSTRUCT ps;
			HDC hdc = BeginPaint(hwnd, &ps);
			if (hdc == NULL) 
				break;

			int oldBkMode = SetBkMode(hdc, TRANSPARENT);
			SetStretchBltMode(hdc, HALFTONE);

			RECT rc;
			GetClientRect(hwnd, &rc);

			// Draw background
			if (data->bkgColor != -1)
			{
				HBRUSH hbrush = CreateSolidBrush(data->bkgColor);
				FillRect(hdc, &rc, hbrush);
				DeleteObject(hbrush);
			}

			// If has a flash avatar, don't draw it
			if (data->showingFlash && ServiceExists(MS_FAVATAR_GETINFO))
			{
				FLASHAVATAR fa = {0}; 
                fa.hContact = data->hContact;
				fa.cProto = data->proto;
				fa.hParentWindow = hwnd;
                fa.id = 1675;
				CallService(MS_FAVATAR_GETINFO, (WPARAM)&fa, 0);
				if (fa.hWindow != NULL)
				{
					// Draw control border
					if (data->borderColor != -1)
					{
						HBRUSH hbrush = CreateSolidBrush(data->borderColor);
						FrameRect(hdc, &rc, hbrush);
						DeleteObject(hbrush);
					}
					return TRUE;
				}
			}

			// Draw avatar
            AVATARDRAWREQUEST avdrq = {0};
            avdrq.cbSize = sizeof(avdrq);
			avdrq.rcDraw = rc;
            avdrq.hContact = data->hContact;
			avdrq.szProto = data->proto;
            avdrq.hTargetDC = hdc;
            avdrq.dwFlags = AVDRQ_HIDEBORDERONTRANSPARENCY
				| (data->respectHidden ? AVDRQ_RESPECTHIDDEN : 0) 
				| (data->hContact != NULL ? 0 : AVDRQ_OWNPIC)
				| (data->avatarBorderColor == -1 ? 0 : AVDRQ_DRAWBORDER)
				| (data->avatarRoundCornerRadius <= 0 ? 0 : AVDRQ_ROUNDEDCORNER)
				| (data->resizeIfSmaller ? 0 : AVDRQ_DONTRESIZEIFSMALLER);
            avdrq.clrBorder = data->avatarBorderColor;
            avdrq.radius = data->avatarRoundCornerRadius;
			if (!CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdrq)) 
			{
				HGDIOBJ oldFont = SelectObject(hdc, data->hFont);

				// Get text rectangle
				RECT tr = avdrq.rcDraw;
				tr.top += 10;
				tr.bottom -= 10;
				tr.left += 10;
				tr.right -= 10;

				// Calc text size
				RECT tr_ret = tr;
				DrawTextA(hdc, data->noAvatarText, -1, &tr_ret, 
						DT_WORDBREAK | DT_NOPREFIX | DT_CENTER | DT_CALCRECT);
				
				// Calc needed size
				tr.top += ((tr.bottom - tr.top) - (tr_ret.bottom - tr_ret.top)) / 2;
				tr.bottom = tr.top + (tr_ret.bottom - tr_ret.top);
				DrawTextA(hdc, data->noAvatarText, -1, &tr, 
						DT_WORDBREAK | DT_NOPREFIX | DT_CENTER);

				SelectObject(hdc, oldFont);
			}

			// Draw control border
			if (data->borderColor != -1)
			{
				HBRUSH hbrush = CreateSolidBrush(data->borderColor);
				FrameRect(hdc, &rc, hbrush);
				DeleteObject(hbrush);
			}

			SetBkMode(hdc, oldBkMode);

			EndPaint(hwnd, &ps);
			return TRUE;
		}
		case WM_ERASEBKGND:
		{
			HDC hdc = (HDC) wParam;
			RECT rc;
			GetClientRect(hwnd, &rc);

			// Draw background
			if (data->bkgColor != -1)
			{
				HBRUSH hbrush = CreateSolidBrush(data->bkgColor);
				FillRect(hdc, &rc, hbrush);
				DeleteObject(hbrush);
			}

			// Draw control border
			if (data->borderColor != -1)
			{
				HBRUSH hbrush = CreateSolidBrush(data->borderColor);
				FrameRect(hdc, &rc, hbrush);
				DeleteObject(hbrush);
			}

			return TRUE;
		}
		case WM_SIZE:
		{
			if (data->showingFlash)
				ResizeFlash(hwnd, data);
			InvalidateRect(hwnd, NULL, TRUE);
			break;
		}
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}