static int EventArea_DrawWorker(HWND hWnd, HDC hDC) { RECT rc; HFONT hOldFont; GetClientRect(hWnd, &rc); if (g_CluiData.fDisableSkinEngine) sttDrawEventAreaBackground(hWnd, hDC, &rc); else SkinDrawGlyph(hDC, &rc, &rc, "Main,ID=EventArea"); hOldFont = g_clcPainter.ChangeToFont(hDC, NULL, FONTID_EVENTAREA, NULL); SetBkMode(hDC, TRANSPARENT); int iCount = GetMenuItemCount(g_CluiData.hMenuNotify); rc.left += 26; if (g_CluiData.hUpdateContact != 0) { TCHAR *szName = pcli->pfnGetContactDisplayName(g_CluiData.hUpdateContact, 0); int iIcon = cli_GetContactIcon(g_CluiData.hUpdateContact); ske_ImageList_DrawEx(g_himlCListClc, iIcon, hDC, rc.left, (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL); rc.left += 18; ske_DrawText(hDC, szName, -1, &rc, DT_VCENTER | DT_SINGLELINE); ske_ImageList_DrawEx(g_himlCListClc, (int)g_CluiData.iIconNotify, hDC, 4, (rc.bottom + rc.top - 16) / 2, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL); } else if (iCount > 0) { MENUITEMINFO mii = { 0 }; struct NotifyMenuItemExData *nmi; TCHAR *szName; int iIcon; mii.cbSize = sizeof(mii); mii.fMask = MIIM_DATA; GetMenuItemInfo(g_CluiData.hMenuNotify, iCount - 1, TRUE, &mii); nmi = (struct NotifyMenuItemExData *) mii.dwItemData; szName = pcli->pfnGetContactDisplayName(nmi->hContact, 0); iIcon = cli_GetContactIcon(nmi->hContact); ske_ImageList_DrawEx(g_himlCListClc, iIcon, hDC, rc.left, (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL); rc.left += 18; ske_ImageList_DrawEx(g_himlCListClc, nmi->iIcon, hDC, 4, (rc.bottom + rc.top) / 2 - 8, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL); ske_DrawText(hDC, szName, -1, &rc, DT_VCENTER | DT_SINGLELINE); } else { HICON hIcon = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_BLANK), IMAGE_ICON, 16, 16, 0); TCHAR *ptszEvents = TranslateT("No events"); ske_DrawText(hDC, ptszEvents, (int)mir_tstrlen(ptszEvents), &rc, DT_VCENTER | DT_SINGLELINE); ske_DrawIconEx(hDC, 4, (rc.bottom + rc.top - 16) / 2, hIcon, 16, 16, 0, 0, DI_NORMAL | DI_COMPAT); DestroyIcon(hIcon); } ske_ResetTextEffect(hDC); SelectObject(hDC, hOldFont); return 0; }
int RowHeight_CalcRowHeight(ClcData *dat, ClcContact *contact, int item) { if (!RowHeights_Alloc(dat, item + 1)) return -1; if (!g_clistApi.hwndContactTree) return 0; ClcCacheEntry *pdnce = contact->pce; if (dat->hWnd != g_clistApi.hwndContactTree || !gl_RowRoot || contact->type == CLCIT_GROUP) { int tmp = dat->fontModernInfo[g_clcPainter.GetBasicFontID(contact)].fontHeight; if (dat->text_replace_smileys && dat->first_line_draw_smileys && !dat->text_resize_smileys) tmp = max(tmp, contact->ssText.iMaxSmileyHeight); if (contact->type == CLCIT_GROUP) { wchar_t *szCounts = Clist_GetGroupCountsText(dat, contact); // Has the count? if (szCounts && szCounts[0]) tmp = max(tmp, dat->fontModernInfo[contact->group->expanded ? FONTID_OPENGROUPCOUNTS : FONTID_CLOSEDGROUPCOUNTS].fontHeight); } tmp = max(tmp, ICON_HEIGHT); tmp = max(tmp, dat->row_min_heigh); tmp += dat->row_border * 2; if (contact->type == CLCIT_GROUP && contact->group->parent->groupId == 0 && contact->group->parent->cl[0] != contact) tmp += dat->row_before_group_space; if (item != -1) dat->row_heights[item] = tmp; return tmp; } bool hasAvatar = contact->avatar_data != nullptr; for (int i = 0;; i++) { ROWCELL *pCell = gl_RowTabAccess[i]; if (pCell == nullptr) break; if (pCell->type != TC_SPACE) { pCell->h = 0; pCell->w = 0; SetRect(&pCell->r, 0, 0, 0, 0); switch (pCell->type) { case TC_TEXT1: pCell->h = dat->fontModernInfo[g_clcPainter.GetBasicFontID(contact)].fontHeight; if (dat->text_replace_smileys && dat->first_line_draw_smileys && !dat->text_resize_smileys) pCell->h = max(pCell->h, contact->ssText.iMaxSmileyHeight); if (item == -1) { // calculate text width here SIZE size = { 0 }; RECT dummyRect = { 0, 0, 1024, pCell->h }; HDC hdc = CreateCompatibleDC(nullptr); g_clcPainter.ChangeToFont(hdc, dat, g_clcPainter.GetBasicFontID(contact), nullptr); g_clcPainter.GetTextSize(&size, hdc, dummyRect, contact->szText, contact->ssText.plText, 0, dat->text_resize_smileys ? 0 : contact->ssText.iMaxSmileyHeight); if (contact->type == CLCIT_GROUP) { wchar_t *szCounts = Clist_GetGroupCountsText(dat, contact); if (szCounts && mir_wstrlen(szCounts) > 0) { RECT count_rc = { 0 }; // calc width and height g_clcPainter.ChangeToFont(hdc, dat, contact->group->expanded ? FONTID_OPENGROUPCOUNTS : FONTID_CLOSEDGROUPCOUNTS, nullptr); ske_DrawText(hdc, L" ", 1, &count_rc, DT_CALCRECT | DT_NOPREFIX); size.cx += count_rc.right - count_rc.left; count_rc.right = 0; count_rc.left = 0; ske_DrawText(hdc, szCounts, (int)mir_wstrlen(szCounts), &count_rc, DT_CALCRECT); size.cx += count_rc.right - count_rc.left; pCell->h = max(pCell->h, count_rc.bottom - count_rc.top); } } pCell->w = size.cx; SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); ske_ResetTextEffect(hdc); DeleteDC(hdc); } break; case TC_TEXT2: if (dat->secondLine.show && pdnce->szSecondLineText && pdnce->szSecondLineText[0]) { pCell->h = dat->fontModernInfo[FONTID_SECONDLINE].fontHeight; if (dat->text_replace_smileys && dat->secondLine.draw_smileys && !dat->text_resize_smileys) pCell->h = max(pCell->h, pdnce->ssSecondLine.iMaxSmileyHeight); if (item == -1) { // calculate text width here SIZE size = { 0 }; RECT dummyRect = { 0, 0, 1024, pCell->h }; HDC hdc = CreateCompatibleDC(nullptr); g_clcPainter.ChangeToFont(hdc, dat, FONTID_SECONDLINE, nullptr); g_clcPainter.GetTextSize(&size, hdc, dummyRect, pdnce->szSecondLineText, pdnce->ssSecondLine.plText, 0, dat->text_resize_smileys ? 0 : pdnce->ssSecondLine.iMaxSmileyHeight); pCell->w = size.cx; SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); ske_ResetTextEffect(hdc); DeleteDC(hdc); } } break; case TC_TEXT3: if (dat->thirdLine.show && pdnce->szThirdLineText && pdnce->szThirdLineText[0]) { pCell->h = dat->fontModernInfo[FONTID_THIRDLINE].fontHeight; if (dat->text_replace_smileys && dat->thirdLine.draw_smileys && !dat->text_resize_smileys) pCell->h = max(pCell->h, pdnce->ssThirdLine.iMaxSmileyHeight); if (item == -1) { //calculate text width here SIZE size = { 0 }; RECT dummyRect = { 0, 0, 1024, pCell->h }; HDC hdc = CreateCompatibleDC(nullptr); g_clcPainter.ChangeToFont(hdc, dat, FONTID_THIRDLINE, nullptr); g_clcPainter.GetTextSize(&size, hdc, dummyRect, pdnce->szThirdLineText, pdnce->ssThirdLine.plText, 0, dat->text_resize_smileys ? 0 : pdnce->ssThirdLine.iMaxSmileyHeight); pCell->w = size.cx; SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); ske_ResetTextEffect(hdc); DeleteDC(hdc); } } break; case TC_STATUS: if ((contact->type == CLCIT_GROUP && !dat->row_hide_group_icon) || (contact->type == CLCIT_CONTACT && contact->iImage != -1 && !(dat->icon_hide_on_avatar && dat->avatars_show && (hasAvatar || (!hasAvatar && dat->icon_draw_on_avatar_space && contact->iImage != -1)) && !contact->bImageIsSpecial))) { pCell->h = ICON_HEIGHT; pCell->w = ICON_HEIGHT; } break; case TC_AVATAR: if (dat->avatars_show && contact->type == CLCIT_CONTACT && (hasAvatar || (dat->icon_hide_on_avatar && dat->icon_draw_on_avatar_space && contact->iImage != -1))) { int iW = 0, iH = 0; if (contact->avatar_data) { iH = contact->avatar_data->bmHeight; iW = contact->avatar_data->bmWidth; } SIZE sz = GetAvatarSize(iW, iH, dat->avatars_maxwidth_size, dat->avatars_maxheight_size); if ((sz.cx == 0 || sz.cy == 0) && dat->icon_hide_on_avatar && dat->icon_draw_on_avatar_space && contact->iImage != -1) sz.cx = ICON_HEIGHT, sz.cy = ICON_HEIGHT; pCell->h = sz.cy; pCell->w = sz.cx; } break; case TC_EXTRA: // Draw extra icons if (contact->type == CLCIT_CONTACT && (!contact->iSubNumber || db_get_b(0, "CLC", "MetaHideExtra", SETTING_METAHIDEEXTRA_DEFAULT) == 0 && dat->extraColumnsCount > 0)) { bool hasExtra = false; int width = 0; for (int k = 0; k < dat->extraColumnsCount; k++) if (contact->iExtraImage[k] != EMPTY_EXTRA_ICON || !dat->bMetaIgnoreEmptyExtra) { hasExtra = true; if (item != -1) break; width += (width > 0) ? dat->extraColumnSpacing : (dat->extraColumnSpacing - 2); } if (hasExtra) { pCell->h = ICON_HEIGHT; pCell->w = width; } } break; case TC_EXTRA1: case TC_EXTRA2: case TC_EXTRA3: case TC_EXTRA4: case TC_EXTRA5: case TC_EXTRA6: case TC_EXTRA7: case TC_EXTRA8: case TC_EXTRA9: if (contact->type == CLCIT_CONTACT && (!contact->iSubNumber || db_get_b(0, "CLC", "MetaHideExtra", SETTING_METAHIDEEXTRA_DEFAULT) == 0 && dat->extraColumnsCount > 0)) { int eNum = pCell->type - TC_EXTRA1; if (eNum < dat->extraColumnsCount) if (contact->iExtraImage[eNum] != EMPTY_EXTRA_ICON || !dat->bMetaIgnoreEmptyExtra) { pCell->h = ICON_HEIGHT; pCell->w = ICON_HEIGHT; } } break; case TC_TIME: if (contact->type == CLCIT_CONTACT && dat->contact_time_show && pdnce->hTimeZone) { pCell->h = dat->fontModernInfo[FONTID_CONTACT_TIME].fontHeight; if (item == -1) { wchar_t szResult[80]; if (!TimeZone_PrintDateTime(pdnce->hTimeZone, L"t", szResult, _countof(szResult), 0)) { SIZE text_size = { 0 }; RECT rc = { 0 }; // Select font HDC hdc = CreateCompatibleDC(nullptr); g_clcPainter.ChangeToFont(hdc, dat, FONTID_CONTACT_TIME, nullptr); // Get text size text_size.cy = ske_DrawText(hdc, szResult, (int)mir_wstrlen(szResult), &rc, DT_CALCRECT | DT_NOPREFIX | DT_SINGLELINE); SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); ske_ResetTextEffect(hdc); DeleteDC(hdc); text_size.cx = rc.right - rc.left; pCell->w = text_size.cx; } } } break; } } } int height = cppCalculateRowHeight(gl_RowRoot); height += dat->row_border * 2; height = max(height, dat->row_min_heigh); if (item != -1) dat->row_heights[item] = height; return height; }
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); } }