Esempio n. 1
0
        private static void DrawTextInternal(
            IDeviceContext dc,
            string?text,
            Font?font,
            Rectangle bounds,
            Color foreColor,
            Color backColor = default,
            User32.DT flags = User32.DT.CENTER | User32.DT.VCENTER)
        {
            if (dc is null)
            {
                throw new ArgumentNullException(nameof(dc));
            }

            // Avoid creating the HDC, etc if we're not going to do any drawing
            if (string.IsNullOrEmpty(text) || foreColor == Color.Transparent)
            {
                return;
            }

            // This MUST come before retreiving the HDC, which locks the Graphics object
            Gdi32.QUALITY quality = FontQualityFromTextRenderingHint(dc);

            using var hdc            = new DeviceContextHdcScope(dc, applyGraphicsState: false);
            using WindowsGraphics wg = WindowsGraphics.FromHdc(hdc);
            using WindowsFont? wf    = WindowsGraphicsCacheManager.GetWindowsFont(font, quality);
            wg.DrawText(text, wf, bounds, foreColor, backColor, flags);
        }
Esempio n. 2
0
 public static Size MeasureText(
     this DeviceContextHdcScope hdc,
     string?text,
     FontCache.FontScope font,
     Size proposedSize,
     User32.DT flags)
 => MeasureText(hdc.HDC, text, font, proposedSize, flags);
Esempio n. 3
0
 public static Size MeasureText(
     this DeviceContextHdcScope hdc,
     ReadOnlySpan <char> text,
     FontCache.Scope font,
     Size proposedSize,
     User32.DT flags)
 => MeasureText(hdc.HDC, text, font, proposedSize, flags);
Esempio n. 4
0
        /// <summary>
        ///  Returns the Size in logical units of the given text using the given Font, and according to the formatting flags.
        ///  The proposed size is used to create a bounding rectangle as follows:
        ///  - If there are multiple lines of text, DrawText uses the width of the rectangle pointed to by
        ///  the lpRect parameter and extends the base of the rectangle to bound the last line of text.
        ///  - If the largest word is wider than the rectangle, the width is expanded.
        ///  - If the text is less than the width of the rectangle, the width is reduced.
        ///  - If there is only one line of text, DrawText modifies the right side of the rectangle so that
        ///  it bounds the last character in the line.
        ///  If the font is null, the hdc's current font will be used.
        ///
        ///  Note for vertical fonts (if ever supported): DrawTextEx uses GetTextExtentPoint32 for measuring the text and this
        ///  function has the following limitation (from MSDN):
        ///  - This function assumes that the text is horizontal, that is, that the escapement is always 0. This is true for both
        ///  the horizontal and vertical measurements of the text.  The application must convert it explicitly.
        /// </summary>
        public static Size MeasureText(
            this Gdi32.HDC hdc,
            ReadOnlySpan <char> text,
            FontCache.Scope font,
            Size proposedSize,
            User32.DT flags)
        {
            ValidateFlags(flags);

            if (text.IsEmpty)
            {
                return(Size.Empty);
            }

            // DrawText returns a rectangle useful for aligning, but not guaranteed to encompass all
            // pixels (its not a FitBlackBox, if the text is italicized, it will overhang on the right.)
            // So we need to account for this.

            User32.DRAWTEXTPARAMS dtparams = GetTextMargins(font);

            // If Width / Height are < 0, we need to make them larger or DrawText will return
            // an unbounded measurement when we actually trying to make it very narrow.
            int minWidth = 1 + dtparams.iLeftMargin + dtparams.iRightMargin;

            if (proposedSize.Width <= minWidth)
            {
                proposedSize.Width = minWidth;
            }

            if (proposedSize.Height <= 0)
            {
                proposedSize.Height = 1;
            }

            var rect = new RECT(0, 0, proposedSize.Width, proposedSize.Height);

            using var fontSelection = new Gdi32.SelectObjectScope(hdc, font.Object);

            // If proposedSize.Height >= MaxSize.Height it is assumed bounds needed.  If flags contain SINGLELINE and
            // VCENTER or BOTTOM options, DrawTextEx does not bind the rectangle to the actual text height since
            // it assumes the text is to be vertically aligned; we need to clear the VCENTER and BOTTOM flags to
            // get the actual text bounds.
            if (proposedSize.Height >= TextRenderer.MaxSize.Height && (flags & User32.DT.SINGLELINE) != 0)
            {
                // Clear vertical-alignment flags.
                flags &= ~(User32.DT.BOTTOM | User32.DT.VCENTER);
            }

            if (proposedSize.Width == TextRenderer.MaxSize.Width)
            {
                // PERF: No constraining width means no word break.
                // in this case, we dont care about word wrapping - there should be enough room to fit it all
                flags &= ~(User32.DT.WORDBREAK);
            }

            flags |= User32.DT.CALCRECT;
            User32.DrawTextExW(hdc, text, ref rect, flags, ref dtparams);

            return(rect.Size);
        }
