/// <summary> /// Gets metrics for this flow. /// </summary> private _Metrics _GetMetrics() { if (this._MetricsCache == null) { return this._MetricsCache = this._CreateMetrics(); } return this._MetricsCache; }
SIZE _Measure(int maxWidth) { SIZE R = default; _z?.Dispose(); _z = new _Metrics(this); int buttonPlusX = (_z.bBorder + _z.textPaddingX) * 2 + _z.check + _z.image + _z.submenu + _z.submenuMargin; int buttonPlusY = (_z.bBorder + _z.textPaddingY) * 2 + 1; int maxTextWidth = maxWidth - buttonPlusX; var font = NativeFont_.RegularCached(_dpi); using var dc = new FontDC_(font); int lineHeight = dc.MeasureEP(" ").height + buttonPlusY; int maxHotkey = 0; if (_z.hasHotkeys) { foreach (var b in _a) { if (b.Hotkey == null) { continue; } int wid = dc.MeasureDT(b.Hotkey, c_tffHotkey).width; maxHotkey = Math.Max(maxHotkey, Math.Min(wid, maxTextWidth / 2)); } } int hotkeyPlus = lineHeight * 3 / 2; //space between text and hotkey if (maxHotkey > 0) { maxTextWidth -= maxHotkey += hotkeyPlus; } int y = 0; for (int i = 0; i < _a.Count; i++) { //note: to support multiline, wrap, underlines and tabs we have to use DrawText, not TextOut. // DrawText(DT_CALCRECT) is slow. Very slow compared with GetTextExtentPoint32. Eg 100-300 ms for 1000 items. Depends on text length. var b = _a[i]; SIZE z; if (b.IsSeparator) { z = new(0, _z.separator); } else { var s = b.Text; if (!s.NE()) { if (b.FontBold) { Api.SelectObject(dc, NativeFont_.BoldCached(_dpi)); } z = dc.MeasureDT(s, _TfFlags(b), maxTextWidth); z.width = Math.Min(z.width, maxTextWidth); if (b.FontBold) { Api.SelectObject(dc, font); } _z.xTextEnd = Math.Max(_z.xTextEnd, z.width); z.width += buttonPlusX; z.height += buttonPlusY; } else { z = new(0, lineHeight); } } b.rect = new(0, y, z.width, z.height); y += z.height; R.width = Math.Max(R.width, z.width); R.height = Math.Max(R.height, y); } if (maxHotkey > 0) { R.width += maxHotkey; _z.xHotkeyStart = _z.xTextEnd + hotkeyPlus; } foreach (var b in _a) { b.rect.right = R.width; } return(R); }