Example #1
0
 /// <summary>Object created with this ctor can draw and measure.</summary>
 /// <param name="hdc">Device context handle. <b>Dispose</b> will not release it.</param>
 /// <param name="dpi"></param>
 public GdiTextRenderer(IntPtr hdc, int dpi)
 {
     _dpi      = dpi;
     _dc       = hdc;
     _oldFont  = Api.SelectObject(_dc, NativeFont_.RegularCached(_dpi));
     _oldAlign = 0xffffffff;
     Api.SetBkMode(_dc, 1);
     _oldColor = Api.SetTextColor(_dc, _color = 0);
 }
Example #2
0
            void _WmMousemove(POINT pc)
            {
                if (!_paintedOnce)
                {
                    return;
                }

                //format text to draw below magnifier
                string text;

                using (new StringBuilder_(out var s)) {
                    var ic = _flags & (ICFlags.Image | ICFlags.Color | ICFlags.Rectangle);
                    if (ic == 0)
                    {
                        ic = ICFlags.Image | ICFlags.Color;
                    }
                    bool canColor = ic.Has(ICFlags.Color);
                    if (canColor)
                    {
                        var color = _img.GetPixel(pc.x, pc.y).ToArgb() & 0xffffff;
                        s.Append("Color  #").Append(color.ToString("X6")).Append('\n');
                    }
                    if (ic == ICFlags.Color)
                    {
                        s.Append("Click to capture color.\n");
                    }
                    else if (ic == ICFlags.Rectangle)
                    {
                        s.Append("Mouse-drag to capture rectangle.\n");
                    }
                    else if (!canColor)
                    {
                        s.Append("Mouse-drag to capture image.\n");
                    }
                    else
                    {
                        s.Append("Mouse-drag to capture image,\nor Ctrl+click to capture color.\n");
                    }
                    s.Append("More:  right-click");                     //"  cancel:  key Esc\n  retry:  key F3 ... F3"
                    text = s.ToString();
                }

                var font   = NativeFont_.RegularCached(_dpi);
                int magnWH = Dpi.Scale(200, _dpi) / 10 * 10;                 //width and height of the magnified image without borders etc

                if (_textSize == default)
                {
                    using (var tr = new FontDC_(font)) _textSize = tr.MeasureDT(text, TFFlags.NOPREFIX);
                }
                int width = Math.Max(magnWH, _textSize.width) + 2, height = magnWH + 4 + _textSize.height;

                using var mb = new MemoryBitmap(width, height);
                var dc = mb.Hdc;

                using var wdc = new WindowDC_(_w);

                //draw frames and color background. Also erase magnifier, need when near screen edges.
                Api.FillRect(dc, (0, 0, width, height), Api.GetStockObject(4));                 //BLACK_BRUSH

                //copy from captured screen image to magnifier image. Magnify 5 times.
                int k = magnWH / 10;

                Api.StretchBlt(dc, 1, 1, magnWH, magnWH, wdc, pc.x - k, pc.y - k, k * 2, k * 2, Api.SRCCOPY);

                //draw red crosshair
                k = magnWH / 2;
                using (var pen = new Pen_(0xff)) {
                    pen.DrawLine(dc, (k, 1), (k, magnWH + 1));
                    pen.DrawLine(dc, (1, k), (magnWH + 1, k));
                }

                //draw text below magnifier
                var rc = new RECT(1, magnWH + 2, _textSize.width, _textSize.height);

                Api.SetTextColor(dc, 0x32CD9A);                 //Color.YellowGreen
                Api.SetBkMode(dc, 1);
                var oldFont = Api.SelectObject(dc, font);

                Api.DrawText(dc, text, ref rc, TFFlags.NOPREFIX);
                Api.SelectObject(dc, oldFont);

                //set magninifier position far from cursor
                var pm    = new POINT(4, 4); _w.MapScreenToClient(ref pm);
                int xMove = magnWH * 3;

                if (_magnMoved)
                {
                    pm.Offset(xMove, 0);
                }
                var rm = new RECT(pm.x, pm.y, width, height); rm.Inflate(magnWH / 2, magnWH / 2);

                if (rm.Contains(pc))
                {
                    Api.InvalidateRect(_w, (pm.x, pm.y, width, height));
                    _magnMoved ^= true;
                    pm.Offset(_magnMoved ? xMove : -xMove, 0);
                }

                Api.BitBlt(wdc, pm.x, pm.y, width, height, dc, 0, 0, Api.SRCCOPY);
            }