Esempio n. 5
0
        internal static void DrawTextInternal(
            IDeviceContext dc,
            ReadOnlySpan <char> text,
            Font?font,
            Rectangle bounds,
            Color foreColor,
            Color backColor = default,
            User32.DT flags = User32.DT.CENTER | User32.DT.VCENTER)
        {
            if (dc is null)
            {
                throw new ArgumentNullException(nameof(dc));
            }

            // Avoid creating the HDC, etc if we're not going to do any drawing
            if (text.IsEmpty || foreColor == Color.Transparent)
            {
                return;
            }

            // This MUST come before retreiving the HDC, which locks the Graphics object
            Gdi32.QUALITY quality = FontQualityFromTextRenderingHint(dc);

            using var hdc = new DeviceContextHdcScope(dc);

            DrawTextInternal(hdc, text, font, bounds, foreColor, quality, backColor, flags);
        }
Esempio n. 6
0
        private static Size MeasureTextInternal(
            IDeviceContext dc,
            ReadOnlySpan <char> text,
            Font?font,
            Size proposedSize,
            TextFormatFlags flags  = TextFormatFlags.Bottom,
            bool blockModifyString = false)
        {
            if (dc is null)
            {
                throw new ArgumentNullException(nameof(dc));
            }

            User32.DT drawTextFlags = GetTextFormatFlags(flags, blockModifyString);

            if (text.IsEmpty)
            {
                return(Size.Empty);
            }

            // This MUST come before retreiving the HDC, which locks the Graphics object
            Gdi32.QUALITY quality = FontQualityFromTextRenderingHint(dc);

            using var hdc   = new DeviceContextHdcScope(dc);
            using var hfont = GdiCache.GetHFONT(font, quality, hdc);
            return(hdc.MeasureText(text, hfont, proposedSize, drawTextFlags));
        }
Esempio n. 7
0
 private static void DrawTextInternal(
     IDeviceContext dc,
     ReadOnlySpan<char> text,
     Font? font,
     Point pt,
     Color foreColor,
     Color backColor,
     User32.DT flags = User32.DT.DEFAULT)
     => DrawTextInternal(dc, text, font, new Rectangle(pt, MaxSize), foreColor, backColor, flags);
Esempio n. 8
0
 private static void DrawTextInternal(
     IDeviceContext dc,
     string?text,
     Font?font,
     Point pt,
     Color foreColor,
     Color backColor = default,
     User32.DT flags = User32.DT.DEFAULT)
 => DrawTextInternal(dc, text, font, new Rectangle(pt, WindowsGraphics.MaxSize), foreColor, backColor, flags);
Esempio n. 9
0
 public static void DrawText(
     this DeviceContextHdcScope hdc,
     string?text,
     FontCache.Scope font,
     Rectangle bounds,
     Color foreColor,
     User32.DT flags,
     Color backColor            = default,
     TextPaddingOptions padding = default)
 => DrawText(hdc.HDC, text, font, bounds, foreColor, flags, backColor, padding);
 public static extern HRESULT DrawThemeText(
     IntPtr hTheme,
     Gdi32.HDC hdc,
     int iPartId,
     int iStateId,
     string pszText,
     int iCharCount,
     User32.DT dwTextFlags,
     uint dwTextFlags2,
     ref RECT pRect);
