public static void ClearBackgroundColor(MshtmlMarkupServices markupServices, MarkupRange selection) { HtmlStyleHelper htmlStyleHelper = new HtmlStyleHelper(markupServices); htmlStyleHelper.SplitInlineTags(selection.Start); htmlStyleHelper.SplitInlineTags(selection.End); IHTMLElement[] elements = selection.GetElements(ElementFilters.CreateTagIdFilter("font"), false); foreach (IHTMLElement element in elements) { element.style.backgroundColor = ""; } // We may now be left with empty font tags, e.g. <font>blah</font>. // After switching between editors this becomes <font size="+0">blah</font>, which // causes blah to be rendered differently. // To avoid that we need to remove any empty-attribute font tags. selection.RemoveElementsByTagId(_ELEMENT_TAG_ID.TAGID_FONT, true); }
public virtual string GetEditedHtml(bool useXhtml, bool doCleanup) { try { if (doCleanup || useXhtml) { MshtmlMarkupServices markupServices = new MshtmlMarkupServices(HTMLElement.document as IMarkupServicesRaw); if (doCleanup) { MarkupRange bodyRange = markupServices.CreateMarkupRange(((IHTMLDocument2)HTMLElement.document).body, false); bodyRange.RemoveElementsByTagId(_ELEMENT_TAG_ID.TAGID_FONT, true); } if (useXhtml) { MarkupRange bounds = markupServices.CreateMarkupRange(HTMLElement, false); string xhtml = FormattedHtmlPrinter.ToFormattedHtml(markupServices, bounds); return(doCleanup ? CleanupHtml(xhtml, true) : xhtml); } } } catch (Exception e) { // E.g. this failure case: <pre><b></pre></b> Trace.Fail("Exception generating XHTML: " + e.ToString()); } string html = HTMLElement.innerHTML ?? String.Empty; if (doCleanup) { return(CleanupHtml(html, false)); } else { return(html); } }
public static MarkupRange ApplyInlineTag(MshtmlMarkupServices markupServices, _ELEMENT_TAG_ID tagId, string attributes, MarkupRange selection, bool toggle) { HtmlStyleHelper htmlStyleHelper = new HtmlStyleHelper(markupServices); // Aligning the with the behavior of Word, we will make <SUP> and <SUB> mutually exclusive. // That is, if you are applying <SUB> to a selection that has <SUP> applied already, we will first remove the <SUP>, and vice versa. // Wait, if empty and we're on the very end of the already existing formatting, then we just want to jump out and apply... MarkupRange selectionToApply = selection.Clone(); if (toggle) { // If already entirely inside the tag // If empty and just inside of the closing tag, then jump outside the closing tag // Else remove the tag // If already entirely outside the tag // If empty, apply the tag and put selection inside // If non-empty, then apply tag and reselect // If partially inside the tag // Remove the tag _ELEMENT_TAG_ID mutuallyExclusiveTagId = _ELEMENT_TAG_ID.TAGID_NULL; switch (tagId) { case _ELEMENT_TAG_ID.TAGID_SUP: mutuallyExclusiveTagId = _ELEMENT_TAG_ID.TAGID_SUB; break; case _ELEMENT_TAG_ID.TAGID_SUB: mutuallyExclusiveTagId = _ELEMENT_TAG_ID.TAGID_SUP; break; default: break; } if (selection.IsEmpty()) { // If the selection is empty and we're just inside the tagId closing tag (meaning that there is no text before the closing tag), // then we just hop outside of the tagId closing tag. bool exitScopeMatchesTagIdToBeApplied; MarkupPointer pointerOutsideTagIdScope = htmlStyleHelper.NextExitScopeWithoutInterveningText(selection, tagId, mutuallyExclusiveTagId, out exitScopeMatchesTagIdToBeApplied); if (pointerOutsideTagIdScope != null) { selectionToApply = markupServices.CreateMarkupRange(pointerOutsideTagIdScope, pointerOutsideTagIdScope); if (exitScopeMatchesTagIdToBeApplied) { return(selectionToApply); } // else we still need to apply tagId } } // If a mutually exclusive tag is applied, then remove it. if (selectionToApply.IsTagId(mutuallyExclusiveTagId, true)) { selectionToApply.RemoveElementsByTagId(mutuallyExclusiveTagId, false); } // If this tag is already applied, then remove it and return. if (selectionToApply.IsTagId(tagId, true)) { selectionToApply.RemoveElementsByTagId(tagId, false); return(selectionToApply); } } return(htmlStyleHelper.ApplyInlineTag(tagId, attributes, selectionToApply)); }