static void DrawProperties(HWND hwnd, HDC hdc) { PropertiesLayout *layoutData = FindPropertyWindowByHwnd(hwnd); ScopedFont fontLeftTxt(GetSimpleFont(hdc, LEFT_TXT_FONT, LEFT_TXT_FONT_SIZE)); ScopedFont fontRightTxt(GetSimpleFont(hdc, RIGHT_TXT_FONT, RIGHT_TXT_FONT_SIZE)); HGDIOBJ origFont = SelectObject(hdc, fontLeftTxt); /* Just to remember the orig font */ SetBkMode(hdc, TRANSPARENT); ClientRect rcClient(hwnd); FillRect(hdc, &rcClient.ToRECT(), gBrushAboutBg); SetTextColor(hdc, WIN_COL_BLACK); /* render text on the left*/ SelectObject(hdc, fontLeftTxt); for (size_t i = 0; i < layoutData->Count(); i++) { PropertyEl *el = layoutData->At(i); DrawText(hdc, el->leftTxt, -1, &el->leftPos.ToRECT(), DT_RIGHT | DT_NOPREFIX); } /* render text on the right */ SelectObject(hdc, fontRightTxt); for (size_t i = 0; i < layoutData->Count(); i++) { PropertyEl *el = layoutData->At(i); RectI rc = el->rightPos; if (rc.x + rc.dx > rcClient.x + rcClient.dx - PROPERTIES_RECT_PADDING) rc.dx = rcClient.x + rcClient.dx - PROPERTIES_RECT_PADDING - rc.x; DrawText(hdc, el->rightTxt, -1, &rc.ToRECT(), DT_LEFT | DT_PATH_ELLIPSIS | DT_NOPREFIX); } SelectObject(hdc, origFont); }
static void UpdatePropertiesLayout(PropertiesLayout *layoutData, HDC hdc, RectI *rect) { ScopedFont fontLeftTxt(GetSimpleFont(hdc, LEFT_TXT_FONT, LEFT_TXT_FONT_SIZE)); ScopedFont fontRightTxt(GetSimpleFont(hdc, RIGHT_TXT_FONT, RIGHT_TXT_FONT_SIZE)); HGDIOBJ origFont = SelectObject(hdc, fontLeftTxt); /* calculate text dimensions for the left side */ SelectObject(hdc, fontLeftTxt); int leftMaxDx = 0; for (size_t i = 0; i < layoutData->Count(); i++) { PropertyEl *el = layoutData->At(i); RECT rc = { 0 }; DrawText(hdc, el->leftTxt, -1, &rc, DT_NOPREFIX | DT_CALCRECT); el->leftPos.dx = rc.right - rc.left; // el->leftPos.dy is set below to be equal to el->rightPos.dy if (el->leftPos.dx > leftMaxDx) leftMaxDx = el->leftPos.dx; } /* calculate text dimensions for the right side */ SelectObject(hdc, fontRightTxt); int rightMaxDx = 0; int lineCount = 0; int textDy = 0; for (size_t i = 0; i < layoutData->Count(); i++) { PropertyEl *el = layoutData->At(i); RECT rc = { 0 }; DrawText(hdc, el->rightTxt, -1, &rc, DT_NOPREFIX | DT_CALCRECT); el->rightPos.dx = rc.right - rc.left; el->leftPos.dy = el->rightPos.dy = rc.bottom - rc.top; textDy += el->rightPos.dy; if (el->rightPos.dx > rightMaxDx) rightMaxDx = el->rightPos.dx; lineCount++; } assert(lineCount > 0 && textDy > 0); int totalDx = leftMaxDx + PROPERTIES_LEFT_RIGHT_SPACE_DX + rightMaxDx; int totalDy = 4; totalDy += textDy + (lineCount - 1) * PROPERTIES_TXT_DY_PADDING; totalDy += 4; int offset = PROPERTIES_RECT_PADDING; if (rect) *rect = RectI(0, 0, totalDx + 2 * offset, totalDy + offset); int currY = 0; for (size_t i = 0; i < layoutData->Count(); i++) { PropertyEl *el = layoutData->At(i); el->leftPos = RectI(offset, offset + currY, leftMaxDx, el->leftPos.dy); el->rightPos.x = offset + leftMaxDx + PROPERTIES_LEFT_RIGHT_SPACE_DX; el->rightPos.y = offset + currY; currY += el->rightPos.dy + PROPERTIES_TXT_DY_PADDING; } SelectObject(hdc, origFont); }
static void DrawProperties(HWND hwnd, HDC hdc) { PropertiesLayout *layoutData = FindPropertyWindowByHwnd(hwnd); ScopedFont fontLeftTxt(CreateSimpleFont(hdc, LEFT_TXT_FONT, LEFT_TXT_FONT_SIZE)); ScopedFont fontRightTxt(CreateSimpleFont(hdc, RIGHT_TXT_FONT, RIGHT_TXT_FONT_SIZE)); HGDIOBJ origFont = SelectObject(hdc, fontLeftTxt); /* Just to remember the orig font */ SetBkMode(hdc, TRANSPARENT); ClientRect rcClient(hwnd); RECT rTmp = rcClient.ToRECT(); ScopedGdiObj<HBRUSH> brushAboutBg(CreateSolidBrush(GetAboutBgColor())); FillRect(hdc, &rTmp, brushAboutBg); SetTextColor(hdc, WIN_COL_BLACK); /* render text on the left*/ SelectObject(hdc, fontLeftTxt); for (size_t i = 0; i < layoutData->Count(); i++) { PropertyEl *el = layoutData->At(i); const WCHAR *txt = el->leftTxt; rTmp = el->leftPos.ToRECT(); DrawText(hdc, txt, -1, &rTmp, DT_RIGHT | DT_NOPREFIX); } /* render text on the right */ SelectObject(hdc, fontRightTxt); for (size_t i = 0; i < layoutData->Count(); i++) { PropertyEl *el = layoutData->At(i); const WCHAR *txt = el->rightTxt; RectI rc = el->rightPos; if (rc.x + rc.dx > rcClient.x + rcClient.dx - PROPERTIES_RECT_PADDING) rc.dx = rcClient.x + rcClient.dx - PROPERTIES_RECT_PADDING - rc.x; rTmp = rc.ToRECT(); UINT format = DT_LEFT | DT_NOPREFIX | (el->isPath ? DT_PATH_ELLIPSIS : DT_WORD_ELLIPSIS); DrawText(hdc, txt, -1, &rTmp, format); } SelectObject(hdc, origFont); }
static void UpdateAboutLayoutInfo(HWND hwnd, HDC hdc, RectI *rect) { ScopedFont fontLeftTxt(GetSimpleFont(hdc, LEFT_TXT_FONT, LEFT_TXT_FONT_SIZE)); ScopedFont fontRightTxt(GetSimpleFont(hdc, RIGHT_TXT_FONT, RIGHT_TXT_FONT_SIZE)); HGDIOBJ origFont = SelectObject(hdc, fontLeftTxt); /* calculate minimal top box size */ SizeI headerSize = CalcSumatraVersionSize(hdc); /* calculate left text dimensions */ SelectObject(hdc, fontLeftTxt); int leftLargestDx = 0; int leftDy = 0; for (AboutLayoutInfoEl *el = gAboutLayoutInfo; el->leftTxt; el++) { SIZE txtSize; GetTextExtentPoint32(hdc, el->leftTxt, (int)str::Len(el->leftTxt), &txtSize); el->leftPos.dx = txtSize.cx; el->leftPos.dy = txtSize.cy; if (el == &gAboutLayoutInfo[0]) leftDy = el->leftPos.dy; else assert(leftDy == el->leftPos.dy); if (leftLargestDx < el->leftPos.dx) leftLargestDx = el->leftPos.dx; } /* calculate right text dimensions */ SelectObject(hdc, fontRightTxt); int rightLargestDx = 0; int rightDy = 0; for (AboutLayoutInfoEl *el = gAboutLayoutInfo; el->leftTxt; el++) { SIZE txtSize; GetTextExtentPoint32(hdc, el->rightTxt, (int)str::Len(el->rightTxt), &txtSize); el->rightPos.dx = txtSize.cx; el->rightPos.dy = txtSize.cy; if (el == &gAboutLayoutInfo[0]) rightDy = el->rightPos.dy; else assert(rightDy == el->rightPos.dy); if (rightLargestDx < el->rightPos.dx) rightLargestDx = el->rightPos.dx; } /* calculate total dimension and position */ RectI minRect; minRect.dx = ABOUT_LEFT_RIGHT_SPACE_DX + leftLargestDx + ABOUT_LINE_SEP_SIZE + rightLargestDx + ABOUT_LEFT_RIGHT_SPACE_DX; if (minRect.dx < headerSize.dx) minRect.dx = headerSize.dx; minRect.dx += 2 * ABOUT_LINE_OUTER_SIZE + 2 * ABOUT_MARGIN_DX; minRect.dy = headerSize.dy; for (AboutLayoutInfoEl *el = gAboutLayoutInfo; el->leftTxt; el++) minRect.dy += rightDy + ABOUT_TXT_DY; minRect.dy += 2 * ABOUT_LINE_OUTER_SIZE + 4; ClientRect rc(hwnd); minRect.x = (rc.dx - minRect.dx) / 2; minRect.y = (rc.dy - minRect.dy) / 2; if (rect) *rect = minRect; /* calculate text positions */ int linePosX = ABOUT_LINE_OUTER_SIZE + ABOUT_MARGIN_DX + leftLargestDx + ABOUT_LEFT_RIGHT_SPACE_DX; int currY = minRect.y + headerSize.dy + 4; for (AboutLayoutInfoEl *el = gAboutLayoutInfo; el->leftTxt; el++) { el->leftPos.x = minRect.x + linePosX - ABOUT_LEFT_RIGHT_SPACE_DX - el->leftPos.dx; el->leftPos.y = currY + (rightDy - leftDy) / 2; el->rightPos.x = minRect.x + linePosX + ABOUT_LEFT_RIGHT_SPACE_DX; el->rightPos.y = currY; currY += rightDy + ABOUT_TXT_DY; } SelectObject(hdc, origFont); }
/* Draws the about screen and remembers some state for hyperlinking. It transcribes the design I did in graphics software - hopeless to understand without seeing the design. */ static void DrawAbout(HWND hwnd, HDC hdc, RectI rect, Vec<StaticLinkInfo>& linkInfo) { HPEN penBorder = CreatePen(PS_SOLID, ABOUT_LINE_OUTER_SIZE, WIN_COL_BLACK); HPEN penDivideLine = CreatePen(PS_SOLID, ABOUT_LINE_SEP_SIZE, WIN_COL_BLACK); HPEN penLinkLine = CreatePen(PS_SOLID, ABOUT_LINE_SEP_SIZE, COL_BLUE_LINK); ScopedFont fontLeftTxt(GetSimpleFont(hdc, LEFT_TXT_FONT, LEFT_TXT_FONT_SIZE)); ScopedFont fontRightTxt(GetSimpleFont(hdc, RIGHT_TXT_FONT, RIGHT_TXT_FONT_SIZE)); HGDIOBJ origFont = SelectObject(hdc, fontLeftTxt); /* Just to remember the orig font */ ClientRect rc(hwnd); FillRect(hdc, &rc.ToRECT(), gBrushAboutBg); /* render title */ RectI titleRect(rect.TL(), CalcSumatraVersionSize(hdc)); SelectObject(hdc, gBrushLogoBg); SelectObject(hdc, penBorder); #ifndef ABOUT_USE_LESS_COLORS Rectangle(hdc, rect.x, rect.y + ABOUT_LINE_OUTER_SIZE, rect.x + rect.dx, rect.y + titleRect.dy + ABOUT_LINE_OUTER_SIZE); #else RectI titleBgBand(0, rect.y, rc.dx, titleRect.dy); FillRect(hdc, &titleBgBand.ToRECT(), gBrushLogoBg); PaintLine(hdc, RectI(0, rect.y, rc.dx, 0)); PaintLine(hdc, RectI(0, rect.y + titleRect.dy, rc.dx, 0)); #endif titleRect.Offset((rect.dx - titleRect.dx) / 2, 0); DrawSumatraVersion(hdc, titleRect); /* render attribution box */ SetTextColor(hdc, ABOUT_BORDER_COL); SetBkMode(hdc, TRANSPARENT); #ifndef ABOUT_USE_LESS_COLORS Rectangle(hdc, rect.x, rect.y + titleRect.dy, rect.x + rect.dx, rect.y + rect.dy); #endif /* render text on the left*/ SelectObject(hdc, fontLeftTxt); for (AboutLayoutInfoEl *el = gAboutLayoutInfo; el->leftTxt; el++) { TextOut(hdc, el->leftPos.x, el->leftPos.y, el->leftTxt, (int)str::Len(el->leftTxt)); } /* render text on the right */ SelectObject(hdc, fontRightTxt); SelectObject(hdc, penLinkLine); linkInfo.Reset(); for (AboutLayoutInfoEl *el = gAboutLayoutInfo; el->leftTxt; el++) { bool hasUrl = HasPermission(Perm_DiskAccess) && el->url; SetTextColor(hdc, hasUrl ? COL_BLUE_LINK : ABOUT_BORDER_COL); TextOut(hdc, el->rightPos.x, el->rightPos.y, el->rightTxt, (int)str::Len(el->rightTxt)); if (hasUrl) { int underlineY = el->rightPos.y + el->rightPos.dy - 3; PaintLine(hdc, RectI(el->rightPos.x, underlineY, el->rightPos.dx, 0)); linkInfo.Append(StaticLinkInfo(el->rightPos, el->url, el->url)); } } SelectObject(hdc, penDivideLine); RectI divideLine(gAboutLayoutInfo[0].rightPos.x - ABOUT_LEFT_RIGHT_SPACE_DX, rect.y + titleRect.dy + 4, 0, rect.y + rect.dy - 4 - gAboutLayoutInfo[0].rightPos.y); PaintLine(hdc, divideLine); SelectObject(hdc, origFont); DeleteObject(penBorder); DeleteObject(penDivideLine); DeleteObject(penLinkLine); }