Esempio n. 11
0
        public static void DrawString(Control context, Font font, string text, Rectangle textBounds, bool useMnemonics, GdiTextDrawMode textMode)
        {
            IntPtr hdc = User32.GetDC(context.Handle);

            try
            {
                Gdi32.SetBkColor(hdc, Gdi32.ToColorRef(context.BackColor));
                Gdi32.SetTextColor(hdc, Gdi32.ToColorRef(context.ForeColor));

                try
                {
                    IntPtr hFont = font.ToHfont();
                    try
                    {
                        IntPtr hPrevFont = Gdi32.SelectObject(hdc, hFont);
                        try
                        {
                            StringBuilder         sb       = new StringBuilder(text);
                            RECT                  rect     = textBounds;
                            User32.DRAWTEXTPARAMS dtparams = new User32.DRAWTEXTPARAMS();
                            dtparams.cbSize = (uint)Marshal.SizeOf(typeof(User32.DRAWTEXTPARAMS));
                            User32.DT flags =
                                textMode == GdiTextDrawMode.EndEllipsis ? User32.DT.END_ELLIPSIS
                                                                : textMode == GdiTextDrawMode.WordBreak ? User32.DT.WORDBREAK | User32.DT.END_ELLIPSIS
                                                                : User32.DT.WORDBREAK;
                            if (useMnemonics)
                            {
                                flags |= User32.DT.NOPREFIX;
                            }

                            if (0 == User32.DrawTextEx(hdc, sb, sb.Length, ref rect, flags, ref dtparams))
                            {
                                throw new Win32Exception(Marshal.GetLastWin32Error());
                            }
                        }
                        finally
                        {
                            Gdi32.SelectObject(hdc, hPrevFont);
                        }
                    }
                    finally
                    {
                        Gdi32.DeleteObject(hFont);
                    }
                }
                finally
                {
                }
            }
            finally
            {
                User32.ReleaseDC(context.Handle, hdc);
            }
        }
Esempio n. 12
0
        private static User32.DT GetTextFormatFlags(TextFormatFlags flags)
        {
            if (((uint)flags & WindowsGraphics.GdiUnsupportedFlagMask) == 0)
            {
                return((User32.DT)flags);
            }

            // Clear TextRenderer custom flags.
            User32.DT windowsGraphicsSupportedFlags = (User32.DT)(((uint)flags) & ~WindowsGraphics.GdiUnsupportedFlagMask);

            return(windowsGraphicsSupportedFlags);
        }
Esempio n. 13
0
        /// <summary>
        ///  Draws the text in the given bounds, using the given Font, foreColor and backColor, and according to the specified
        ///  TextFormatFlags flags.
        ///
        ///  If font is null, the font currently selected in the hdc is used.
        ///
        ///  If foreColor and/or backColor are Color.Empty, the hdc current text and/or background color are used.
        /// </summary>
        public static void DrawText(
            this Gdi32.HDC hdc,
            ReadOnlySpan <char> text,
            FontCache.Scope font,
            Rectangle bounds,
            Color foreColor,
            User32.DT flags,
            Color backColor            = default,
            TextPaddingOptions padding = default)
        {
            if (text.IsEmpty || foreColor == Color.Transparent)
            {
                return;
            }

            ValidateFlags(flags);

            // DrawText requires default text alignment.
            using var alignment = new Gdi32.SetTextAlignmentScope(hdc, default);

            // Color empty means use the one currently selected in the dc.
            using var textColor = foreColor.IsEmpty ? default : new Gdi32.SetTextColorScope(hdc, foreColor);
                                  using var fontSelection = new Gdi32.SelectObjectScope(hdc, (Gdi32.HFONT)font);

                                  Gdi32.BKMODE newBackGroundMode = (backColor.IsEmpty || backColor == Color.Transparent) ?
                                                                   Gdi32.BKMODE.TRANSPARENT :
                                                                   Gdi32.BKMODE.OPAQUE;

                                  using var backgroundMode  = new Gdi32.SetBkModeScope(hdc, newBackGroundMode);
                                  using var backgroundColor = newBackGroundMode != Gdi32.BKMODE.TRANSPARENT
                ? new Gdi32.SetBackgroundColorScope(hdc, backColor)
                : default;

                                  User32.DRAWTEXTPARAMS dtparams = GetTextMargins(font, padding);

                                  bounds = AdjustForVerticalAlignment(hdc, text, bounds, flags, ref dtparams);

                                  // Adjust unbounded rect to avoid overflow since Rectangle ctr does not do param validation.
                                  if (bounds.Width == TextRenderer.MaxSize.Width)
                                  {
                                      bounds.Width -= bounds.X;
                                  }

                                  if (bounds.Height == TextRenderer.MaxSize.Height)
                                  {
                                      bounds.Height -= bounds.Y;
                                  }

                                  RECT rect = bounds;

                                  User32.DrawTextExW(hdc, text, ref rect, flags, ref dtparams);
        }