Example #3
0
        void _Render(IntPtr dc, RECT rUpdate)
        {
            Api.FillRect(dc, rUpdate, (IntPtr)(Api.COLOR_BTNFACE + 1));

            using var g         = Graphics.FromHdc(dc);
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            var font = NativeFont_.RegularCached(_dpi);

            using var soFont = new GdiSelectObject_(dc, font);
            Api.SetBkMode(dc, 1);
            int textColor = Api.GetSysColor(Api.COLOR_BTNTEXT), textColorDisabled = Api.GetSysColor(Api.COLOR_GRAYTEXT);

            rUpdate.Offset(0, _scroll.Offset);
            for (int i = _scroll.Pos; i < _a.Count; i++)
            {
                var b = _a[i];

                if (b.rect.bottom <= rUpdate.top)
                {
                    continue;
                }
                if (b.rect.top >= rUpdate.bottom)
                {
                    break;
                }

                var r = _ItemRect(b);

                //g.DrawRectangleInset(Pens.BlueViolet, r);

                if (b.IsSeparator)
                {
                    r.Inflate(-_z.textPaddingX / 4, 0);
                    //r.left+=_z.check+_z.image;
                    r.top   += (r.Height - _z.sepLine) / 2;
                    r.Height = _z.sepLine;
                    if (_z.theme != default)
                    {
                        Api.DrawThemeBackground(_z.theme, dc, 15, 0, r);
                    }
                    else
                    {
                        Api.DrawEdge(dc, ref r, Api.EDGE_ETCHED, Api.BF_TOP);
                    }
                }
                else
                {
                    if (b.BackgroundColor != default)
                    {
                        using (var brush = new SolidBrush((Color)b.BackgroundColor)) g.FillRectangle(brush, r);
                    }
                    if (i == _iHot)
                    {
                        if ((textColor == 0 || b.TextColor != default) && b.BackgroundColor == default)
                        {
                            using (var brush = new SolidBrush(0xC0DCF3.ToColor_())) g.FillRectangle(brush, r);
                        }
                        using (var pen = new Pen(0x90C8F6.ToColor_(), _z.bBorder)) g.DrawRectangleInset(pen, r);
                    }

                    r.Inflate(-_z.bBorder, -_z.bBorder);
                    var r2 = r;

                    r.left += _z.check;

                    if (b.image2 != null)
                    {
                        g.DrawImage(b.image2, r.left + _z.textPaddingY, r.top + (r.Height - _z.image) / 2, _z.image, _z.image);
                    }

                    r.left += _z.image + _z.textPaddingX; r.right -= _z.textPaddingX + _z.submenu + _z.submenuMargin;
                    r.top  += _z.textPaddingY; r.bottom -= _z.textPaddingY;

                    if (b.Hotkey != null)
                    {
                        Api.SetTextColor(dc, textColorDisabled);
                        var rh = r; rh.left += _z.xHotkeyStart;
                        Api.DrawText(dc, b.Hotkey, ref rh, c_tffHotkey);
                    }

                    Api.SetTextColor(dc, b.TextColor != default ? b.TextColor.ToBGR() : (b.IsDisabled ? textColorDisabled : textColor));
                    if (!b.Text.NE())
                    {
                        if (b.FontBold)
                        {
                            Api.SelectObject(dc, NativeFont_.BoldCached(_dpi));
                        }
                        r.Width = _z.xTextEnd;
                        Api.DrawText(dc, b.Text, ref r, _TfFlags(b));
                        if (b.FontBold)
                        {
                            Api.SelectObject(dc, font);
                        }
                    }

                    if (b.IsSubmenu)
                    {
                        _DrawControl(_z.zSubmenu, 16, b.IsDisabled ? 2 : 1, "➜", r2.right - _z.submenu, r.top, _z.submenu, r.Height);
                    }
                    if (b.IsChecked)
                    {
                        _DrawControl(_z.zCheck, 11, b.checkType == 1 ? (b.IsDisabled ? 2 : 1) : (b.IsDisabled ? 4 : 3), b.checkType == 1 ? "✔" : "●", r2.left, r.top, _z.check, r.Height);
                    }

                    void _DrawControl(SIZE z, int part, int state, string c, int x, int y, int width, int height)
                    {
                        if (_z.theme != default && z != default)
                        {
                            RECT r = new(x, r2.top + (r2.Height - z.height) / 2, z.width, z.height);
                            Api.DrawThemeBackground(_z.theme, dc, part, state, r);
                        }
                        else
                        {
                            RECT r = new(x, y, width, height);
                            Api.DrawText(dc, c, ref r, TFFlags.CENTER);
                            //cannot use DrawFrameControl(DFC_MENU, DFCS_MENUARROW etc), it draws with white background and too small when high DPI
                        }
                    }
                }
            }
        }
Example #4
0
 /// <summary>
 /// Selects standard UI font for specified DPI.
 /// </summary>
 /// <param name="dpi"></param>
 public FontDC_(DpiOf dpi) : this(NativeFont_.RegularCached(dpi))
 {
 }
Example #5
0
        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);
        }