/// <summary> /// Returns a rectangle based on the given IDisplayPointer /// </summary> /// <param name="element">The element that contains the display pointer</param> /// <param name="displayPointer"></param> /// <returns></returns> protected Rectangle GetLineRect(IHTMLElement element, IDisplayPointerRaw displayPointer) { ILineInfo lineInfo; displayPointer.GetLineInfo(out lineInfo); Rectangle elementRect = HTMLElementHelper.GetClientRectangle(element); //determine the rectangle based on the baseline and text height. //Note: baseline is relative to the parent element, and the text //height includes the textDescent, which is below the baseline int lineBottom = elementRect.Y + lineInfo.baseLine + lineInfo.textDescent; int lineTop = lineBottom - lineInfo.textHeight; int lineLeft = elementRect.X; int lineWidth = elementRect.Width; //Calculate the height of line. Since the bottom pixel line is shared by the next line, //we subtract 1 from the height. This height exactly matches height of the caret. //Note: this height adjustment fixes a bug that can occur with some text styles where a //caret placed on the next line is detected as being within this rectangle. int lineHeight = lineInfo.textHeight - 1; //create a rectangle that exactly fits the caret for this line //Note: this can be verified by painting a rectangle over the line using this rectangle return(new Rectangle(lineLeft, lineTop, lineWidth, lineHeight)); }
public static void TraceMoveToMarkupPointer(IDisplayPointerRaw displayPointer, MarkupPointer markupPointer) { try { if (displayPointer == null) throw new ArgumentException("Unexpected null display pointer."); if (markupPointer == null) throw new ArgumentException("Unexpected null markup pointer."); //position a display pointer on the same line as the markup pointer displayPointer.MoveToMarkupPointer(markupPointer.PointerRaw, null); } catch (Exception e) { Trace.Fail("Unexpected exception in TraceMoveToMarkupPointer: " + e.ToString()); throw; } }
public static void TraceMoveToMarkupPointer(IDisplayPointerRaw displayPointer, MarkupPointer markupPointer) { try { if (displayPointer == null) { throw new ArgumentException("Unexpected null display pointer."); } if (markupPointer == null) { throw new ArgumentException("Unexpected null markup pointer."); } //position a display pointer on the same line as the markup pointer displayPointer.MoveToMarkupPointer(markupPointer.PointerRaw, null); } catch (Exception e) { Trace.Fail("Unexpected exception in TraceMoveToMarkupPointer: " + e.ToString()); throw; } }
/// <summary> /// Positions the specified displayPointer at the specified clientPoint. /// </summary> /// <param name="displayPointer"></param> /// <param name="clientPoint"></param> protected void MoveDisplayPointerToClientPoint(IDisplayPointerRaw displayPointer, Point clientPoint) { POINT point = new POINT(); point.x = clientPoint.X; point.y = clientPoint.Y; // move the caret position display pointer to the point uint htRes; displayPointer.MoveToPoint( point, // point to move to _COORD_SYSTEM.COORD_SYSTEM_GLOBAL, // global (client area) coordinates null, // element coordinates are relative to (not used for GLOBAL) 0, // HT_OPTIONS (don't hit test beyond EOL) out htRes); // HT_RESULTS (1 indicates hit test is over a glyph) }
/// <summary> /// Move the caret to the location of the specified pointer. /// </summary> /// <param name="displayPointer"></param> /// <param name="select">if true, the selection will be explicitly driven to the new caret position. /// This ensures that all selection-driver components are displayed based on the new caret position (commands, etc)</param> public void SynchronizeCaretWithDisplayPointer(IDisplayPointerRaw displayPointer, bool select) { HtmlCaret.MoveCaretToPointerEx( displayPointer, // Display pointer to move caret to true, // Make caret visible true, // Auto-scroll to caret _CARET_DIRECTION.CARET_DIRECTION_SAME // Preserve direction of caret ); if (select) { //update the selection (collapse it to ensure that it doesn't span further than the caret) MarkupRange selection = SelectedMarkupRange; selection.Collapse(true); UpdateSelection(selection); //Avoid bug with caret placement: Updating the selection occasionally shifts the caret into another //position. This re-placement ensures that the caret is always placed correctly (even if the //selection known to MSHTML is slightly off) HtmlCaret.MoveCaretToPointerEx( displayPointer, // Display pointer to move caret to true, // Make caret visible true, // Auto-scroll to caret _CARET_DIRECTION.CARET_DIRECTION_SAME // Preserve direction of caret ); } }
protected virtual void AdjustDisplayPointerPosition(ref IDisplayPointerRaw displayPointer, Point fromClientPoint) { }
protected virtual void ResetForDocumentComplete() { htmlCaret = null; caretPositionDisplayPointer = null; }
/// <summary> /// Positions a DisplayPointer at the specified MarkupPointer. /// </summary> /// <param name="displayPointer"></param> /// <param name="p"></param> public void MoveDisplayPointerToMarkupPointer(IDisplayPointerRaw displayPointer, MarkupPointer p) { DisplayServices.TraceMoveToMarkupPointer(displayPointer, p); }
/// <summary> /// Make sure that the display pointer doesn't end up inside SmartContent, /// where the user can't edit anything anyway. If necessary, move the pointer /// to the left or right of the content depending on its position. /// </summary> /// <param name="displayPointer"></param> /// <param name="fromClientPoint"></param> protected override void AdjustDisplayPointerPosition(ref IDisplayPointerRaw displayPointer, Point fromClientPoint) { MarkupPointer tester = MarkupServices.CreateMarkupPointer(); displayPointer.PositionMarkupPointer(tester.PointerRaw); IHTMLElement el = GetSurroundingSmartContent(tester); if (el == null) return; int center = HTMLElementHelper.GetLeftRelativeToClient(el) + el.offsetWidth / 2; tester.MoveAdjacentToElement(el, (fromClientPoint.X < center) ? _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin : _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); DisplayServices.TraceMoveToMarkupPointer(displayPointer, tester); }
/// <summary> /// Returns a rectangle based on the given IDisplayPointer /// </summary> /// <param name="element">The element that contains the display pointer</param> /// <param name="displayPointer"></param> /// <returns></returns> protected Rectangle GetLineRect(IHTMLElement element, IDisplayPointerRaw displayPointer) { ILineInfo lineInfo; displayPointer.GetLineInfo(out lineInfo); Rectangle elementRect = HTMLElementHelper.GetClientRectangle(element); //determine the rectangle based on the baseline and text height. //Note: baseline is relative to the parent element, and the text //height includes the textDescent, which is below the baseline int lineBottom = elementRect.Y + lineInfo.baseLine + lineInfo.textDescent; int lineTop = lineBottom - lineInfo.textHeight; int lineLeft = elementRect.X; int lineWidth = elementRect.Width; //Calculate the height of line. Since the bottom pixel line is shared by the next line, //we subtract 1 from the height. This height exactly matches height of the caret. //Note: this height adjustment fixes a bug that can occur with some text styles where a //caret placed on the next line is detected as being within this rectangle. int lineHeight = lineInfo.textHeight - 1; //create a rectangle that exactly fits the caret for this line //Note: this can be verified by painting a rectangle over the line using this rectangle return new Rectangle(lineLeft, lineTop, lineWidth, lineHeight); }