Esempio n. 14
0
 internal static void DrawTextInternal(
     Gdi32.HDC hdc,
     string?text,
     Font?font,
     Rectangle bounds,
     Color foreColor,
     Gdi32.QUALITY fontQuality,
     Color backColor,
     User32.DT flags)
 {
     using var hfont = GdiCache.GetHFONT(font, fontQuality);
     hdc.DrawText(text, hfont, bounds, foreColor, flags, backColor);
 }
        public static HRESULT DrawThemeText(
            IHandle hTheme,
            Gdi32.HDC hdc,
            int iPartId,
            int iStateId,
            string pszText,
            int iCharCount,
            User32.DT dwTextFlags,
            uint dwTextFlags2,
            ref RECT pRect)
        {
            HRESULT hr = DrawThemeText(hTheme.Handle, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags2, ref pRect);

            GC.KeepAlive(hTheme);
            return(hr);
        }
Esempio n. 16
0
        private static User32.DT GetTextFormatFlags(TextFormatFlags flags, bool blockModifyString = false)
        {
            if (blockModifyString && flags.HasFlag(TextFormatFlags.ModifyString))
            {
                throw new ArgumentOutOfRangeException(nameof(flags), SR.TextFormatFlagsModifyStringNotAllowed);
            }

            if (((uint)flags & GdiUnsupportedFlagMask) == 0)
            {
                return((User32.DT)flags);
            }

            // Clear TextRenderer custom flags.
            User32.DT windowsGraphicsSupportedFlags = (User32.DT)((uint)flags & ~GdiUnsupportedFlagMask);

            return(windowsGraphicsSupportedFlags);
        }
        private static (User32.DT Flags, TextPaddingOptions Padding) SplitTextFormatFlags(TextFormatFlags flags)
        {
            if (((uint)flags & GdiUnsupportedFlagMask) == 0)
            {
                return((User32.DT)flags, TextPaddingOptions.GlyphOverhangPadding);
            }

            // Clear TextRenderer custom flags.
            User32.DT windowsGraphicsSupportedFlags = (User32.DT)((uint)flags & ~GdiUnsupportedFlagMask);

            TextPaddingOptions padding = flags.HasFlag(TextFormatFlags.LeftAndRightPadding)
                ? TextPaddingOptions.LeftAndRightPadding
                : flags.HasFlag(TextFormatFlags.NoPadding)
                    ? TextPaddingOptions.NoPadding
                    : TextPaddingOptions.GlyphOverhangPadding;

            return(windowsGraphicsSupportedFlags, padding);
        }
        /// <summary>
        ///  The GDI DrawText does not do multiline alignment when User32.DT.SINGLELINE is not set. This
        ///  adjustment is to workaround that limitation. We don't want to duplicate SelectObject calls here,
        ///  so put your Font in the dc before calling this.
        ///
        ///  AdjustForVerticalAlignment is only used when the text is multiline and it fits inside the bounds passed in.
        ///  In that case we want the horizontal center of the multiline text to be at the horizontal center of the bounds.
        ///
        ///  If the text is multiline and it does not fit inside the bounds passed in, then return the bounds that were passed in.
        ///  This way we paint the top of the text at the top of the bounds passed in.
        /// </summary>
        public static Rectangle AdjustForVerticalAlignment(
            this Gdi32.HDC hdc,
            ReadOnlySpan <char> text,
            Rectangle bounds,
            User32.DT flags,
            ref User32.DRAWTEXTPARAMS dtparams)
        {
            ValidateFlags(flags);

            // Ok if any Top (Cannot test User32.DT.Top because it is 0), single line text or measuring text.
            bool isTop = (flags & User32.DT.BOTTOM) == 0 && (flags & User32.DT.VCENTER) == 0;

            if (isTop || ((flags & User32.DT.SINGLELINE) != 0) || ((flags & User32.DT.CALCRECT) != 0))
            {
                return(bounds);
            }

            RECT rect = new RECT(bounds);

            // Get the text bounds.
            flags |= User32.DT.CALCRECT;
            int textHeight = User32.DrawTextExW(hdc, text, ref rect, flags, ref dtparams);

            // if the text does not fit inside the bounds then return the bounds that were passed in
            if (textHeight > bounds.Height)
            {
                return(bounds);
            }

            Rectangle adjustedBounds = bounds;

            if ((flags & User32.DT.VCENTER) != 0)
            {
                // Middle
                adjustedBounds.Y = adjustedBounds.Top + adjustedBounds.Height / 2 - textHeight / 2;
            }
            else
            {
                // Bottom
                adjustedBounds.Y = adjustedBounds.Bottom - textHeight;
            }

            return(adjustedBounds);
        }
