INT_PTR DrawAvatarPicture(WPARAM wParam, LPARAM lParam) { AVATARDRAWREQUEST *r = (AVATARDRAWREQUEST *)lParam; AVATARCACHEENTRY *ace = NULL; if (fei == NULL || r == NULL || IsBadReadPtr((void *)r, sizeof(AVATARDRAWREQUEST))) return 0; if (r->cbSize != sizeof(AVATARDRAWREQUEST)) return 0; if (r->dwFlags & AVDRQ_PROTOPICT) { if (r->szProto == NULL) return 0; for (int i = 0; i < g_ProtoPictures.getCount(); i++) { protoPicCacheEntry& p = g_ProtoPictures[i]; if ( !lstrcmpA(p.szProtoname, r->szProto) && lstrlenA(r->szProto) == lstrlenA(p.szProtoname) && p.hbmPic != 0) { ace = (AVATARCACHEENTRY *)&g_ProtoPictures[i]; break; } } } else if (r->dwFlags & AVDRQ_OWNPIC) { if (r->szProto == NULL) return 0; if (r->szProto[0] == '\0' && db_get_b(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1)) return -1; ace = (AVATARCACHEENTRY *)GetMyAvatar(0, (LPARAM)r->szProto); } else ace = (AVATARCACHEENTRY *)GetAvatarBitmap((WPARAM)r->hContact, 0); if (ace && (!(r->dwFlags & AVDRQ_RESPECTHIDDEN) || !(ace->dwFlags & AVS_HIDEONCLIST))) { ace->t_lastAccess = time(NULL); if (ace->bmHeight == 0 || ace->bmWidth == 0 || ace->hbmPic == 0) return 0; InternalDrawAvatar(r, ace->hbmPic, ace->bmWidth, ace->bmHeight, ace->dwFlags); return 1; } return 0; }
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); }