/// <summary> /// /// </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 measureGraphics = Graphics.FromHwnd(IntPtr.Zero)) { // first layout without size restriction to know html actual size htmlContainer.PerformLayout(measureGraphics); if (maxSize.Width > 0 && maxSize.Width < htmlContainer.ActualSize.Width) { // to allow the actual size be smaller than max we need to set max size only if it is really larger htmlContainer.MaxSize = new SizeF(maxSize.Width, 0); htmlContainer.PerformLayout(measureGraphics); } // restrict the final size by min/max var finalWidth = Math.Max(maxSize.Width > 0 ? Math.Min(maxSize.Width, (int)htmlContainer.ActualSize.Width) : (int)htmlContainer.ActualSize.Width, minSize.Width); // if the final width is larger than the actual we need to re-layout so the html can take the full given width. if (finalWidth > htmlContainer.ActualSize.Width) { htmlContainer.MaxSize = new SizeF(finalWidth, 0); htmlContainer.PerformLayout(measureGraphics); } var finalHeight = Math.Max(maxSize.Height > 0 ? Math.Min(maxSize.Height, (int)htmlContainer.ActualSize.Height) : (int)htmlContainer.ActualSize.Height, minSize.Height); return(new Size(finalWidth, finalHeight)); } }
/// <summary> /// Perform the layout of the html in the control. /// </summary> protected override void OnLayout(LayoutEventArgs levent) { if (_htmlContainer != null) { if (AutoSize) { _htmlContainer.MaxSize = SizeF.Empty; } else if (AutoSizeHeightOnly) { _htmlContainer.MaxSize = new SizeF(Width, 0); } else { _htmlContainer.MaxSize = Size; } using (Graphics g = CreateGraphics()) { _htmlContainer.PerformLayout(g); if (AutoSize || _autoSizeHight) { if (AutoSize) { Size = Size.Round(_htmlContainer.ActualSize); if (MaximumSize.Width > 0 && MaximumSize.Width < _htmlContainer.ActualSize.Width) { // to allow the actual size be smaller than max we need to set max size only if it is really larger _htmlContainer.MaxSize = MaximumSize; _htmlContainer.PerformLayout(g); Size = Size.Round(_htmlContainer.ActualSize); } else if (MinimumSize.Width > 0 && MinimumSize.Width > _htmlContainer.ActualSize.Width) { // if min size is larger than the actual we need to re-lyout so all 100% layouts will be correct _htmlContainer.MaxSize = new SizeF(MinimumSize.Width, 0); _htmlContainer.PerformLayout(g); Size = Size.Round(_htmlContainer.ActualSize); } } else if (_autoSizeHight) { Height = (int)_htmlContainer.ActualSize.Height; } } } } base.OnLayout(levent); }
/// <summary> /// Measure the size (width and height) required to draw the given html under given width and height restrictions.<br/> /// </summary> /// <param name="g">Device to use for measure</param> /// <param name="html">HTML source to render</param> /// <param name="maxWidth">optional: bound the width of the html to render in (default - 0, unlimited)</param> /// <param name="cssData">optiona: 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 size required for the html</returns> public static SizeF Measure(Graphics g, string html, float maxWidth, CssData cssData, EventHandler <HtmlStylesheetLoadEventArgs> stylesheetLoad, EventHandler <HtmlImageLoadEventArgs> imageLoad) { ArgChecker.AssertArgNotNull(g, "g"); SizeF actualSize = SizeF.Empty; if (!string.IsNullOrEmpty(html)) { var container = new HtmlContainer(); if (stylesheetLoad != null) { container.StylesheetLoad += stylesheetLoad; } if (imageLoad != null) { container.ImageLoad += imageLoad; } container.SetHtml(html, cssData); container.MaxSize = new SizeF(maxWidth, 0); container.PerformLayout(g); if (stylesheetLoad != null) { container.StylesheetLoad -= stylesheetLoad; } if (imageLoad != null) { container.ImageLoad -= imageLoad; } actualSize = container.ActualSize; } return(actualSize); }
/// <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 widht 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">optiona: the style to use for html rendering (default - use W3 default style)</param> /// <param name="bridge">optional: used to resolve external references in html code (property and method calls)</param> /// <returns>the actual size of the rendered html</returns> public static SizeF Render(Graphics g, string html, PointF location, SizeF maxSize, CssData cssData = null, object bridge = null) { ArgChecker.AssertArgNotNull(g, "g"); SizeF actualSize = SizeF.Empty; if (!string.IsNullOrEmpty(html)) { Region prevClip = null; if (maxSize.Height > 0) { prevClip = g.Clip; g.SetClip(new RectangleF(location, maxSize)); } var container = new HtmlContainer(html, bridge, cssData); container.Location = location; container.MaxSize = maxSize; container.PerformLayout(g); container.PerformPaint(g); if (prevClip != null) { g.SetClip(prevClip, CombineMode.Replace); } actualSize = container.ActualSize; } return(actualSize); }
/// <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> /// On tooltip appear set the html by the associated control, layout and set the tooltip size by the html size. /// </summary> private void OnToolTipPopup(object sender, PopupEventArgs e) { //Create fragment container var cssClass = string.IsNullOrEmpty(_tooltipCssClass) ? null : string.Format(" class=\"{0}\"", _tooltipCssClass); var toolipHtml = string.Format("<div{0}>{1}</div>", cssClass, GetToolTip(e.AssociatedControl)); _htmlContainer.SetHtml(toolipHtml, _baseCssData); _htmlContainer.MaxSize = MaximumSize; //Measure size of the container using (var g = e.AssociatedControl.CreateGraphics()) { _htmlContainer.PerformLayout(g); } //Set the size of the tooltip e.ToolTipSize = new Size((int)Math.Ceiling(_htmlContainer.ActualSize.Width), (int)Math.Ceiling(_htmlContainer.ActualSize.Height)); // start mouse handle timer if (_allowLinksHandling) { _associatedControl = e.AssociatedControl; _linkHandlingTimer.Start(); } }
/// <summary> /// Perform the layout of the html in the control. /// </summary> protected override void OnLayout(LayoutEventArgs levent) { if (_htmlContainer != null) { if (AutoSize) { _htmlContainer.MaxSize = MaximumSize; } else if (AutoSizeHeightOnly) { _htmlContainer.MaxSize = new SizeF(Width, 0); } else { _htmlContainer.MaxSize = Size; } using (Graphics g = CreateGraphics()) { _htmlContainer.PerformLayout(g); } if (AutoSize || _autoSizeHight) { if (AutoSize) { Size = Size.Round(_htmlContainer.ActualSize); if (MaximumSize.Width > 0 && MaximumSize.Width < Width) { Width = MaximumSize.Width; } if (MinimumSize.Width > 0 && MinimumSize.Width > Width) { Width = MinimumSize.Width; } } else if (_autoSizeHight) { Height = (int)_htmlContainer.ActualSize.Height; } if (MaximumSize.Height > 0 && MaximumSize.Height < Height) { Height = MaximumSize.Height; } if (MinimumSize.Height > 0 && MinimumSize.Height > Height) { Height = MinimumSize.Height; } } } base.OnLayout(levent); }
/// <summary> /// Perform html container layout by the current panel client size. /// </summary> private void PerformHtmlLayout() { if (_htmlContainer != null) { _htmlContainer.MaxSize = new SizeF(ClientSize.Width, 0); using (var g = CreateGraphics()) { _htmlContainer.PerformLayout(g); } AutoScrollMinSize = Size.Round(_htmlContainer.ActualSize); } }
/// <summary> /// Measure the size (width and height) required to draw the given html under given width and height restrictions.<br/> /// </summary> /// <param name="g">Device to use for measure</param> /// <param name="html">HTML source to render</param> /// <param name="maxWidth">optional: bound the width of the html to render in (default - 0, unlimited)</param> /// <param name="maxHeight">optional: bound the height of the html to render in (default - 0)</param> /// <param name="cssData">optiona: the style to use for html rendering (default - use W3 default style)</param> /// <param name="bridge">optional: used to resolve external references in html code (property, method calls)</param> /// <returns>the size required for the html</returns> public static SizeF Measure(Graphics g, string html, float maxWidth = 0, float maxHeight = 0, CssData cssData = null, object bridge = null) { ArgChecker.AssertArgNotNull(g, "g"); SizeF actualSize = SizeF.Empty; if (!string.IsNullOrEmpty(html)) { var container = new HtmlContainer(html, bridge, cssData); container.MaxSize = new SizeF(maxWidth, maxHeight); container.PerformLayout(g); actualSize = container.ActualSize; } return actualSize; }
/// <summary> /// Measure the size (width and height) required to draw the given html under given width and height restrictions.<br/> /// </summary> /// <param name="g">Device to use for measure</param> /// <param name="html">HTML source to render</param> /// <param name="maxWidth">optional: bound the width of the html to render in (default - 0, unlimited)</param> /// <param name="maxHeight">optional: bound the height of the html to render in (default - 0)</param> /// <param name="cssData">optiona: the style to use for html rendering (default - use W3 default style)</param> /// <param name="bridge">optional: used to resolve external references in html code (property, method calls)</param> /// <returns>the size required for the html</returns> public static SizeF Measure(Graphics g, string html, float maxWidth = 0, float maxHeight = 0, CssData cssData = null, object bridge = null) { ArgChecker.AssertArgNotNull(g, "g"); SizeF actualSize = SizeF.Empty; if (!string.IsNullOrEmpty(html)) { var container = new HtmlContainer(html, bridge, cssData); container.MaxSize = new SizeF(maxWidth, maxHeight); container.PerformLayout(g); actualSize = container.ActualSize; } return(actualSize); }
/// <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 widht 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">optiona: 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 actual size of the rendered html</returns> public static SizeF Render(Graphics g, string html, PointF location, SizeF maxSize, CssData cssData, EventHandler <HtmlStylesheetLoadEventArgs> stylesheetLoad, EventHandler <HtmlImageLoadEventArgs> imageLoad) { ArgChecker.AssertArgNotNull(g, "g"); SizeF actualSize = SizeF.Empty; if (!string.IsNullOrEmpty(html)) { Region prevClip = null; if (maxSize.Height > 0) { prevClip = g.Clip; g.SetClip(new RectangleF(location, maxSize)); } var container = new HtmlContainer(); if (stylesheetLoad != null) { container.StylesheetLoad += stylesheetLoad; } if (imageLoad != null) { container.ImageLoad += imageLoad; } container.SetHtml(html, cssData); container.Location = location; container.MaxSize = maxSize; container.PerformLayout(g); container.PerformPaint(g); if (stylesheetLoad != null) { container.StylesheetLoad -= stylesheetLoad; } if (imageLoad != null) { container.ImageLoad -= imageLoad; } if (prevClip != null) { g.SetClip(prevClip, CombineMode.Replace); } actualSize = container.ActualSize; } return(actualSize); }
private void OnToolTipPopup(object sender, PopupEventArgs e) { string text = GetToolTip(e.AssociatedControl); string font = string.Format(NumberFormatInfo.InvariantInfo, "font: {0}pt {1}", e.AssociatedControl.Font.Size, e.AssociatedControl.Font.FontFamily.Name); //Create fragment container var documentSource = "<div><table class=htmltooltipbackground cellspacing=5 cellpadding=0 style=\"" + font + "\"><tr><td style=border:0px>" + text + "</td></tr></table></div>"; _container = new HtmlContainer(documentSource, Bridge); _container.AvoidGeometryAntialias = true; //Measure bounds of the container using (Graphics g = e.AssociatedControl.CreateGraphics()) { _container.PerformLayout(g); } //Set the size of the tooltip e.ToolTipSize = new Size((int)Math.Round(_container.ActualSize.Width, MidpointRounding.AwayFromZero), (int)Math.Round(_container.ActualSize.Height, MidpointRounding.AwayFromZero)); }
/// <summary> /// Renders the specified HTML into image of unknown size that will be determined by max width/height and HTML layout.<br/> /// If <paramref name="maxWidth"/> 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="maxHeight"/> 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/> /// </summary> /// <param name="html">HTML source to render</param> /// <param name="maxWidth">the max width of the rendered html</param> /// <param name="maxHeight">optional: the max height of the rendered html, if above zero it will be clipped</param> /// <param name="cssData">optiona: 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 RenderToImage(string html, int maxWidth, int maxHeight = 0, CssData cssData = null, EventHandler<HtmlStylesheetLoadEventArgs> stylesheetLoad = null, EventHandler<HtmlImageLoadEventArgs> imageLoad = null) { if (string.IsNullOrEmpty(html)) return new Bitmap(0, 0, PixelFormat.Format32bppArgb); using (var htmlContainer = new HtmlContainer()) { // use desktop created graphics to measure the HTML using (var measureGraphics = Graphics.FromHwnd(IntPtr.Zero)) { if (stylesheetLoad != null) htmlContainer.StylesheetLoad += stylesheetLoad; if (imageLoad != null) htmlContainer.ImageLoad += imageLoad; htmlContainer.SetHtml(html, cssData); htmlContainer.PerformLayout(measureGraphics); if (maxWidth > 0 && maxWidth < htmlContainer.ActualSize.Width) { // to allow the actual size be smaller than max we need to set max size only if it is really larger htmlContainer.MaxSize = new SizeF(maxWidth, 0); htmlContainer.PerformLayout(measureGraphics); } } var size = new Size(maxWidth > 0 ? Math.Min(maxWidth, (int) htmlContainer.ActualSize.Width) : (int) htmlContainer.ActualSize.Width, maxHeight > 0 ? Math.Min(maxHeight, (int) htmlContainer.ActualSize.Height) : (int) htmlContainer.ActualSize.Height); // create the final image to render into by measured size var image = new Bitmap(size.Width, size.Height, PixelFormat.Format32bppArgb); // create memory buffer from desktop handle that supports alpha chanel 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(Color.White); htmlContainer.PerformPaint(memoryGraphics); } // copy from memory buffer to image using (var imageGraphics = Graphics.FromImage(image)) { var imgHdc = imageGraphics.GetHdc(); Win32Utils.BitBlt(imgHdc, 0, 0, image.Width, image.Height, memoryHdc, 0, 0, Win32Utils.BitBltCopy); imageGraphics.ReleaseHdc(imgHdc); } } finally { Win32Utils.ReleaseMemoryHdc(memoryHdc, dib); } return image; } }
/// <summary> /// Renders the specified HTML into image of the requested size.<br/> /// The HTML will be layout by the given size but will be clipped if cannot fit. /// </summary> /// <param name="html">HTML source to render</param> /// <param name="size">The size of the image to render into, layout html by width and clipped by height</param> /// <param name="cssData">optiona: 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 RenderToImage(string html, Size size, CssData cssData = null, EventHandler<HtmlStylesheetLoadEventArgs> stylesheetLoad = null, EventHandler<HtmlImageLoadEventArgs> imageLoad = null) { // create the final image to render into var image = new Bitmap(size.Width, size.Height, PixelFormat.Format32bppArgb); if (!string.IsNullOrEmpty(html)) { // create memory buffer from desktop handle that supports alpha chanel IntPtr dib; var memoryHdc = Win32Utils.CreateMemoryHdc(IntPtr.Zero, image.Width, image.Height, out dib); try { // create memory buffer graphics to use for HTML rendering using (var memoryGraphics = Graphics.FromHdc(memoryHdc)) { memoryGraphics.Clear(Color.White); // render HTML into the memory buffer using (var htmlContainer = new HtmlContainer()) { if (stylesheetLoad != null) htmlContainer.StylesheetLoad += stylesheetLoad; if (imageLoad != null) htmlContainer.ImageLoad += imageLoad; htmlContainer.SetHtml(html, cssData); htmlContainer.MaxSize = size; htmlContainer.PerformLayout(memoryGraphics); htmlContainer.PerformPaint(memoryGraphics); } } // copy from memory buffer to image using (var imageGraphics = Graphics.FromImage(image)) { var imgHdc = imageGraphics.GetHdc(); Win32Utils.BitBlt(imgHdc, 0, 0, image.Width, image.Height, memoryHdc, 0, 0, Win32Utils.BitBltCopy); imageGraphics.ReleaseHdc(imgHdc); } } 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 widht 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">optiona: 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 actual size of the rendered html</returns> public static SizeF Render(Graphics g, string html, PointF location, SizeF maxSize, CssData cssData, EventHandler<HtmlStylesheetLoadEventArgs> stylesheetLoad, EventHandler<HtmlImageLoadEventArgs> imageLoad) { ArgChecker.AssertArgNotNull(g, "g"); SizeF actualSize = SizeF.Empty; if (!string.IsNullOrEmpty(html)) { Region prevClip = null; if (maxSize.Height > 0) { prevClip = g.Clip; g.SetClip(new RectangleF(location, maxSize)); } using (var container = new HtmlContainer()) { if (stylesheetLoad != null) container.StylesheetLoad += stylesheetLoad; if (imageLoad != null) container.ImageLoad += imageLoad; container.SetHtml(html, cssData); container.Location = location; container.MaxSize = maxSize; container.PerformLayout(g); container.PerformPaint(g); if (prevClip != null) { g.SetClip(prevClip, CombineMode.Replace); } actualSize = container.ActualSize; } } return actualSize; }
/// <summary> /// Measure the size (width and height) required to draw the given html under given width and height restrictions.<br/> /// </summary> /// <param name="g">Device to use for measure</param> /// <param name="html">HTML source to render</param> /// <param name="maxWidth">optional: bound the width of the html to render in (default - 0, unlimited)</param> /// <param name="cssData">optiona: 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 size required for the html</returns> public static SizeF Measure(Graphics g, string html, float maxWidth, CssData cssData, EventHandler<HtmlStylesheetLoadEventArgs> stylesheetLoad, EventHandler<HtmlImageLoadEventArgs> imageLoad) { ArgChecker.AssertArgNotNull(g, "g"); SizeF actualSize = SizeF.Empty; if (!string.IsNullOrEmpty(html)) { using (var container = new HtmlContainer()) { if (stylesheetLoad != null) container.StylesheetLoad += stylesheetLoad; if (imageLoad != null) container.ImageLoad += imageLoad; container.SetHtml(html, cssData); container.MaxSize = new SizeF(maxWidth, 0); container.PerformLayout(g); actualSize = container.ActualSize; } } return actualSize; }
private void OnToolTipPopup(object sender, PopupEventArgs e) { string text = GetToolTip(e.AssociatedControl); string font = string.Format(NumberFormatInfo.InvariantInfo, "font: {0}pt {1}", e.AssociatedControl.Font.Size, e.AssociatedControl.Font.FontFamily.Name); //Create fragment container var documentSource = "<div><table class=htmltooltipbackground cellspacing=5 cellpadding=0 style=\"" + font + "\"><tr><td style=border:0px>" + text + "</td></tr></table></div>"; _container = new HtmlContainer(documentSource, Bridge); _container.AvoidGeometryAntialias = true; //Measure bounds of the container using (Graphics g = e.AssociatedControl.CreateGraphics()) { _container.PerformLayout(g); } //Set the size of the tooltip e.ToolTipSize = new Size((int) Math.Round(_container.ActualSize.Width, MidpointRounding.AwayFromZero), (int) Math.Round(_container.ActualSize.Height, MidpointRounding.AwayFromZero)); }
/// <summary> /// Perform the layout of the html in the control. /// </summary> protected override void OnLayout(LayoutEventArgs levent) { if (_htmlContainer != null) { if (AutoSize) { _htmlContainer.MaxSize = SizeF.Empty; } else if (AutoSizeHeightOnly) { _htmlContainer.MaxSize = new SizeF(ClientSize.Width, 0); } else { _htmlContainer.MaxSize = ClientSize; } using (Graphics g = CreateGraphics()) { _htmlContainer.PerformLayout(g); if (AutoSize || _autoSizeHight) { if (AutoSize) { ClientSize = Size.Round(_htmlContainer.ActualSize); if (MaximumSize.Width > 0 && MaximumSize.Width < _htmlContainer.ActualSize.Width) { // to allow the actual size be smaller than max we need to set max size only if it is really larger _htmlContainer.MaxSize = MaximumSize; _htmlContainer.PerformLayout(g); ClientSize = Size.Round(_htmlContainer.ActualSize); } else if (MinimumSize.Width > 0 && MinimumSize.Width > _htmlContainer.ActualSize.Width) { // if min size is larger than the actual we need to re-layout so all 100% layouts will be correct _htmlContainer.MaxSize = new SizeF(MinimumSize.Width, 0); _htmlContainer.PerformLayout(g); ClientSize = Size.Round(_htmlContainer.ActualSize); } } else if (_autoSizeHight && ClientSize.Height != (int)Math.Round(_htmlContainer.ActualSize.Height)) { var prevWidth = ClientSize.Width; // make sure the height is not lower than min if given var newHeight = MinimumSize.Height > 0 && MinimumSize.Height > _htmlContainer.ActualSize.Height ? MinimumSize.Height : (int)Math.Round(_htmlContainer.ActualSize.Height); ClientSize = new Size(ClientSize.Width, newHeight); // handle if changing the height of the label affects the desired width and those require re-layout if (prevWidth != ClientSize.Width) { OnLayout(levent); } } } } } base.OnLayout(levent); }
/// <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 widht 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">optiona: the style to use for html rendering (default - use W3 default style)</param> /// <param name="bridge">optional: used to resolve external references in html code (property and method calls)</param> /// <returns>the actual size of the rendered html</returns> public static SizeF Render(Graphics g, string html, PointF location, SizeF maxSize, CssData cssData = null, object bridge = null) { ArgChecker.AssertArgNotNull(g, "g"); SizeF actualSize = SizeF.Empty; if(!string.IsNullOrEmpty(html)) { Region prevClip = null; if (maxSize.Height > 0) { prevClip = g.Clip; g.SetClip(new RectangleF(location, maxSize)); } var container = new HtmlContainer(html, bridge, cssData); container.Location = location; container.MaxSize = maxSize; container.PerformLayout(g); container.PerformPaint(g); if (prevClip != null) { g.SetClip(prevClip, CombineMode.Replace); } actualSize = container.ActualSize; } return actualSize; }