Esempio n. 19
0
        private static Size MeasureTextInternal(
            ReadOnlySpan <char> text,
            Font?font,
            Size proposedSize,
            TextFormatFlags flags  = TextFormatFlags.Bottom,
            bool blockModifyString = false)
        {
            User32.DT drawTextFlags = GetTextFormatFlags(flags, blockModifyString);

            if (text.IsEmpty)
            {
                return(Size.Empty);
            }

            using var screen = GdiCache.GetScreenHdc();
            using var hfont  = GdiCache.GetHFONT(font, Gdi32.QUALITY.DEFAULT, screen);

            return(screen.HDC.MeasureText(text, hfont, proposedSize, drawTextFlags));
        }
Esempio n. 20
0
        /// <summary>
        ///  The GDI DrawText does not do multiline alignment when User32.DT.SINGLELINE is not set. This
        ///  adjustment is to workaround that limitation. We don't want to duplicate SelectObject calls here,
        ///  so put your Font in the dc before calling this.
        ///
        ///  AdjustForVerticalAlignment is only used when the text is multiline and it fits inside the bounds passed in.
        ///  In that case we want the horizontal center of the multiline text to be at the horizontal center of the bounds.
        ///
        ///  If the text is multiline and it does not fit inside the bounds passed in, then return the bounds that were passed in.
        ///  This way we paint the top of the text at the top of the bounds passed in.
        /// </summary>
        public static Rectangle AdjustForVerticalAlignment(
            HandleRef hdc,
            string text,
            Rectangle bounds,
            User32.DT flags,
            ref User32.DRAWTEXTPARAMS dtparams)
        {
            Debug.Assert(((uint)flags & GdiUnsupportedFlagMask) == 0, "Some custom flags were left over and are not GDI compliant!");

            // Ok if any Top (Cannot test User32.DT.Top because it is 0), single line text or measuring text.
            bool isTop = (flags & User32.DT.BOTTOM) == 0 && (flags & User32.DT.VCENTER) == 0;

            if (isTop || ((flags & User32.DT.SINGLELINE) != 0) || ((flags & User32.DT.CALCRECT) != 0))
            {
                return(bounds);
            }

            RECT rect = new RECT(bounds);

            // Get the text bounds.
            flags |= User32.DT.CALCRECT;
            int textHeight = User32.DrawTextExW(hdc, text, text.Length, ref rect, flags, ref dtparams);

            // if the text does not fit inside the bounds then return the bounds that were passed in
            if (textHeight > bounds.Height)
            {
                return(bounds);
            }

            Rectangle adjustedBounds = bounds;

            if ((flags & User32.DT.VCENTER) != 0)  // Middle
            {
                adjustedBounds.Y = adjustedBounds.Top + adjustedBounds.Height / 2 - textHeight / 2;
            }
            else // Bottom.
            {
                adjustedBounds.Y = adjustedBounds.Bottom - textHeight;
            }

            return(adjustedBounds);
        }
