/// <summary> /// Renders the specified HTML into a new image of unknown size that will be determined by min/max width/height and HTML layout.<br/> /// If <paramref name="maxSize.Width"/> is zero the html will use all the required width, otherwise it will perform line /// wrap as specified in the html<br/> /// If <paramref name="maxSize.Height"/> is zero the html will use all the required height, otherwise it will clip at the /// given max height not rendering the html below it.<br/> /// If <paramref name="minSize"/> (Width/Height) is above zero the rendered image will not be smaller than the given min size.<br/> /// The generated image have transparent background that the html is rendered on.<br/> /// GDI+ text rending can be controlled by providing <see cref="TextRenderingHint"/>.<br/> /// See "Rendering to image" remarks section on <see cref="HtmlRender"/>.<br/> /// </summary> /// <param name="html">HTML source to render</param> /// <param name="minSize">optional: the min size of the rendered html (zero - not limit the width/height)</param> /// <param name="maxSize">optional: the max size of the rendered html, if not zero and html cannot be layout within the limit it will be clipped (zero - not limit the width/height)</param> /// <param name="textRenderingHint">optional: (default - SingleBitPerPixelGridFit)</param> /// <param name="cssData">optional: the style to use for html rendering (default - use W3 default style)</param> /// <param name="stylesheetLoad">optional: can be used to overwrite stylesheet resolution logic</param> /// <param name="imageLoad">optional: can be used to overwrite image resolution logic</param> /// <returns>the generated image of the html</returns> public static Image RenderToImageGdiPlus(string html, Size minSize, Size maxSize, TextRenderingHint textRenderingHint = TextRenderingHint.AntiAlias, CssData cssData = null, EventHandler <HtmlStylesheetLoadEventArgs> stylesheetLoad = null, EventHandler <HtmlImageLoadEventArgs> imageLoad = null) { if (string.IsNullOrEmpty(html)) { return(new Bitmap(0, 0, PixelFormat.Format32bppArgb)); } using (var container = new HtmlContainer()) { container.AvoidAsyncImagesLoading = true; container.AvoidImagesLateLoading = true; container.UseGdiPlusTextRendering = true; if (stylesheetLoad != null) { container.StylesheetLoad += stylesheetLoad; } if (imageLoad != null) { container.ImageLoad += imageLoad; } container.SetHtml(html, cssData); var finalSize = MeasureHtmlByRestrictions(container, minSize, maxSize); container.MaxSize = finalSize; // create the final image to render into by measured size var image = new Bitmap(finalSize.Width, finalSize.Height, PixelFormat.Format32bppArgb); // render HTML into the image using (var g = Graphics.FromImage(image)) { g.TextRenderingHint = textRenderingHint; container.PerformPaint(g); } return(image); } }
/// <summary> /// Unsubscribe from events and dispose of <see cref="HtmlContainer"/>. /// </summary> protected virtual void OnToolTipDisposed(EventArgs e) { Popup -= OnToolTipPopup; Draw -= OnToolTipDraw; Disposed -= OnToolTipDisposed; if (HtmlContainer != null) { HtmlContainer.RenderError -= OnRenderError; HtmlContainer.StylesheetLoad -= OnStylesheetLoad; HtmlContainer.ImageLoad -= OnImageLoad; HtmlContainer.Dispose(); HtmlContainer = null; } #if !MONO if (_linkHandlingTimer != null) { _linkHandlingTimer.Dispose(); _linkHandlingTimer = null; if (HtmlContainer != null) HtmlContainer.LinkClicked -= OnLinkClicked; } #endif }
/// <summary> /// Init. /// </summary> public HtmlToolTip() { OwnerDraw = true; HtmlContainer = new HtmlContainer(); HtmlContainer.IsSelectionEnabled = false; HtmlContainer.IsContextMenuEnabled = false; HtmlContainer.AvoidGeometryAntialias = true; HtmlContainer.AvoidImagesLateLoading = true; HtmlContainer.RenderError += OnRenderError; HtmlContainer.StylesheetLoad += OnStylesheetLoad; HtmlContainer.ImageLoad += OnImageLoad; Popup += OnToolTipPopup; Draw += OnToolTipDraw; Disposed += OnToolTipDisposed; #if !MONO _linkHandlingTimer = new Timer(); _linkHandlingTimer.Tick += OnLinkHandlingTimerTick; _linkHandlingTimer.Interval = 40; HtmlContainer.LinkClicked += OnLinkClicked; #endif AutoPopDelay = 90000; InitialDelay = 300; }
/// <summary> /// Release the html container resources. /// </summary> protected override void Dispose(bool disposing) { if (_htmlContainer != null) { _htmlContainer.LinkClicked -= OnLinkClicked; _htmlContainer.BoxClicked -= OnBoxClicked; _htmlContainer.RenderError -= OnRenderError; _htmlContainer.Refresh -= OnRefresh; _htmlContainer.ScrollChange -= OnScrollChange; _htmlContainer.StylesheetLoad -= OnStylesheetLoad; _htmlContainer.ImageLoad -= OnImageLoad; _htmlContainer.Dispose(); _htmlContainer = null; } base.Dispose(disposing); }
/// <summary> /// Creates a new HtmlPanel and sets a basic css for it's styling. /// </summary> public HtmlPanel() { AutoScroll = true; BackColor = SystemColors.Window; DoubleBuffered = true; SetStyle(ControlStyles.ResizeRedraw, true); SetStyle(ControlStyles.SupportsTransparentBackColor, true); _htmlContainer = new HtmlContainer(); _htmlContainer.LinkClicked += OnLinkClicked; _htmlContainer.BoxClicked += OnBoxClicked; _htmlContainer.RenderError += OnRenderError; _htmlContainer.Refresh += OnRefresh; _htmlContainer.ScrollChange += OnScrollChange; _htmlContainer.StylesheetLoad += OnStylesheetLoad; _htmlContainer.ImageLoad += OnImageLoad; // subscribe to an event called when the BaseCss sheet changes YamuiThemeManager.OnCssSheetChanged += YamuiThemeManagerOnOnCssSheetChanged; }
/// <summary> /// Creates a new HTML Label /// </summary> public HtmlLabel() { SuspendLayout(); AutoSize = true; BackColor = SystemColors.Window; DoubleBuffered = true; SetStyle(ControlStyles.ResizeRedraw, true); SetStyle(ControlStyles.SupportsTransparentBackColor, true); SetStyle(ControlStyles.Opaque, false); _htmlContainer = new HtmlContainer(); _htmlContainer.AvoidImagesLateLoading = true; _htmlContainer.MaxSize = MaximumSize; _htmlContainer.LinkClicked += OnLinkClicked; _htmlContainer.RenderError += OnRenderError; _htmlContainer.Refresh += OnRefresh; _htmlContainer.StylesheetLoad += OnStylesheetLoad; _htmlContainer.ImageLoad += OnImageLoad; ResumeLayout(false); TabStop = false; // subscribe to an event called when the BaseCss sheet changes YamuiThemeManager.OnCssChanged += YamuiThemeManagerOnOnCssChanged; }
/// <summary> /// Renders the specified HTML into a new image of unknown size that will be determined by min/max width/height and HTML layout.<br/> /// If <paramref name="maxSize.Width"/> is zero the html will use all the required width, otherwise it will perform line /// wrap as specified in the html<br/> /// If <paramref name="maxSize.Height"/> is zero the html will use all the required height, otherwise it will clip at the /// given max height not rendering the html below it.<br/> /// If <paramref name="minSize"/> (Width/Height) is above zero the rendered image will not be smaller than the given min size.<br/> /// <p> /// Limitation: The image cannot have transparent background, by default it will be white.<br/> /// See "Rendering to image" remarks section on <see cref="HtmlRender"/>.<br/> /// </p> /// </summary> /// <param name="html">HTML source to render</param> /// <param name="minSize">optional: the min size of the rendered html (zero - not limit the width/height)</param> /// <param name="maxSize">optional: the max size of the rendered html, if not zero and html cannot be layout within the limit it will be clipped (zero - not limit the width/height)</param> /// <param name="backgroundColor">optional: the color to fill the image with (default - white)</param> /// <param name="cssData">optional: the style to use for html rendering (default - use W3 default style)</param> /// <param name="stylesheetLoad">optional: can be used to overwrite stylesheet resolution logic</param> /// <param name="imageLoad">optional: can be used to overwrite image resolution logic</param> /// <returns>the generated image of the html</returns> /// <exception cref="ArgumentOutOfRangeException">if <paramref name="backgroundColor"/> is <see cref="Color.Transparent"/></exception>. public static Image RenderToImage(string html, Size minSize, Size maxSize, Color backgroundColor = new Color(), CssData cssData = null, EventHandler<HtmlStylesheetLoadEventArgs> stylesheetLoad = null, EventHandler<HtmlImageLoadEventArgs> imageLoad = null) { if (backgroundColor == Color.Transparent) throw new ArgumentOutOfRangeException("backgroundColor", "Transparent background in not supported"); if (string.IsNullOrEmpty(html)) return new Bitmap(0, 0, PixelFormat.Format32bppArgb); using (var container = new HtmlContainer()) { container.AvoidAsyncImagesLoading = true; container.AvoidImagesLateLoading = true; if (stylesheetLoad != null) container.StylesheetLoad += stylesheetLoad; if (imageLoad != null) container.ImageLoad += imageLoad; container.SetHtml(html, cssData); var finalSize = MeasureHtmlByRestrictions(container, minSize, maxSize); container.MaxSize = finalSize; // create the final image to render into by measured size var image = new Bitmap(finalSize.Width, finalSize.Height, PixelFormat.Format32bppArgb); // create memory buffer from desktop handle that supports alpha channel IntPtr dib; var memoryHdc = Win32Utils.CreateMemoryHdc(IntPtr.Zero, image.Width, image.Height, out dib); try { // render HTML into the memory buffer using (var memoryGraphics = Graphics.FromHdc(memoryHdc)) { memoryGraphics.Clear(backgroundColor != Color.Empty ? backgroundColor : Color.White); container.PerformPaint(memoryGraphics); } // copy from memory buffer to image CopyBufferToImage(memoryHdc, image); } finally { Win32Utils.ReleaseMemoryHdc(memoryHdc, dib); } return image; } }
/// <summary> /// Renders the specified HTML source on the specified location and max size restriction.<br/> /// If <paramref name="maxSize"/>.Width is zero the html will use all the required width, otherwise it will perform line /// wrap as specified in the html<br/> /// If <paramref name="maxSize"/>.Height is zero the html will use all the required height, otherwise it will clip at the /// given max height not rendering the html below it.<br/> /// Returned is the actual width and height of the rendered html.<br/> /// </summary> /// <param name="g">Device to render with</param> /// <param name="html">HTML source to render</param> /// <param name="location">the top-left most location to start render the html at</param> /// <param name="maxSize">the max size of the rendered html (if height above zero it will be clipped)</param> /// <param name="cssData">optional: the style to use for html rendering (default - use W3 default style)</param> /// <param name="useGdiPlusTextRendering">true - use GDI+ text rendering, false - use GDI text rendering</param> /// <param name="stylesheetLoad">optional: can be used to overwrite stylesheet resolution logic</param> /// <param name="imageLoad">optional: can be used to overwrite image resolution logic</param> /// <returns>the actual size of the rendered html</returns> private static SizeF RenderHtml(Graphics g, string html, PointF location, SizeF maxSize, CssData cssData, bool useGdiPlusTextRendering, EventHandler<HtmlStylesheetLoadEventArgs> stylesheetLoad, EventHandler<HtmlImageLoadEventArgs> imageLoad) { SizeF actualSize = SizeF.Empty; if (!string.IsNullOrEmpty(html)) { using (var container = new HtmlContainer()) { container.Location = location; container.MaxSize = maxSize; container.AvoidAsyncImagesLoading = true; container.AvoidImagesLateLoading = true; container.UseGdiPlusTextRendering = useGdiPlusTextRendering; if (stylesheetLoad != null) container.StylesheetLoad += stylesheetLoad; if (imageLoad != null) container.ImageLoad += imageLoad; container.SetHtml(html, cssData); container.PerformLayout(g); container.PerformPaint(g); actualSize = container.ActualSize; } } return actualSize; }
/// <summary> /// Measure the size of the html by performing layout under the given restrictions. /// </summary> /// <param name="htmlContainer">the html to calculate the layout for</param> /// <param name="minSize">the minimal size of the rendered html (zero - not limit the width/height)</param> /// <param name="maxSize">the maximum size of the rendered html, if not zero and html cannot be layout within the limit it will be clipped (zero - not limit the width/height)</param> /// <returns>return: the size of the html to be rendered within the min/max limits</returns> private static Size MeasureHtmlByRestrictions(HtmlContainer htmlContainer, Size minSize, Size maxSize) { // use desktop created graphics to measure the HTML using (var g = Graphics.FromHwnd(IntPtr.Zero)) using (var mg = new GraphicsAdapter(g, htmlContainer.UseGdiPlusTextRendering)) { var sizeInt = HtmlRendererUtils.MeasureHtmlByRestrictions(mg, htmlContainer.HtmlContainerInt, Utils.Convert(minSize), Utils.Convert(maxSize)); return Utils.ConvertRound(sizeInt); } }
/// <summary> /// Renders the specified HTML into a new image of unknown size that will be determined by min/max width/height and HTML layout.<br/> /// If <paramref name="maxSize.Width"/> is zero the html will use all the required width, otherwise it will perform line /// wrap as specified in the html<br/> /// If <paramref name="maxSize.Height"/> is zero the html will use all the required height, otherwise it will clip at the /// given max height not rendering the html below it.<br/> /// If <paramref name="minSize"/> (Width/Height) is above zero the rendered image will not be smaller than the given min size.<br/> /// The generated image have transparent background that the html is rendered on.<br/> /// GDI+ text rending can be controlled by providing <see cref="TextRenderingHint"/>.<br/> /// See "Rendering to image" remarks section on <see cref="HtmlRender"/>.<br/> /// </summary> /// <param name="html">HTML source to render</param> /// <param name="minSize">optional: the min size of the rendered html (zero - not limit the width/height)</param> /// <param name="maxSize">optional: the max size of the rendered html, if not zero and html cannot be layout within the limit it will be clipped (zero - not limit the width/height)</param> /// <param name="textRenderingHint">optional: (default - SingleBitPerPixelGridFit)</param> /// <param name="cssData">optional: the style to use for html rendering (default - use W3 default style)</param> /// <param name="stylesheetLoad">optional: can be used to overwrite stylesheet resolution logic</param> /// <param name="imageLoad">optional: can be used to overwrite image resolution logic</param> /// <returns>the generated image of the html</returns> public static Image RenderToImageGdiPlus(string html, Size minSize, Size maxSize, TextRenderingHint textRenderingHint = TextRenderingHint.AntiAlias, CssData cssData = null, EventHandler<HtmlStylesheetLoadEventArgs> stylesheetLoad = null, EventHandler<HtmlImageLoadEventArgs> imageLoad = null) { if (string.IsNullOrEmpty(html)) return new Bitmap(0, 0, PixelFormat.Format32bppArgb); using (var container = new HtmlContainer()) { container.AvoidAsyncImagesLoading = true; container.AvoidImagesLateLoading = true; container.UseGdiPlusTextRendering = true; if (stylesheetLoad != null) container.StylesheetLoad += stylesheetLoad; if (imageLoad != null) container.ImageLoad += imageLoad; container.SetHtml(html, cssData); var finalSize = MeasureHtmlByRestrictions(container, minSize, maxSize); container.MaxSize = finalSize; // create the final image to render into by measured size var image = new Bitmap(finalSize.Width, finalSize.Height, PixelFormat.Format32bppArgb); // render HTML into the image using (var g = Graphics.FromImage(image)) { g.TextRenderingHint = textRenderingHint; container.PerformPaint(g); } return image; } }