Esempio n. 21
0
        internal static void DrawTextInternal(
            PaintEventArgs e,
            string?text,
            Font?font,
            Rectangle bounds,
            Color foreColor,
            Color backColor = default,
            User32.DT flags = User32.DT.CENTER | User32.DT.VCENTER)
        {
            Gdi32.HDC hdc = e.HDC;
            if (hdc.IsNull)
            {
                // This MUST come before retreiving the HDC, which locks the Graphics object
                Gdi32.QUALITY quality = FontQualityFromTextRenderingHint(e.GraphicsInternal);

                using var graphicsHdc = new DeviceContextHdcScope(e.GraphicsInternal, applyGraphicsState: false);
                DrawTextInternal(graphicsHdc, text, font, bounds, foreColor, quality, backColor, flags);
            }
            else
            {
                DrawTextInternal(hdc, text, font, bounds, foreColor, _defaultQuality, backColor, flags);
            }
        }
Esempio n. 22
0
        /// <summary>
        ///  Returns the Size in logical units of the given text using the given Font, and according to the formatting flags.
        ///  The proposed size is used to create a bounding rectangle as follows:
        ///  - If there are multiple lines of text, DrawText uses the width of the rectangle pointed to by
        ///  the lpRect parameter and extends the base of the rectangle to bound the last line of text.
        ///  - If the largest word is wider than the rectangle, the width is expanded.
        ///  - If the text is less than the width of the rectangle, the width is reduced.
        ///  - If there is only one line of text, DrawText modifies the right side of the rectangle so that
        ///  it bounds the last character in the line.
        ///  If the font is null, the hdc's current font will be used.
        ///
        ///  Note for vertical fonts (if ever supported): DrawTextEx uses GetTextExtentPoint32 for measuring the text and this
        ///  function has the following limitation (from MSDN):
        ///  - This function assumes that the text is horizontal, that is, that the escapement is always 0. This is true for both
        ///  the horizontal and vertical measurements of the text.  The application must convert it explicitly.
        /// </summary>
        public Size MeasureText(string text, WindowsFont font, Size proposedSize, User32.DT flags)
        {
            Debug.Assert(((uint)flags & GdiUnsupportedFlagMask) == 0, "Some custom flags were left over and are not GDI compliant!");

            if (string.IsNullOrEmpty(text))
            {
                return(Size.Empty);
            }

            // DrawText returns a rectangle useful for aligning, but not guaranteed to encompass all
            // pixels (its not a FitBlackBox, if the text is italicized, it will overhang on the right.)
            // So we need to account for this.

#if OPTIMIZED_MEASUREMENTDC
            User32.DRAWTEXTPARAMS dtparams;
            // use the cache if we've got it
            if (MeasurementDCInfo.IsMeasurementDC(DeviceContext))
            {
                dtparams = MeasurementDCInfo.GetTextMargins(this, font);
            }
            else
            {
                dtparams = GetTextMargins(font);
            }
#else
            User32.DRAWTEXTPARAMS dtparams = GetTextMargins(font);
#endif

            // If Width / Height are < 0, we need to make them larger or DrawText will return
            // an unbounded measurement when we actually trying to make it very narrow.
            int minWidth = 1 + dtparams.iLeftMargin + dtparams.iRightMargin;

            if (proposedSize.Width <= minWidth)
            {
                proposedSize.Width = minWidth;
            }
            if (proposedSize.Height <= 0)
            {
                proposedSize.Height = 1;
            }

            var rect = new RECT(0, 0, proposedSize.Width, proposedSize.Height);
            if (font != null)
            {
                DeviceContext.SelectFont(font);
            }

            // If proposedSize.Height >= MaxSize.Height it is assumed bounds needed.  If flags contain SINGLELINE and
            // VCENTER or BOTTOM options, DrawTextEx does not bind the rectangle to the actual text height since
            // it assumes the text is to be vertically aligned; we need to clear the VCENTER and BOTTOM flags to
            // get the actual text bounds.
            if (proposedSize.Height >= MaxSize.Height && (flags & User32.DT.SINGLELINE) != 0)
            {
                // Clear vertical-alignment flags.
                flags &= ~(User32.DT.BOTTOM | User32.DT.VCENTER);
            }

            if (proposedSize.Width == MaxSize.Width)
            {
                // PERF: No constraining width means no word break.
                // in this case, we dont care about word wrapping - there should be enough room to fit it all
                flags &= ~(User32.DT.WORDBREAK);
            }

            flags |= User32.DT.CALCRECT;
            User32.DrawTextExW(DeviceContext.Hdc, text, text.Length, ref rect, flags, ref dtparams);

            return(rect.Size);
        }
Esempio n. 23
0
        /// <summary>
        ///  Draws the text in the given bounds, using the given Font, foreColor and backColor, and according to the specified
        ///  TextFormatFlags flags.
        ///
        ///  If font is null, the font currently selected in the hdc is used.
        ///
        ///  If foreColor and/or backColor are Color.Empty, the hdc current text and/or background color are used.
        /// </summary>
        public void DrawText(string text, WindowsFont font, Rectangle bounds, Color foreColor, Color backColor, User32.DT flags)
        {
            if (string.IsNullOrEmpty(text) || foreColor == Color.Transparent)
            {
                return;
            }

            Debug.Assert(((uint)flags & GdiUnsupportedFlagMask) == 0, "Some custom flags were left over and are not GDI compliant!");
            Debug.Assert((flags & User32.DT.CALCRECT) == 0, "CALCRECT flag is set, text won't be drawn");

            HandleRef hdc = new HandleRef(DeviceContext, DeviceContext.Hdc);

            // DrawText requires default text alignment.
            if (DeviceContext.TextAlignment != default)
            {
                DeviceContext.TextAlignment = default;
            }

            // color empty means use the one currently selected in the dc.

            if (!foreColor.IsEmpty && foreColor != DeviceContext.TextColor)
            {
                DeviceContext.TextColor = foreColor;
            }

            if (font != null)
            {
                DeviceContext.SelectFont(font);
            }

            Gdi32.BKMODE newBackGndMode = (backColor.IsEmpty || backColor == Color.Transparent) ?
                                          Gdi32.BKMODE.TRANSPARENT :
                                          Gdi32.BKMODE.OPAQUE;

            if (DeviceContext.BackgroundMode != newBackGndMode)
            {
                DeviceContext.SetBackgroundMode(newBackGndMode);
            }

            if (newBackGndMode != Gdi32.BKMODE.TRANSPARENT && backColor != DeviceContext.BackgroundColor)
            {
                DeviceContext.BackgroundColor = backColor;
            }

            User32.DRAWTEXTPARAMS dtparams = GetTextMargins(font);

            bounds = AdjustForVerticalAlignment(hdc, text, bounds, flags, ref dtparams);

            // Adjust unbounded rect to avoid overflow since Rectangle ctr does not do param validation.
            if (bounds.Width == MaxSize.Width)
            {
                bounds.Width -= bounds.X;
            }
            if (bounds.Height == MaxSize.Height)
            {
                bounds.Height -= bounds.Y;
            }

            var rect = new RECT(bounds);

            User32.DrawTextExW(hdc, text, text.Length, ref rect, flags, ref dtparams);

            // No need to restore previous objects into the dc (see comments on top of the class).
        }
Esempio n. 24
0
 /// <summary>
 ///  Draws the text in the given bounds, using the given Font and foreColor, and according to the specified flags.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Rectangle bounds, Color color, User32.DT flags)
 => DrawText(text, font, bounds, color, Color.Empty, flags);
Esempio n. 25
0
 /// <summary>
 ///  Draws the text at the specified point, using the given Font, foreColor and backColor, and according
 ///  to the specified flags.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, Color backColor, User32.DT flags)
 => DrawText(text, font, new Rectangle(pt, MaxSize), foreColor, backColor, flags);
Esempio n. 26
0
 /// <summary>
 ///  Draws the text at the specified point, using the given Font and foreColor, and according to the
 ///  specified flags.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, User32.DT flags)
 => DrawText(text, font, pt, foreColor, Color.Empty, flags);
 private static void ValidateFlags(User32.DT flags)
 {
     Debug.Assert(((uint)flags & GdiUnsupportedFlagMask) == 0,
                  "Some custom flags were left over and are not GDI compliant!");
 }